← К оглавлению урока

💻 Примеры: Инлайн-формы и Admin Actions

⚡ Ключевые примеры

# models.py
class Publisher(models.Model):
    name = models.CharField(max_length=100)
    established_date = models.DateField()
    def __str__(self): return self.name

class Book(models.Model):
    title = models.CharField(max_length=200)
    publisher = models.ForeignKey(
        Publisher, on_delete=models.CASCADE, null=True, blank=True
    )

# admin.py — TabularInline
class BookInline(admin.TabularInline):
    model = Book
    extra = 1

@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    inlines = [BookInline]

Пример 1: Модели Publisher и Book

Из лекции: создаём модель Publisher и добавляем ForeignKey в Book.

# models.py
from django.db import models


class Publisher(models.Model):  # NEW MODEL
    name = models.CharField(max_length=100)
    established_date = models.DateField()

    def __str__(self):
        return self.name


class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"


class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    published_date = models.DateField()
    publisher = models.ForeignKey(
        Publisher,
        on_delete=models.CASCADE,
        null=True,
        blank=True
    )  # NEW FIELD

    def __str__(self):
        return f"{self.title} by {self.author}"

    class Meta:
        ordering = ['title']

После изменения моделей — обязательно выполнить миграции:

python manage.py makemigrations
python manage.py migrate

Пример 2: TabularInline (из лекции)

Минимальная настройка — книги отображаются в табличном формате на странице издательства.

# admin.py
from django.contrib import admin
from .models import Book, Publisher


class BookInline(admin.TabularInline):
    model = Book
    extra = 1  # 1 пустая строка для новой книги


class PublisherAdmin(admin.ModelAdmin):
    inlines = [BookInline]


admin.site.register(Publisher, PublisherAdmin)
admin.site.register(Book)
Результат: при открытии страницы редактирования Publisher в Admin, внизу страницы появится секция «Books» с табличной формой для добавления/редактирования книг.

Пример 3: StackedInline (из лекции)

Тот же результат, но каждая книга отображается отдельным блоком:

class BookInline(admin.StackedInline):
    model = Book
    extra = 1


class PublisherAdmin(admin.ModelAdmin):
    inlines = [BookInline]


admin.site.register(Publisher, PublisherAdmin)
admin.site.register(Book)

Пример 4: Расширенная настройка Inline

Современный стиль с @admin.register и дополнительными атрибутами:

from django.contrib import admin
from .models import Book, Publisher


class BookInline(admin.TabularInline):
    model = Book
    extra = 1
    max_num = 20
    fields = ['title', 'published_date']
    readonly_fields = []
    can_delete = True
    show_change_link = True  # ссылка на отдельную страницу книги


@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    inlines = [BookInline]
    list_display = ['name', 'established_date']
    search_fields = ['name']


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'publisher', 'published_date']
    search_fields = ['title', 'author__first_name']
    list_filter = ['publisher']

Пример 5: Admin Action — обновление поля (из лекции)

Сначала добавим поле created_at к модели Book:

# models.py — добавляем поле
class Book(models.Model):
    ...
    created_at = models.DateTimeField(null=True, blank=True)  # NEW FIELD
python manage.py makemigrations
python manage.py migrate

Теперь создаём action для массового обновления поля created_at:

# admin.py
from django.contrib import admin
from django.utils import timezone
from .models import Book, Publisher


class BookInline(admin.TabularInline):
    model = Book
    extra = 1


@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    inlines = [BookInline]


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'created_at']

    def update_created_at(self, request, queryset):
        queryset.update(created_at=timezone.now())

    update_created_at.short_description = "Update created_at to current time"

    actions = [update_created_at]
Как использовать Action:
  1. Открыть список Book в Admin
  2. Отметить нужные книги чекбоксами
  3. В выпадающем списке «Action» выбрать «Update created_at to current time»
  4. Нажать «Go»

Пример 6: Action с декоратором @admin.action (Django 3.2+)

Современный способ задать short_description через декоратор:

from django.contrib import admin
from django.utils import timezone


@admin.action(description="Установить created_at = сейчас")
def update_created_at(modeladmin, request, queryset):
    queryset.update(created_at=timezone.now())


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    actions = [update_created_at]
⚠️ Проверить по документации: декоратор @admin.action доступен с Django 3.2. В Django 5.x — рекомендуемый способ.

Пример 7: Несколько Inline на одной странице

Можно добавить сразу несколько Inline-классов к одному ModelAdmin:

class ReviewInline(admin.TabularInline):
    model = Review
    extra = 0  # не показывать пустые строки
    max_num = 5

class BookInline(admin.TabularInline):
    model = Book
    extra = 1

@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    inlines = [BookInline, ReviewInline]  # оба Inline