Django Admin: полное руководство по админке Django
Как включить админку Django, создать суперпользователя, зарегистрировать модели и настроить ModelAdmin: списки, фильтры, поиск, инлайны и действия.
Содержание · 12 разделов
- Как включить админку Django
- Как создать суперпользователя
- Русский язык интерфейса
- Регистрация моделей в админке
- Настройка списка объектов (changelist)
- Вычисляемые колонки и @admin.display
- Редактирование прямо в списке
- Свой фильтр: SimpleListFilter
- Настройка формы редактирования
- Порядок и группировка полей
- Большие связанные таблицы: autocomplete_fields
- Инлайны: связанные объекты на одной странице
- Действия над выбранными записями (admin actions)
- Права доступа
- Оформление: заголовки и тема
- Частые проблемы
- Админка без стилей после деплоя
- «CSRF verification failed» при входе
- Модель не появилась в админке
- Список открывается медленно
- Частые вопросы
- Как сделать поле необязательным в форме админки?
- Как убрать «Группы» или другую встроенную модель из админки?
- Можно ли дать доступ к админке клиентам сайта?
- Почему после ввода верного пароля снова открывается форма входа?
- Как выводить в админке картинку или ссылку?
- Как узнать, кто изменил запись?
- Чек-лист настройки админки
Django Admin — встроенная в Django панель администратора: по описанию моделей она строит интерфейс для просмотра, поиска, создания и редактирования записей в базе данных. Для внутренних инструментов, бэк-офиса и модерации контента это часто самый быстрый способ получить рабочий интерфейс без единой строки фронтенда.
В руководстве разберём весь путь: от включения админки и создания суперпользователя до тонкой настройки ModelAdmin, прав доступа и типичных проблем в продакшне. Примеры рассчитаны на Django 5.2 LTS и 6.x.
Как включить админку Django
В проекте, созданном командой startproject, админка уже подключена. Если вы начинаете с нуля (подробнее — в статьях «Как установить Django» и «Как создать проект Django»):
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install django
django-admin startproject config .
python manage.py migrate
Проверьте, что в settings.py есть приложения, от которых зависит админка:
# settings.py
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# ваши приложения
"library",
]
И что маршрут админки объявлен в корневом urls.py:
# config/urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path("admin/", admin.site.urls),
]
Совет: в продакшне замените
admin/на неочевидный путь. От целевой атаки смена пути не защитит, зато отсечёт массовые сканеры. Полноценная защита — в статье «Защита Admin URL».
Как создать суперпользователя
Войти в админку может только пользователь с флагом is_staff. Первого администратора создают командой createsuperuser — Django спросит имя, email и пароль:
python manage.py createsuperuser
Неинтерактивный режим для Docker и CI, смена забытого пароля через changepassword и типичные ошибки разобраны в отдельной статье «Как создать суперпользователя в Django».
Теперь запустите сервер разработки и откройте http://127.0.0.1:8000/admin/:
python manage.py runserver
Русский язык интерфейса
Админка переведена на русский. Достаточно указать язык и часовой пояс:
# settings.py
LANGUAGE_CODE = "ru"
TIME_ZONE = "Europe/Moscow"
USE_I18N = True
USE_TZ = True
Регистрация моделей в админке
Возьмём небольшое приложение «библиотека»:
# library/models.py
from django.db import models
class Author(models.Model):
name = models.CharField("Имя", max_length=200)
class Meta:
verbose_name = "автор"
verbose_name_plural = "авторы"
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField("Название", max_length=300)
slug = models.SlugField(unique=True)
author = models.ForeignKey(Author, on_delete=models.PROTECT, related_name="books")
published = models.DateField("Дата выхода")
is_available = models.BooleanField("В наличии", default=True)
price = models.DecimalField("Цена", max_digits=8, decimal_places=2)
class Meta:
verbose_name = "книга"
verbose_name_plural = "книги"
def __str__(self):
return self.title
Обратите внимание на verbose_name и __str__: админка использует их в заголовках, меню и выпадающих списках. Без __str__ записи будут отображаться как Book object (1). Поля, Meta и choices подробно разобраны в статье «Модели в Django».
Самый короткий способ зарегистрировать модель:
# library/admin.py
from django.contrib import admin
from .models import Author, Book
admin.site.register(Author)
admin.site.register(Book)
На практике почти всегда нужен собственный класс ModelAdmin. Регистрировать его удобнее декоратором (снятие регистрации, своя AdminSite и ошибки AlreadyRegistered — в статье «Как зарегистрировать модель в Django Admin»):
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
pass
Настройка списка объектов (changelist)
Страница списка — то, с чем пользователи админки работают чаще всего. Основные опции:
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ["title", "author", "published", "price", "is_available"]
list_display_links = ["title"]
list_filter = ["is_available", "published", "author"]
search_fields = ["title", "author__name"]
ordering = ["-published"]
date_hierarchy = "published"
list_per_page = 50
list_select_related = ["author"]
| Опция | Что делает |
|---|---|
list_display | Колонки таблицы: поля модели, методы или вычисляемые значения |
list_display_links | Какие колонки ведут на страницу редактирования |
list_filter | Панель фильтров справа: по булевым полям, датам, внешним ключам |
search_fields | Поиск по полям, в том числе через связи (author__name) |
date_hierarchy | Навигация по годам, месяцам и дням над таблицей |
list_select_related | select_related для колонок с внешними ключами — защита от N+1 |
list_editable | Редактирование полей прямо в списке |
search_help_text | Подсказка под строкой поиска |
list_select_related важен: без него каждая строка с колонкой author делает отдельный SQL-запрос. Подробно о проблеме — в разборе N+1 в Django ORM.
Вычисляемые колонки и @admin.display
В list_display можно передать метод. Декоратор @admin.display задаёт заголовок колонки, сортировку и отображение булевых значений иконкой:
from django.db.models import Count
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
list_display = ["name", "books_count"]
search_fields = ["name"]
def get_queryset(self, request):
# Считаем книги одним запросом, а не по запросу на автора
return super().get_queryset(request).annotate(_books_count=Count("books"))
@admin.display(description="Книг", ordering="_books_count")
def books_count(self, obj):
return obj._books_count
Редактирование прямо в списке
class BookAdmin(admin.ModelAdmin):
list_display = ["title", "price", "is_available"]
list_editable = ["price", "is_available"]
Поле из list_editable обязано быть в list_display и не может одновременно быть ссылкой из list_display_links. Иначе Django выдаст ошибку проверки при запуске.
Свой фильтр: SimpleListFilter
Когда фильтра по значению поля мало, опишите бизнес-условие классом SimpleListFilter. Метод lookups() возвращает пункты меню фильтра, queryset() — отфильтрованную выборку:
import datetime
class NoveltyFilter(admin.SimpleListFilter):
title = "новизна"
parameter_name = "novelty"
def lookups(self, request, model_admin):
return [("new", "Вышли за последний год"), ("old", "Старше года")]
def queryset(self, request, queryset):
year_ago = datetime.date.today() - datetime.timedelta(days=365)
if self.value() == "new":
return queryset.filter(published__gte=year_ago)
if self.value() == "old":
return queryset.filter(published__lt=year_ago)
return queryset
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_filter = [NoveltyFilter, "is_available", "author"]
Если queryset() возвращает None, фильтр не применяется — поэтому последний return queryset можно не писать.
Настройка формы редактирования
Порядок и группировка полей
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
fieldsets = [
(None, {"fields": ["title", "slug", "author"]}),
("Продажи", {"fields": ["price", "is_available"]}),
(
"Публикация",
{"fields": ["published"], "classes": ["collapse"]},
),
]
prepopulated_fields = {"slug": ["title"]}
fieldsets— группы полей с заголовками; классcollapseсворачивает группу.prepopulated_fields— заполняет slug из заголовка прямо в браузере.readonly_fields— поля только для чтения, в том числе вычисляемые методы.filter_horizontalиfilter_vertical— виджет с двумя списками и поиском для полейManyToManyFieldвместо обычного множественного выбора.save_on_top = True— кнопки сохранения дублируются над формой, удобно для длинных форм.
Большие связанные таблицы: autocomplete_fields
Выпадающий список на 100 000 авторов загрузит все записи в HTML. Используйте поиск с подгрузкой:
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
search_fields = ["name"] # обязательно для autocomplete
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
autocomplete_fields = ["author"]
Альтернатива — raw_id_fields: поле с ID и кнопкой выбора во всплывающем окне. Оно работает без search_fields, но менее удобно редакторам.
Инлайны: связанные объекты на одной странице
Чтобы редактировать книги прямо на странице автора, используйте TabularInline (таблица) или StackedInline (форма в столбик):
class BookInline(admin.TabularInline):
model = Book
extra = 0 # не показывать пустые формы по умолчанию
fields = ["title", "published", "price"]
show_change_link = True
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInline]
Инлайны рендерят все связанные объекты. Если у родителя сотни дочерних записей, страница станет тяжёлой — в таком случае лучше ссылка на отфильтрованный список. Остальные параметры инлайнов и приёмы для больших связей — в статье об инлайнах в Django Admin.
Действия над выбранными записями (admin actions)
Действия появляются в выпадающем списке над таблицей и применяются к отмеченным строкам:
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
actions = ["mark_unavailable"]
@admin.action(description="Снять с продажи", permissions=["change"])
def mark_unavailable(self, request, queryset):
updated = queryset.update(is_available=False)
self.message_user(request, f"Снято с продажи: {updated}")
queryset.update() выполняет один SQL-запрос вместо цикла по объектам. Для действительно больших выборок и долгих операций переносите работу в фоновые задачи — см. оптимизацию массовых действий.
Действие может вернуть HTTP-ответ — например, файл. Так делают выгрузку выбранных записей в CSV; пример с графиками и сводной таблицей — в статье об отчётах в Django Admin. Для импорта и экспорта в CSV и Excel с предпросмотром есть сторонний пакет django-import-export.
Права доступа
Админка опирается на систему прав django.contrib.auth:
- войти может пользователь с
is_staff=True; - суперпользователь (
is_superuser=True) имеет все права; - остальным права выдаются на уровне моделей:
view,add,change,delete— через пользователей или группы.
Для тонкой логики переопределите методы ModelAdmin:
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
def has_delete_permission(self, request, obj=None):
# Удалять книги могут только суперпользователи
return request.user.is_superuser
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
# Редактор видит только книги в наличии
return qs.filter(is_available=True)
Оформление: заголовки и тема
Тексты в шапке меняются атрибутами сайта админки — например, в admin.py любого приложения:
admin.site.site_header = "Библиотека: управление"
admin.site.site_title = "Библиотека"
admin.site.index_title = "Разделы"
Как устроены AdminSite и ModelAdmin, как завести вторую админку и добавить свою страницу через get_urls, разобрано в статье «Как устроен Django Admin».
Глубокая переделка внешнего вида — через переопределение шаблонов и стилей: см. темизацию Django Admin и виджеты дашборда. Готовые темы оформления сравниваем в обзоре Unfold, Jazzmin и Grappelli.
Частые проблемы
Админка без стилей после деплоя
При DEBUG = False Django не раздаёт статику. Соберите её и отдавайте через веб-сервер или WhiteNoise:
# settings.py
STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
python manage.py collectstatic --noinput
«CSRF verification failed» при входе
Если сайт работает за HTTPS-прокси или на нестандартном домене, добавьте origin со схемой:
CSRF_TRUSTED_ORIGINS = ["https://admin.example.org"]
Для прокси также нужен SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https"), если прокси передаёт этот заголовок.
Модель не появилась в админке
Проверьте по порядку: приложение есть в INSTALLED_APPS; модель зарегистрирована в admin.py этого приложения; у пользователя есть право view на модель; сервер перезапущен после изменений.
Список открывается медленно
Почти всегда причина — N+1 запросы из колонок с внешними ключами или методов в list_display. Включите list_select_related, используйте annotate в get_queryset и проверьте число запросов через Django Debug Toolbar (подключение — в разборе N+1).
Частые вопросы
Как сделать поле необязательным в форме админки?
Админка берёт обязательность из модели. Добавьте полю blank=True (для нестроковых полей — ещё и null=True) и создайте миграцию:
published = models.DateField("Дата выхода", blank=True, null=True)
Как убрать «Группы» или другую встроенную модель из админки?
Снимите регистрацию в admin.py любого своего приложения:
from django.contrib import admin
from django.contrib.auth.models import Group
admin.site.unregister(Group)
Приложение с этим кодом должно стоять в INSTALLED_APPS ниже django.contrib.auth: админ-модули загружаются по порядку, и раньше регистрации Django ответит ошибкой NotRegistered.
Можно ли дать доступ к админке клиентам сайта?
Не стоит. Django Admin задуман как внутренний инструмент сотрудников: интерфейс повторяет структуру моделей, а права выдаются на целые таблицы. Личный кабинет клиента делают обычными представлениями и формами — см. формы Django.
Почему после ввода верного пароля снова открывается форма входа?
Чаще всего у пользователя нет is_staff=True или он неактивен (is_active=False) — Django тогда показывает ошибку под формой. Если ошибки нет, а форма возвращается, браузер не сохраняет cookie сессии: например, при SESSION_COOKIE_SECURE = True сайт открыт по HTTP. Проверьте схему и домен в настройках cookie.
Как выводить в админке картинку или ссылку?
Сделайте метод для list_display или readonly_fields и верните разметку через format_html — функция экранирует подставляемые значения. Пример для модели с полем cover = models.ImageField(...):
from django.utils.html import format_html
@admin.display(description="Обложка")
def cover_preview(self, obj):
if not obj.cover:
return "—"
return format_html('<img src="{}" height="60">', obj.cover.url)
Как узнать, кто изменил запись?
Админка сама пишет историю в модель LogEntry: она доступна по кнопке «История» на странице объекта. Изменения через код и queryset.update() туда не попадают — их логируйте отдельно.
Чек-лист настройки админки
- у моделей есть
__str__иverbose_name - у каждой модели свой
ModelAdminсlist_display,search_fieldsиlist_filter - внешние ключи в списке покрыты
list_select_related - большие связи — через
autocomplete_fieldsилиraw_id_fields - массовые операции используют
queryset.update()или фоновые задачи - права выданы через группы, а не суперпользователям «на всякий случай»
- в продакшне: свой путь к админке, HTTPS,
collectstatic, 2FA
Документация по всем опциям ModelAdmin — в официальном руководстве Django.
- #Django Admin
- #Админка Django
- #ModelAdmin
- #createsuperuser
- #Инлайны
- #Admin Actions