Both allow you to edit models on the same page as a parent model.
In other words, it is sometimes preferable for a user to have the possibility to edit a certain model
while editing another one instead of having to manually add another instance somewhere else in your interface.
The difference is Layout
TabularInline
class GlossaryTermLanguageInline(admin.TabularInline):
model = GlossaryTermLanguage
fk_name = 'segment' # must add if more than 1 FK
# exclude = ("e",) # optional
# list_display = ('pk', 'name')
# readonly_fields = ('id',)
# can_delete = False
# classes = ['collapse']
# verbose_name_plural = 'Translation Files'
class GlossaryTermAdmin(admin.ModelAdmin):
inlines = [GlossaryTermLanguageInline]
admin.site.register(GlossaryTerm, GlossaryTermAdmin)
Another example
from django.contrib import admin
from .models import Question, Choice
class ChoiceInline(admin.TabularInline):
model = Choice
extra = 3
class QuestionAdmin(admin.ModelAdmin):
fieldsets = [(None, {'fields': ['question_text']}),
('Data Information', {'fields': ['pub_date'], 'classes': ['collapse']}),]
inlines = [ChoiceInline]
admin.site.register(Question, QuestionAdmin)
StackedInline
class FileTranslationInline(admin.StackedInline):
model = FileTranslation
list_display = ('pk', 'name')
readonly_fields = ('id',)
can_delete = False
classes = ['collapse']
verbose_name_plural = 'Translation Files'
fk_name = 'source_file'
class FileStatisticsInline(admin.StackedInline):
model = FileStatistics
classes = ['collapse']
fk_name = 'source_file'
class FileAdmin(admin.ModelAdmin):
inlines = (FileTranslationInline, FileStatisticsInline)
admin.site.register(File, FileAdmin)
Inline Many to Many Objects in Django Admin
You should link to the same class.M2M_field.through, this works for both Stacked Inline and Tabular Inline
models.py
class User(models.Model):
....
class Project(models.Model):
users = models.ManyToManyField(User, blank=True)
...
admin.py
Pay attention to model = Project.users.through
class UserInline(admin.StackedInline):
model = Project.users.through
classes = ['collapse']
verbose_name_plural = 'users'
fk_name = 'project'
class ProjectAdmin(admin.ModelAdmin):
inlines = (UserInline,)
def get_inline_instances(self, request, obj=None):
if not obj:
return list()
return super(ProjectAdmin, self).get_inline_instances(request, obj)
model = Project
admin.site.register(Project, ProjectAdmin)