Якщо порівняти роботу з моделлю в адмінці з керуванням автомобілем, то реєстрація моделі через 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 = 'Опубліковано нещодавно?' # Налаштування заголовка стовпця
# 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)
Тепер наша адмінка не лише функціональна, але й добре кастомізована під задачі управління книгами!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ