Django-Admin.ru
Django · Django Admin★ Руководство

Django Admin: полное руководство по админке Django

Как включить админку Django, создать суперпользователя, зарегистрировать модели и настроить ModelAdmin: списки, фильтры, поиск, инлайны и действия.

Редакция Django-Admin.ru
· обновлено · 10 мин чтения

Содержание · 12 разделов
  1. Как включить админку Django
  2. Как создать суперпользователя
  3. Русский язык интерфейса
  4. Регистрация моделей в админке
  5. Настройка списка объектов (changelist)
  6. Вычисляемые колонки и @admin.display
  7. Редактирование прямо в списке
  8. Свой фильтр: SimpleListFilter
  9. Настройка формы редактирования
  10. Порядок и группировка полей
  11. Большие связанные таблицы: autocomplete_fields
  12. Инлайны: связанные объекты на одной странице
  13. Действия над выбранными записями (admin actions)
  14. Права доступа
  15. Оформление: заголовки и тема
  16. Частые проблемы
  17. Админка без стилей после деплоя
  18. «CSRF verification failed» при входе
  19. Модель не появилась в админке
  20. Список открывается медленно
  21. Частые вопросы
  22. Как сделать поле необязательным в форме админки?
  23. Как убрать «Группы» или другую встроенную модель из админки?
  24. Можно ли дать доступ к админке клиентам сайта?
  25. Почему после ввода верного пароля снова открывается форма входа?
  26. Как выводить в админке картинку или ссылку?
  27. Как узнать, кто изменил запись?
  28. Чек-лист настройки админки

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_relatedselect_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
↑ ↓ выборEnter открытьEsc закрыть