Django-Admin.ru

Как зарегистрировать модель в Django Admin

Как зарегистрировать модель в Django Admin: admin.site.register, @admin.register, unregister, свой AdminSite, ошибки AlreadyRegistered и NotRegistered.

Редакция Django-Admin.ru
· 13 мин чтения

Содержание · 12 разделов
  1. Где регистрировать модели: admin.py и autodiscover
  2. admin.site.register: три формы вызова
  3. Декоратор @admin.register
  4. Как зарегистрировать несколько моделей
  5. Регистрация в своём AdminSite
  6. unregister и перерегистрация: User и Group
  7. Ошибки регистрации и их тексты
  8. AlreadyRegistered: The model … is already registered
  9. NotRegistered: The model … is not registered
  10. ImproperlyConfigured: абстрактная модель
  11. admin.E039: связанная модель не зарегистрирована
  12. Модель не видна в админке: чек-лист
  13. Названия в меню: verbose_name и имя приложения
  14. Порядок моделей и приложений в меню
  15. Частые вопросы
  16. Можно ли зарегистрировать одну модель дважды с разными настройками?
  17. Как скрыть модель из меню, но оставить её для autocomplete?
  18. Как разбить большой admin.py на несколько файлов?
  19. Можно ли регистрировать модели в models.py?
  20. Как сделать так, чтобы связанные объекты редактировались на странице модели?
  21. Итог

Чтобы модель появилась в Django Admin, зарегистрируйте её в файле admin.py своего приложения: admin.site.register(Book) или декоратором @admin.register(Book) над классом ModelAdmin. Django сам импортирует admin.py всех приложений из INSTALLED_APPS, поэтому больше ничего подключать не нужно — после перезапуска сервера модель появится на главной странице админки.

# library/admin.py
from django.contrib import admin

from .models import Author, Book

admin.site.register(Author)  # стандартный интерфейс


@admin.register(Book)  # интерфейс со своими настройками
class BookAdmin(admin.ModelAdmin):
    list_display = ["title", "author", "is_available"]

Ниже — все варианты регистрации, свой AdminSite, снятие и замена регистрации встроенных моделей User и Group, реальные тексты ошибок и чек-лист на случай, если модель в админке не видна. Примеры проверены на Django 6.1 и 5.2 LTS. Как включить админку и создать первого администратора, рассказано в полном руководстве по Django Admin.

Где регистрировать модели: admin.py и autodiscover

Команда startapp создаёт в папке приложения, рядом с models.py, файл admin.py с заготовкой from django.contrib import admin — регистрация пишется в нём. Модуль никто не импортирует вручную: при старте проекта приложение django.contrib.admin вызывает admin.autodiscover(), а тот по очереди импортирует модуль admin каждого приложения из INSTALLED_APPS.

Из этого следуют три правила:

  • файл должен называться именно admin.py (или быть пакетом admin/ с __init__.py) и лежать в папке приложения;
  • приложение должно стоять в INSTALLED_APPS, иначе его admin.py не загрузится;
  • модули загружаются в порядке INSTALLED_APPS — это важно, когда вы снимаете регистрацию чужой модели (об этом ниже, в разделе про unregister()).

Ошибка импорта в admin.py не проходит молча: проект не запустится, а python manage.py check покажет причину, например опечатку в имени модели:

ImportError: cannot import name 'Boook' from 'library.models' (...\library\models.py). Did you mean: 'Book'?

Совет: если автопоиск не нужен, замените в INSTALLED_APPS строку "django.contrib.admin" на "django.contrib.admin.apps.SimpleAdminConfig". Тогда модули admin.py не импортируются автоматически: импортируйте их сами или вызовите admin.autodiscover() там, где это нужно.

admin.site.register: три формы вызова

admin.site — сайт админки по умолчанию, тот, что подключён в urls.py строкой path("admin/", admin.site.urls). Его метод register() принимает модель (или список моделей), необязательный класс ModelAdmin и необязательные опции.

Только модель. Django подставит базовый ModelAdmin: список с одной колонкой (результат __str__), форма со всеми редактируемыми полями. Для справочников этого часто достаточно:

admin.site.register(Author)

Модель и класс настроек. Класс наследуется от admin.ModelAdmin и описывает колонки списка, фильтры, поиск, форму:

class BookAdmin(admin.ModelAdmin):
    list_display = ["title", "author", "is_available"]
    list_filter = ["is_available"]
    search_fields = ["title"]


admin.site.register(Book, BookAdmin)

Модель и опции без класса. Именованные аргументы превращаются в атрибуты класса, который Django создаст сам:

admin.site.register(Genre, list_display=["name"], search_fields=["name"])

type(admin.site.get_model_admin(Genre)).__name__  # → 'GenreAdmin'

Третья форма удобна для пары опций, но как только настроек становится больше, отдельный класс читается лучше. Все опции ModelAdmin — колонки, фильтры, формы, инлайны — собраны в упомянутом выше руководстве.

Декоратор @admin.register

Декоратор делает то же самое, что admin.site.register(Book, BookAdmin), но регистрация стоит прямо над классом и не теряется в конце файла:

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

Декоратор принимает несколько моделей и именованный аргумент site — сайт админки, если он не стандартный:

@admin.register(Genre, Publisher)  # один класс настроек на две модели
class DictionaryAdmin(admin.ModelAdmin):
    list_display = ["name"]
    search_fields = ["name"]

Класс под декоратором обязан наследоваться от admin.ModelAdmin. Если забыть базовый класс, проект не запустится:

ValueError: Wrapped class must subclass ModelAdmin.
СпособКогда подходит
admin.site.register(Model)справочник, которому хватает стандартного интерфейса
admin.site.register(Model, Admin)класс настроек описан в другом модуле или переиспользуется
admin.site.register(Model, **opts)одна-две опции, отдельный класс избыточен
@admin.register(Model)основной вариант для модели со своим ModelAdmin
@admin.register(Model, site=...)регистрация в собственном AdminSite

Как зарегистрировать несколько моделей

register() принимает не только модель, но и список. Так удобно подключать справочники одной строкой:

admin.site.register([Genre, Publisher])

Если у моделей общие настройки, передайте их в декоратор вместе, как в примере с DictionaryAdmin выше.

Чтобы зарегистрировать все модели приложения, переберите их через реестр приложений и пропустите уже зарегистрированные — иначе получите AlreadyRegistered:

from django.apps import apps
from django.contrib import admin

from .models import Book


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


# Остальные модели приложения — со стандартным ModelAdmin
for model in apps.get_app_config("library").get_models():
    if not admin.site.is_registered(model):
        admin.site.register(model)

Цикл стоит в конце файла, после всех явных регистраций. Пользуйтесь им осторожно: в админку попадут и служебные модели, которые редакторам видеть не нужно.

Регистрация в своём AdminSite

Второй сайт админки нужен, когда разным сотрудникам требуется отдельный интерфейс со своим набором моделей и своим адресом: например, каталог для контент-менеджеров рядом с основной админкой. Создайте экземпляр AdminSite и регистрируйте модели в нём, а не в admin.site:

# library/admin.py
from django.contrib import admin

from .models import Author, Book


class LibraryAdminSite(admin.AdminSite):
    site_header = "Библиотека: каталог"
    site_title = "Каталог"
    index_title = "Разделы каталога"


library_site = LibraryAdminSite(name="library_admin")


@admin.register(Book, site=library_site)
class BookAdmin(admin.ModelAdmin):
    list_display = ["title", "author"]


library_site.register(Author)
# config/urls.py
from django.contrib import admin
from django.urls import path

from library.admin import library_site

urlpatterns = [
    path("admin/", admin.site.urls),
    path("catalog/", library_site.urls),
]

Модели из library_site открываются по адресу /catalog/ и не появляются в /admin/ — у каждого сайта свой реестр. Имя сайта задаёт пространство имён URL: reverse("library_admin:library_book_changelist") вернёт /catalog/library/book/.

Стандартный сайт тоже можно заменить своим классом, например чтобы поменять порядок моделей во всей админке. Для этого служит AdminConfig.default_site — пример есть ниже, в разделе о порядке. Как AdminSite строит маршруты и как добавить на сайт свои страницы, разобрано в статье «Как устроен Django Admin».

unregister и перерегистрация: User и Group

Встроенные модели уже зарегистрированы приложением django.contrib.auth. Чтобы убрать их из админки или заменить настройки, сначала снимите регистрацию методом unregister().

Убрать «Группы» из меню:

# library/admin.py
from django.contrib import admin
from django.contrib.auth.models import Group

admin.site.unregister(Group)

Заменить интерфейс пользователей своим: наследуйтесь от UserAdmin, чтобы сохранить формы смены пароля и наборы полей, и зарегистрируйте модель заново:

from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from django.contrib.auth.models import Group, User

admin.site.unregister(User)
admin.site.unregister(Group)


@admin.register(User)
class MyUserAdmin(UserAdmin):
    list_display = ["username", "email", "is_staff", "last_login"]
    list_filter = ["is_staff", "is_active", "groups"]


@admin.register(Group)
class MyGroupAdmin(GroupAdmin):
    list_display = ["name", "users_count"]

    @admin.display(description="Пользователей")
    def users_count(self, obj):
        return obj.user_set.count()

Код работает, только если приложение с ним стоит в INSTALLED_APPS ниже django.contrib.auth. Если поставить его выше, admin.py загрузится раньше, чем auth зарегистрирует свои модели, и проект упадёт с NotRegistered.

С собственной моделью пользователя (AUTH_USER_MODEL) встроенный User заменён, и Django его в админке не регистрирует. Свою модель нужно зарегистрировать самостоятельно, обычно с подклассом UserAdmin.

Проверить состояние реестра можно в shell:

python manage.py shell -v0 -c "from django.contrib import admin; from library.models import Book; print(admin.site.is_registered(Book), admin.site.get_model_admin(Book))"
# → True library.BookAdmin

На macOS и Linux вместо python может понадобиться python3. Метод is_registered() отвечает, есть ли модель в реестре, а get_model_admin() возвращает её экземпляр ModelAdmin или выбрасывает NotRegistered.

Ошибки регистрации и их тексты

Все ошибки ниже возникают при запуске проекта, ещё до первого запроса: их покажут runserver, migrate и python manage.py check.

AlreadyRegistered: The model … is already registered

Модель регистрируют второй раз в одном и том же сайте. Текст зависит от того, как прошла первая регистрация. Если без своего класса:

django.contrib.admin.exceptions.AlreadyRegistered: The model Book is already registered in app 'library'.

Если с классом BookAdmin:

django.contrib.admin.exceptions.AlreadyRegistered: The model Book is already registered with 'library.BookAdmin'.

Частые причины:

  • над классом стоит @admin.register(Book), а в конце файла остался admin.site.register(Book, BookAdmin) — оставьте что-то одно;
  • модель уже зарегистрировало другое приложение. Для встроенного пользователя это выглядит так: The model User is already registered with 'auth.UserAdmin'. Сначала вызовите admin.site.unregister(User);
  • цикл автоматической регистрации стоит раньше явной регистрации — перенесите его в конец файла или проверяйте is_registered().

NotRegistered: The model … is not registered

unregister() вызван для модели, которой нет в реестре:

django.contrib.admin.exceptions.NotRegistered: The model Group is not registered

Обычно приложение с unregister() стоит в INSTALLED_APPS выше того, что регистрирует модель. Переставьте его ниже. Та же ошибка (с точкой в конце) возникает при вызове admin.site.get_model_admin() для незарегистрированной модели.

ImproperlyConfigured: абстрактная модель

Абстрактную модель (abstract = True в Meta) зарегистрировать нельзя — у неё нет таблицы:

django.core.exceptions.ImproperlyConfigured: The model TimeStamped is abstract, so it cannot be registered with admin.

Регистрируйте конкретных наследников. Модели с составным первичным ключом (CompositePrimaryKey, появился в Django 5.2) админка тоже пока не поддерживает: register() для них выбрасывает ImproperlyConfigured с текстом has a composite primary key, so it cannot be registered with admin.

admin.E039: связанная модель не зарегистрирована

autocomplete_fields работает через поиск по связанной модели, поэтому она обязана быть зарегистрирована и иметь search_fields. Если регистрации нет, проверка проекта остановит запуск:

<class 'library.admin.BookAdmin'>: (admin.E039) An admin for model "Author" has to be registered to be referenced by BookAdmin.autocomplete_fields.

Модель не видна в админке: чек-лист

Пройдите пункты по порядку — каждый отсекает отдельную причину.

  1. Приложение в INSTALLED_APPS. Без него admin.py не загрузится. Если модели этого приложения импортируются откуда-то ещё, Django сообщит прямо: RuntimeError: Model class library.models.Author doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
  2. Регистрация в правильном файле и сайте. Файл называется admin.py, лежит в папке приложения, вызов register() не закомментирован и не спрятан под условием. Если модель зарегистрирована в своём AdminSite, искать её нужно по адресу этого сайта, а не в /admin/. Быстрая проверка — admin.site.is_registered(Model) в shell.
  3. Сервер перезапущен. runserver перезагружается сам при сохранении файла, а Gunicorn, uWSGI и контейнеры — нет: после деплоя их нужно перезапустить.
  4. Миграции применены. Без таблицы модель всё равно появится в меню, но список упадёт с OperationalError: no such table: library_book (текст для SQLite). Выполните python manage.py makemigrations и python manage.py migrate — подробнее в статье о миграциях Django.
  5. У пользователя is_staff=True. Без флага админка не пускает дальше формы входа: «Пожалуйста, введите корректные имя пользователя и пароль учётной записи…» Флаг ставится в карточке пользователя или в shell; первого администратора создают командой createsuperuser.
  6. Есть право хотя бы на просмотр. Сотрудник без прав видит главную страницу с сообщением «У вас недостаточно полномочий для просмотра или изменения чего либо.» Модель появляется в меню, когда у пользователя или его группы есть одно из прав view_, add_, change_ или delete_ на неё. Как выдавать права через группы, разобрано в статье о правах доступа в Django.
  7. ModelAdmin не прячет модель. Переопределённые has_module_permission() или get_model_perms(), которые возвращают False или пустой словарь, убирают модель из меню даже у суперпользователя.

Названия в меню: verbose_name и имя приложения

Админка не берёт имена из кода класса. Название модели в меню — это verbose_name_plural из Meta с заглавной буквы, заголовок блока — verbose_name конфигурации приложения:

# library/models.py
class Book(models.Model):
    title = models.CharField("Название", max_length=300)

    class Meta:
        verbose_name = "книга"
        verbose_name_plural = "книги"
# library/apps.py
from django.apps import AppConfig


class LibraryConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "library"
    verbose_name = "Библиотека"

Без этих настроек блок называется по метке приложения (Library), модель — по имени класса (Books). Если указать только verbose_name = "книга", Django допишет к нему латинскую s и в меню появится «Книгаs», поэтому для русских названий всегда задавайте обе формы. Поля Meta подробно описаны в статье о моделях Django.

Порядок моделей и приложений в меню

Порядок вызовов register() на меню не влияет. Django сортирует приложения по verbose_name, а модели внутри приложения — по verbose_name_plural, в обоих случаях по алфавиту. Проект с примерами выше выглядит так:

Библиотека
  Авторы
  Жанры
  Издательства
  Книги
Пользователи и группы
  Группы
  Пользователи

Сортировку выполняет метод AdminSite.get_app_list(). Чтобы задать свой порядок, переопределите его в подклассе AdminSite:

# config/admin.py
from django.contrib import admin

# Метка приложения -> имена классов моделей в нужном порядке
MODEL_ORDER = {
    "library": ["Book", "Author", "Genre", "Publisher"],
}


class OrderedAdminSite(admin.AdminSite):
    def get_app_list(self, request, app_label=None):
        app_list = super().get_app_list(request, app_label)
        for app in app_list:
            order = MODEL_ORDER.get(app["app_label"])
            if order:
                app["models"].sort(
                    key=lambda m: order.index(m["object_name"])
                    if m["object_name"] in order
                    else len(order)
                )
        return app_list

И сделайте этот класс сайтом по умолчанию — тогда admin.site во всех admin.py станет экземпляром OrderedAdminSite, и менять регистрации не придётся:

# config/apps.py
from django.contrib.admin.apps import AdminConfig


class OrderedAdminConfig(AdminConfig):
    default_site = "config.admin.OrderedAdminSite"
# settings.py
INSTALLED_APPS = [
    "config.apps.OrderedAdminConfig",  # вместо "django.contrib.admin"
    "django.contrib.auth",
    # ...
]

После этого «Книги» стоят первыми и на главной, и на странице приложения, и в боковом меню. Модели, которых нет в MODEL_ORDER, уходят в конец. Порядок самих приложений меняется так же — сортировкой списка app_list.

Встречается и обходной путь: цифры в начале verbose_name_plural («1. Книги»). Он работает без кода, но цифры видны пользователям и попадают во все сообщения админки.

Частые вопросы

Можно ли зарегистрировать одну модель дважды с разными настройками?

В одном сайте — нет, это AlreadyRegistered. Создайте прокси-модель (proxy = True в Meta) и зарегистрируйте её отдельно: у неё своя строка в меню, свой ModelAdmin и, при необходимости, своя выборка в get_queryset(). Прокси-модель требует миграции, но таблицу не создаёт.

class AvailableBook(Book):
    class Meta:
        proxy = True
        verbose_name = "книга в наличии"
        verbose_name_plural = "книги в наличии"

Как скрыть модель из меню, но оставить её для autocomplete?

Верните пустой словарь из get_model_perms(). Модель исчезнет из меню, но останется зарегистрированной: autocomplete_fields в других ModelAdmin и прямые ссылки продолжат работать, права пользователей не изменятся.

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    search_fields = ["name"]

    def get_model_perms(self, request):
        return {}

Как разбить большой admin.py на несколько файлов?

Превратите модуль в пакет: папка admin/ с файлами books.py, authors.py и __init__.py, который их импортирует (from . import authors, books). Autodiscover импортирует library.admin, а регистрация из подмодулей выполнится при импорте пакета.

Можно ли регистрировать модели в models.py?

Технически вызов сработает, но так смешиваются слой данных и интерфейс, а импорт admin в models.py легко приводит к циклическим импортам. Держите регистрацию в admin.py — там её ищут и другие разработчики, и инструменты вроде autodiscover.

Как сделать так, чтобы связанные объекты редактировались на странице модели?

Регистрировать связанную модель для этого не обязательно: её добавляют в inlines родительского ModelAdmin. Варианты TabularInline и StackedInline разобраны в статье об инлайнах в Django Admin.

Итог

Модель регистрируют в admin.py приложения: admin.site.register(Model) для стандартного интерфейса, @admin.register(Model) над своим ModelAdmin — для настроенного. Встроенные User и Group перед заменой снимают через unregister() из приложения, стоящего в INSTALLED_APPS ниже django.contrib.auth. Если модель не видна, проверьте по чек-листу INSTALLED_APPS, регистрацию, миграции, is_staff и права view. Названия в меню задаются через verbose_name, а порядок — переопределением get_app_list() в своём AdminSite. Остальные статьи кластера собраны в разделе Django Admin.

  • #Django Admin
  • #ModelAdmin
  • #AdminSite
  • #Админка Django
  • #Django
↑ ↓ выборEnter открытьEsc закрыть