Если сравнить работу с моделью в админке с управлением автомобилем, то регистрация модели через admin.site.register() — это как ехать на автомобиле без руля. Вы можете только ехать прямо, но не можете повернуть. А вот ModelAdmin — это ваш руль. Он предоставляет полный набор настроек для:
- управления тем, какие поля отображаются в списках объектов;
- организации внешнего вида формы редактирования объектов;
- добавления функциональности, например, фильтров, поиска, сортировки и действий над объектами.
Давайте разберемся, как настроить ModelAdmin для наших моделей и начать рулить интерфейсом админа!
Основы создания ModelAdmin
ModelAdmin — это класс, который связывается с моделью и позволяет переопределять её поведение в админ-зоне. Начнем с создания простой модели и привязки её к кастомизированному ModelAdmin.
Создадим модель для управления книгами в библиотеке:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()
isbn_number = models.CharField(max_length=13, unique=True)
genre = models.CharField(max_length=50)
def __str__(self):
return self.title
Контролировать работу модели через админ-зону мы будем с помощью класса ModelAdmin. Для этого создадим отдельный класс и зарегистрируем его:
# admin.py
from django.contrib import admin
from .models import Book
class BookAdmin(admin.ModelAdmin):
pass # Пока ничего не настраиваем
admin.site.register(Book, BookAdmin)
После регистрации модель будет доступна в админке, но что если нам нужно изменить отображение полей или поведение?
Использование атрибутов ModelAdmin
list_display: для отображения полей в списке объектов
По умолчанию в списке объектов Django Admin отображает только строковое представление модели (то, что возвращает метод __str__). Вы можете точно указать, какие поля хотите видеть.
# admin.py
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date', 'isbn_number')
Теперь в списке книг будут видны все указанные поля. Поля можно настраивать под любые нужды, например, добавить метод, который вычисляет что-то на основе данных модели:
# models.py
class Book(models.Model):
# ... всё как раньше
def is_recent(self):
return self.published_date.year > 2000
is_recent.short_description = 'Published Recently?' # Настройка заголовка столбца
# admin.py
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date', 'is_recent')
list_filter: добавление фильтров
Если количество записей велико, фильтры помогут быстро находить нужные данные. Мы можем добавить фильтры для любых полей модели.
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date')
list_filter = ('author', 'genre', 'published_date')
Теперь в правой части экрана появятся фильтры, благодаря которым можно мгновенно отсортировать книги по авторам, жанрам или датам.
search_fields: настройка поиска
Поиск позволяет выполнять фильтрацию по заданным полям. Будем искать книги по названию и автору:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date')
list_filter = ('genre',)
search_fields = ('title', 'author')
Теперь в верхней части админки появится строка поиска. Вводите название или имя автора, и Django найдет совпадения.
- Сортировка объектов:
ordering
Допустим, вы хотите, чтобы книги в списке отображались по дате издания в обратном порядке. Это легко настроить:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date')
ordering = ('-published_date',) # Сортировка по убыванию даты
readonly_fields: защита полей от редактирования
Если нужно запретить изменение определённых полей, используйте readonly_fields:
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'isbn_number')
readonly_fields = ('isbn_number',) # Поле ISBN будет только для чтения
Теперь в форме редактирования поле ISBN будет заблокировано для изменения.
- Настройка формы редактирования:
fieldsиfieldsets
Форма редактирования объекта может быть упорядочена согласно вашему предпочтению. Это делается с помощью атрибута fields или fieldsets.
class BookAdmin(admin.ModelAdmin):
fields = ('title', 'author', 'published_date', 'genre', 'isbn_number')
Если же хочется сгруппировать поля в логические блоки, используйте fieldsets:
class BookAdmin(admin.ModelAdmin):
fieldsets = (
('Основная информация', {
'fields': ('title', 'author', 'genre')
}),
('Дополнительная информация', {
'fields': ('published_date', 'isbn_number'),
'classes': ('collapse',), # Раздел можно свернуть
}),
)
Методы ModelAdmin для более глубоких кастомизаций
Иногда статичных атрибутов недостаточно, и мы хотим кастомизировать поведение админ-зоны. ModelAdmin предоставляет методы, которые можно переопределить.
get_queryset: изменение списка объектов
Вы можете настроить, какие объекты отображать в списке:
class BookAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
# Показываем только книги, изданные в 21 веке
return qs.filter(published_date__year__gte=2000)
save_model: действия при сохранении объекта
Этот метод позволяет выполнить действия при сохранении объекта в админке:
class BookAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
if not change: # Если это новый объект
obj.title = obj.title.upper() # Автоматически переводим название в верхний регистр
super().save_model(request, obj, form, change)
Полный пример BookAdmin
Теперь объединим всё, что мы узнали, в одном классе:
# admin.py
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date', 'is_recent')
list_filter = ('genre', 'published_date')
search_fields = ('title', 'author')
ordering = ('-published_date',)
readonly_fields = ('isbn_number',)
fieldsets = (
('Основная информация', {
'fields': ('title', 'author', 'genre')
}),
('Дополнительная информация', {
'fields': ('published_date', 'isbn_number'),
'classes': ('collapse',), # Раздел можно свернуть
}),
)
def get_queryset(self, request):
qs = super().get_queryset(request)
# Показываем только книги с жанром "фантастика"
return qs.filter(genre='фантастика')
def save_model(self, request, obj, form, change):
if not change: # Если это новая книга
obj.title = obj.title.upper()
super().save_model(request, obj, form, change)
admin.site.register(Book, BookAdmin)
Теперь наша админка не только функциональная, но и хорошо кастомизирована под задачи управления книгами!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ