Класс StackedInline

Класс StackedInline применяется в административной панели Django для создания встраиваемых форм связанных моделей. Он наследуется от InlineModelAdmin и отображает связанные объекты в виде вертикального списка полей. Основные параметры: model - связанная модель, extra - количество пустых форм для добавления, fk_name - имя внешнего ключа, если их несколько.

Синтаксис

pythonfrom django.contrib import admin
from .models import ParentModel, ChildModel

class ChildModelInline(admin.StackedInline):
  model = ChildModel
  extra = 1

class ParentModelAdmin(admin.ModelAdmin):
  inlines = [ChildModelInline]

admin.site.register(ParentModel, ParentModelAdmin)

Пример

Рассмотрим модели Author и Book, где один автор может иметь много книг. Используем StackedInline для редактирования книг на странице автора:

pythonfrom django.db import models

class Author(models.Model):
  name = models.CharField(max_length=100)
  email = models.EmailField()

  def __str__(self):
    return self.name

class Book(models.Model):
  title = models.CharField(max_length=200)
  author = models.ForeignKey(Author, on_delete=models.CASCADE)
  published_date = models.DateTimeField()
  is_bestseller = models.BooleanField(default=False)

  def __str__(self):
    return self.title

Теперь создадим встраиваемый класс в админке:

pythonfrom django.contrib import admin
from .models import Author, Book

class BookInline(admin.StackedInline):
  model = Book
  extra = 2
  fields = ['title', 'published_date', 'is_bestseller']

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
  list_display = ['name', 'email']
  inlines = [BookInline]

В результате на странице редактирования автора будет отображаться форма для добавления и редактирования книг. Параметр extra=2 добавит две пустые формы для новых книг.

Пример . С несколькими внешними ключами

Если модель имеет несколько внешних ключей на одну и ту же родительскую модель, используйте параметр fk_name для указания нужного поля:

pythonfrom django.db import models

class User(models.Model):
  username = models.CharField(max_length=50)

class Transaction(models.Model):
  sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sent_transactions')
  receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='received_transactions')
  amount = models.IntegerField()
pythonfrom django.contrib import admin
from .models import User, Transaction

class SentTransactionInline(admin.StackedInline):
  model = Transaction
  fk_name = 'sender'
  extra = 1

class ReceivedTransactionInline(admin.StackedInline):
  model = Transaction
  fk_name = 'receiver'
  extra = 1

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
  inlines = [SentTransactionInline, ReceivedTransactionInline]

Этот код создает два отдельных набора встраиваемых форм: один для отправленных транзакций, другой для полученных.

Настройка отображения полей

Можно настроить отображение полей с помощью атрибутов fields, fieldsets или exclude. Также доступны readonly_fields для полей только для чтения:

pythonfrom django.contrib import admin
from .models import Category, Product

class ProductInline(admin.StackedInline):
  model = Product
  fields = ['name', 'price', 'created_at']
  readonly_fields = ['created_at']
  extra = 1

@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
  inlines = [ProductInline]

Смотрите также

  • класс TabularInline,
    который отображает связанные объекты в виде таблицы
  • класс ModelAdmin,
    который определяет интерфейс администрирования модели
  • декоратор admin.register,
    который регистрирует модель в админке
  • атрибут inlines,
    который подключает встраиваемые классы к ModelAdmin