Admin Stacked Inline and Tabular Inline Django.How

Author avatar wrote on 07/06/2022

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)