Spec-Zone.ru › Django 6.0

Сайт администрирования Django

Одна из самых мощных возможностей Django — автоматический интерфейс администрирования. Он считывает метаданные из ваших моделей и предоставляет быстрый интерфейс, ориентированный на модели, с помощью которого пользователи, которым вы доверяете, могут управлять содержимым сайта. Рекомендуется использовать админку только как внутренний инструмент управления организации. Она не предназначена для построения всего пользовательского интерфейса на её основе.

Админка предоставляет множество хуков для настройки, но будьте осторожны и не пытайтесь использовать исключительно эти хуки. Если вам нужен интерфейс, ориентированный на процессы и скрывающий детали реализации таблиц и полей базы данных, вероятно, пришло время написать собственные представления.

В этом документе рассказывается, как активировать, использовать и настраивать интерфейс администрирования Django.

Обзор

Админка включена в шаблон проекта по умолчанию, используемый командой startproject.

Если вы не используете шаблон проекта по умолчанию, необходимо выполнить следующие требования:

  1. Добавьте 'django.contrib.admin' и его зависимости — django.contrib.auth, django.contrib.contenttypes, django.contrib.messages и django.contrib.sessions — в параметр INSTALLED_APPS.
  2. Настройте бэкенд DjangoTemplates в параметре TEMPLATES, указав django.template.context_processors.request, django.contrib.auth.context_processors.auth и django.contrib.messages.context_processors.messages в параметре 'context_processors' параметра OPTIONS.
  3. Если вы настроили параметр MIDDLEWARE, в него необходимо включить django.contrib.sessions.middleware.SessionMiddleware, django.contrib.auth.middleware.AuthenticationMiddleware и django.contrib.messages.middleware.MessageMiddleware.
  4. Добавьте URL-адреса админки в конфигурацию URL.

После выполнения этих шагов вы сможете пользоваться сайтом администрирования, перейдя по URL-адресу, к которому вы его подключили (по умолчанию — /admin/).

Если вам нужно создать пользователя для входа, используйте команду createsuperuser. По умолчанию для входа в админку у пользователя должен быть установлен атрибут is_staff со значением True.

Наконец, определите, какие модели приложения должны быть доступны для редактирования в интерфейсе администрирования. Для каждой такой модели зарегистрируйте её в админке, как описано в разделе ModelAdmin.

Другие темы

  • Действия админки
  • ModelAdmin Фильтры списков
  • Генератор документации админки Django
  • Настройка JavaScript в админке

См. также

Информацию о раздаче статических файлов (изображений, JavaScript и CSS), связанных с админкой, в рабочей среде см. в разделе Раздача файлов.

Возникли проблемы? Ознакомьтесь с разделом Часто задаваемые вопросы: админка.

Объекты ModelAdmin

class ModelAdmin [исходный код]

Класс ModelAdmin представляет модель в интерфейсе администрирования. Обычно такие классы хранятся в файле с именем admin.py в вашем приложении. Рассмотрим пример ModelAdmin:

from django.contrib import admin
from myapp.models import Author


class AuthorAdmin(admin.ModelAdmin):
    pass


admin.site.register(Author, AuthorAdmin)

Нужен ли вам вообще объект ModelAdmin?

В предыдущем примере класс ModelAdmin пока не определяет пользовательские значения. Поэтому будет предоставлен интерфейс администрирования по умолчанию. Если вас устраивает интерфейс администрирования по умолчанию, определять объект ModelAdmin не нужно — можно зарегистрировать класс модели, не предоставляя описание ModelAdmin. Предыдущий пример можно упростить следующим образом:

from django.contrib import admin
from myapp.models import Author

admin.site.register(Author)

Декоратор register

register(*models, site=django.contrib.admin.sites.site) [исходный код]

Для регистрации классов ModelAdmin также предусмотрен декоратор:

from django.contrib import admin
from .models import Author


@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    pass

Ему передаются один или несколько классов моделей для регистрации в ModelAdmin. Если вы используете пользовательский AdminSite, передайте его с помощью именованного аргумента site:

from django.contrib import admin
from .models import Author, Editor, Reader
from myproject.admin_site import custom_admin_site


@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
    pass

Этот декоратор нельзя использовать, если вам нужно ссылаться на класс администрирования модели в его методе __init__(), например super(PersonAdmin, self).__init__(*args, **kwargs). В этом случае можно использовать super().__init__(*args, **kwargs).

Обнаружение файлов админки

Когда вы добавляете 'django.contrib.admin' в параметр INSTALLED_APPS, Django автоматически ищет модуль admin в каждом приложении и импортирует его.

class apps.AdminConfig

Это класс AppConfig админки по умолчанию. При запуске Django он вызывает autodiscover().

class apps.SimpleAdminConfig

Этот класс работает так же, как AdminConfig, за исключением того, что он не вызывает autodiscover().

default_site

Путь импорта через точку к классу сайта администрирования по умолчанию или к вызываемому объекту, который возвращает экземпляр сайта. По умолчанию — 'django.contrib.admin.sites.AdminSite'. Инструкции по использованию см. в разделе Переопределение сайта администрирования по умолчанию.

autodiscover() [исходный код]

Эта функция пытается импортировать модуль admin из каждого установленного приложения. Предполагается, что такие модули регистрируют модели в админке.

Обычно вызывать эту функцию напрямую не нужно, поскольку AdminConfig вызывает её при запуске Django.

Если вы используете пользовательский AdminSite, часто бывает удобно импортировать в код все подклассы ModelAdmin и зарегистрировать их в пользовательском AdminSite. В этом случае, чтобы отключить автоматическое обнаружение, вместо 'django.contrib.admin' необходимо указать 'django.contrib.admin.apps.SimpleAdminConfig' в параметре INSTALLED_APPS.

ModelAdmin параметры

ModelAdmin очень гибок. Он имеет несколько параметров для настройки интерфейса. Все параметры определяются в подклассе ModelAdmin:

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    date_hierarchy = "pub_date"
ModelAdmin.actions

Список действий, доступных на странице списка изменений. Подробности см. в разделе Действия администратора.

ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom

Определяет, где на странице отображается панель действий. По умолчанию список изменений в административном интерфейсе отображает действия в верхней части страницы (actions_on_top = True; actions_on_bottom = False).

ModelAdmin.actions_selection_counter

Определяет, отображается ли рядом с раскрывающимся списком действий счётчик выбранных элементов. По умолчанию список изменений в административном интерфейсе отображает этот счётчик (actions_selection_counter = True).

ModelAdmin.date_hierarchy

Задайте для date_hierarchy имя DateField или DateTimeField в модели, и на странице списка изменений появится навигация по датам для этого поля.

Пример:

date_hierarchy = "pub_date"

Можно также указать поле связанной модели, используя поиск __, например:

date_hierarchy = "author__pub_date"

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

Примечание

date_hierarchy внутри использует QuerySet.datetimes(). Если поддержка часовых поясов включена (USE_TZ = True), ознакомьтесь с документацией этой функции, где описаны некоторые ограничения.

ModelAdmin.empty_value_display

Этот атрибут переопределяет значение, отображаемое по умолчанию для пустых полей записи (None, пустая строка и т. д.). Значение по умолчанию — - (тире). Например:

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    empty_value_display = "-empty-"

Можно также переопределить empty_value_display для всех страниц административного интерфейса с помощью AdminSite.empty_value_display или для отдельных полей, как показано ниже:

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    list_display = ["name", "title", "view_birth_date"]

    @admin.display(empty_value="???")
    def view_birth_date(self, obj):
        return obj.birth_date
ModelAdmin.exclude

Если задан, этот атрибут должен содержать список имён полей, которые нужно исключить из формы.

Например, рассмотрим следующую модель:

from django.db import models


class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3)
    birth_date = models.DateField(blank=True, null=True)

Если нужна форма для модели Author, включающая только поля name и title, укажите fields или exclude следующим образом:

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    fields = ["name", "title"]


class AuthorAdmin(admin.ModelAdmin):
    exclude = ["birth_date"]

Поскольку модель Author содержит только три поля — name, title и birth_date, — в формах, созданных на основе приведённых выше объявлений, будут одни и те же поля.

ModelAdmin.fields

Используйте параметр fields для простого изменения расположения полей в формах на страницах добавления и изменения: например, чтобы показывать только часть доступных полей, изменить их порядок или сгруппировать их в строки. Например, можно создать упрощённую версию административной формы для модели django.contrib.flatpages.models.FlatPage следующим образом:

class FlatPageAdmin(admin.ModelAdmin):
    fields = ["url", "title", "content"]

В приведённом примере в форме последовательно отображаются только поля url, title и content. fields может содержать значения, определённые в ModelAdmin.readonly_fields, которые будут отображаться только для чтения.

Для более сложного расположения полей см. параметр fieldsets.

Параметр fields принимает те же типы значений, что и list_display, за исключением вызываемых объектов и поисков __ для связанных полей. Имена методов модели и административного класса модели будут использоваться только в том случае, если они перечислены в readonly_fields.

Чтобы расположить несколько полей в одной строке, заключите их в отдельный кортеж. В этом примере поля url и title будут расположены в одной строке, а поле content — в следующей строке:

class FlatPageAdmin(admin.ModelAdmin):
    fields = [("url", "title"), "content"]

Возможная путаница с параметром ModelAdmin.fieldsets

Не следует путать этот параметр fields с ключом словаря fields, который используется в параметре fieldsets, как описано в следующем разделе.

Если не заданы ни параметр fields, ни параметр fieldsets, Django по умолчанию отобразит в одном наборе полей все поля, которые не являются AutoField и имеют editable=True, в том же порядке, в котором они определены в модели, а затем — все поля, заданные в readonly_fields.

ModelAdmin.fieldsets

Задайте fieldsets, чтобы управлять расположением элементов на страницах добавления и изменения в административном интерфейсе.

fieldsets — это список пар из двух элементов, каждая из которых представляет <fieldset> на странице административной формы. (<fieldset> — это «раздел» формы.)

Пары имеют формат (name, field_options), где name — строка, задающая заголовок набора полей, а field_options — словарь с информацией о наборе полей, включая список отображаемых в нём полей.

Полный пример из модели django.contrib.flatpages.models.FlatPage:

from django.contrib import admin


class FlatPageAdmin(admin.ModelAdmin):
    fieldsets = [
        (
            None,
            {
                "fields": ["url", "title", "content", "sites"],
            },
        ),
        (
            "Advanced options",
            {
                "classes": ["collapse"],
                "fields": ["registration_required", "template_name"],
            },
        ),
    ]

В результате получится административная страница следующего вида:

../../../_images/fieldsets.png

Если не заданы ни параметр fieldsets, ни параметр fields, Django по умолчанию отобразит в одном наборе полей все поля, которые не являются AutoField и имеют editable=True, в том же порядке, в котором они определены в модели.

Словарь field_options может содержать следующие ключи:

  • fields

    Список или кортеж имён полей, которые нужно отобразить в этом наборе полей. Этот ключ обязателен.

    Пример:

    {
        "fields": ["first_name", "last_name", "address", "city", "state"],
    }
    

    Как и в случае с параметром fields, чтобы расположить несколько полей в одной строке, заключите их в отдельный кортеж. В этом примере поля first_name и last_name будут расположены в одной строке:

    {
        "fields": [("first_name", "last_name"), "address", "city", "state"],
    }
    

    fields может содержать значения, определённые в readonly_fields, которые будут отображаться только для чтения.

    Если добавить имя вызываемого объекта в fields, будет действовать то же правило, что и для параметра fields: вызываемый объект должен быть перечислен в readonly_fields.

  • classes

    Список или кортеж дополнительных CSS-классов, применяемых к набору полей. Можно указать любые пользовательские CSS-классы, определённые в проекте, а также CSS-классы, предоставляемые Django. В таблице стилей CSS по умолчанию для административного интерфейса определены два особенно полезных класса: collapse и wide.

    Пример:

    {
        "classes": ["wide", "collapse"],
    }
    

    Наборам полей со стилем wide будет предоставлено дополнительное горизонтальное пространство в административном интерфейсе. Наборы полей с именем и стилем collapse изначально будут свёрнуты; их видимость можно переключать с помощью раскрывающегося элемента управления.

  • description

    Необязательная строка дополнительного текста, отображаемого в верхней части каждого набора полей под его заголовком.

    Обратите внимание, что при отображении в административном интерфейсе это значение не экранируется как HTML. Это позволяет при необходимости включать HTML. Также можно использовать обычный текст и функцию django.utils.html.escape(), чтобы экранировать специальные символы HTML.

TabularInline поддерживает fieldsets лишь частично

Функциональность fieldsets при использовании с TabularInline ограничена. Можно указать отображаемые поля и их порядок в макете TabularInline, задав fields в словаре field_options.

Остальные функции не поддерживаются. В частности, нельзя использовать name для задания заголовка группы полей.

ModelAdmin.filter_horizontal

По умолчанию поле ManyToManyField отображается на сайте администрирования в виде <select multiple>. Однако окна множественного выбора могут быть неудобны, когда нужно выбрать много элементов. Если добавить в этот список поле ManyToManyField, вместо него будет использоваться удобный ненавязчивый JavaScript-интерфейс «фильтра», позволяющий искать среди вариантов. Не выбранные и выбранные варианты отображаются в двух расположенных рядом окнах. Чтобы использовать вертикальный интерфейс, см. filter_vertical.

ModelAdmin.filter_vertical

Аналогичен filter_horizontal, но интерфейс фильтра отображается вертикально: окно с невыбранными вариантами находится над окном с выбранными.

ModelAdmin.form

По умолчанию для вашей модели динамически создаётся ModelForm. Она используется для создания формы, отображаемой на страницах добавления и изменения. Вы можете легко предоставить собственный ModelForm, чтобы переопределить поведение формы по умолчанию на этих страницах. Также можно настроить форму по умолчанию, не создавая новую целиком, с помощью метода ModelAdmin.get_form().

Пример приведён в разделе Добавление пользовательской проверки в административный интерфейс.

Не указывайте атрибут Meta.model

Если вы определяете атрибут Meta.model в классе ModelForm, необходимо также определить атрибут Meta.fields (или атрибут Meta.exclude). Однако, поскольку в административном интерфейсе поля задаются другим способом, атрибут Meta.fields будет проигнорирован.

Если ModelForm будет использоваться только в административном интерфейсе, проще всего не указывать атрибут Meta.model, поскольку ModelAdmin предоставит подходящую модель. В качестве альтернативы можно задать fields = [] в классе Meta, чтобы пройти проверку ModelForm.

Приоритет имеет ModelAdmin.exclude

Если в вашем ModelForm и ModelAdmin задан один и тот же параметр exclude, приоритет имеет ModelAdmin:

from django import forms
from django.contrib import admin
from myapp.models import Person


class PersonForm(forms.ModelForm):
    class Meta:
        model = Person
        exclude = ["name"]


class PersonAdmin(admin.ModelAdmin):
    exclude = ["age"]
    form = PersonForm

В приведённом примере поле «age» будет исключено, а поле «name» включено в созданную форму.

ModelAdmin.formfield_overrides

Этот параметр позволяет быстро и без лишних сложностей переопределить некоторые параметры Field для административного интерфейса. formfield_overrides — это словарь, сопоставляющий класс поля со словарём аргументов, передаваемых полю при создании.

Поскольку это описание довольно абстрактно, рассмотрим конкретный пример. Чаще всего formfield_overrides используется для добавления пользовательского виджета для определённого типа поля. Представим, что мы написали RichTextEditorWidget, который хотим использовать для больших текстовых полей вместо стандартного <textarea>. Вот как это сделать:

from django.contrib import admin
from django.db import models

# Import our custom widget and our model from where they're defined
from myapp.models import MyModel
from myapp.widgets import RichTextEditorWidget


class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {"widget": RichTextEditorWidget},
    }

Обратите внимание: ключом словаря является сам класс поля, а не строка. Значение — другой словарь; эти аргументы будут переданы методу __init__() поля формы. Подробности см. в разделе API форм.

Предупреждение

Если вы хотите использовать пользовательский виджет для поля связи (например, ForeignKey или ManyToManyField), убедитесь, что имя этого поля не включено в raw_id_fields, radio_fields или autocomplete_fields.

formfield_overrides не позволяет менять виджет полей связи, для которых заданы raw_id_fields, radio_fields или autocomplete_fields. Это связано с тем, что raw_id_fields, radio_fields и autocomplete_fields подразумевают использование собственных пользовательских виджетов.

ModelAdmin.inlines

См. также приведённые ниже объекты InlineModelAdmin и ModelAdmin.get_formsets_with_inlines().

ModelAdmin.list_display

Задайте list_display, чтобы управлять полями, отображаемыми на странице списка изменений в административном интерфейсе.

Пример:

list_display = ["first_name", "last_name"]

Если не задавать list_display, сайт администрирования будет отображать один столбец с представлением каждого объекта, полученным с помощью __str__().

В list_display можно использовать пять типов значений. Для всех, кроме самого простого типа, можно использовать декоратор display(), позволяющий настраивать отображение поля:

  • Имя поля модели. Например:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ["first_name", "last_name"]
    
  • Имя связанного поля с использованием нотации __. Например:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ["city__name"]
    
  • Вызываемый объект, принимающий один аргумент — экземпляр модели. Например:

    @admin.display(description="Name")
    def upper_case_name(obj):
        return f"{obj.first_name} {obj.last_name}".upper()
    
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = [upper_case_name]
    
  • Строка, представляющая метод ModelAdmin, который принимает один аргумент — экземпляр модели. Например:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ["upper_case_name"]
    
        @admin.display(description="Name")
        def upper_case_name(self, obj):
            return f"{obj.first_name} {obj.last_name}".upper()
    
  • Строка, представляющая атрибут или метод модели (без обязательных аргументов). Например:

    from django.contrib import admin
    from django.db import models
    
    
    class Person(models.Model):
        name = models.CharField(max_length=50)
        birthday = models.DateField()
    
        @admin.display(description="Birth decade")
        def decade_born_in(self):
            decade = self.birthday.year // 10 * 10
            return f"{decade}’s"
    
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ["name", "decade_born_in"]
    

Обратите внимание на несколько особенностей list_display:

  • Если поле является ForeignKey, Django отобразит __str__() связанного объекта.
  • Поля ManyToManyField не поддерживаются, поскольку для этого пришлось бы выполнять отдельный SQL-запрос для каждой строки таблицы. Если вы всё же хотите это сделать, добавьте в модель пользовательский метод и включите его имя в list_display. (Подробнее о пользовательских методах в list_display см. ниже.)
  • Если поле является BooleanField, Django отобразит вместо True, False или None соответствующий значок: «да», «нет» или «неизвестно».
  • Если указанная строка представляет метод модели, ModelAdmin или вызываемый объект, Django по умолчанию экранирует HTML в результате. Чтобы экранировать пользовательский ввод и использовать собственные неэкранированные теги, применяйте format_html().

    Вот полный пример модели:

    from django.contrib import admin
    from django.db import models
    from django.utils.html import format_html
    
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
        color_code = models.CharField(max_length=6)
    
        @admin.display
        def colored_name(self):
            return format_html(
                '<span style="color: #{};">{} {}</span>',
                self.color_code,
                self.first_name,
                self.last_name,
            )
    
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ["first_name", "last_name", "colored_name"]
    
  • Как уже показывают некоторые примеры, при использовании вызываемого объекта, метода модели или метода ModelAdmin можно настроить заголовок столбца: оберните вызываемый объект декоратором display() и передайте аргумент description.
  • Если значение поля равно None, является пустой строкой или представляет собой пустой итерируемый объект, Django отобразит - (тире). Это можно переопределить с помощью AdminSite.empty_value_display:

    from django.contrib import admin
    
    admin.site.empty_value_display = "(None)"
    

    Можно также использовать ModelAdmin.empty_value_display:

    class PersonAdmin(admin.ModelAdmin):
        empty_value_display = "unknown"
    

    Или задать значение для отдельного поля:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ["name", "birth_date_view"]
    
        @admin.display(empty_value="unknown")
        def birth_date_view(self, obj):
            return obj.birth_date
    
  • Если указанная строка представляет метод модели, ModelAdmin или вызываемый объект, возвращающий True, False или None, Django отобразит соответствующий значок: «да», «нет» или «неизвестно», если обернуть метод декоратором display(), передав аргумент boolean со значением True:

    from django.contrib import admin
    from django.db import models
    
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        birthday = models.DateField()
    
        @admin.display(boolean=True)
        def born_in_fifties(self):
            return 1950 <= self.birthday.year < 1960
    
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ["name", "born_in_fifties"]
    
  • Метод __str__() в list_display ничем не отличается от любого другого метода модели, поэтому вполне допустимо поступить так:

    list_display = ["__str__", "some_other_field"]
    
  • Как правило, элементы list_display, которые не являются реальными полями базы данных, нельзя использовать для сортировки (поскольку Django выполняет сортировку на уровне базы данных).

    Однако если элемент list_display представляет определённое поле базы данных, это можно указать с помощью декоратора display(), передав аргумент ordering:

    from django.contrib import admin
    from django.db import models
    from django.utils.html import format_html
    
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        color_code = models.CharField(max_length=6)
    
        @admin.display(ordering="first_name")
        def colored_first_name(self):
            return format_html(
                '<span style="color: #{};">{}</span>',
                self.color_code,
                self.first_name,
            )
    
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ["first_name", "colored_first_name"]
    

    В приведённом примере Django будет сортировать по полю first_name при попытке отсортировать список по colored_first_name в административном интерфейсе.

    Чтобы указать сортировку по убыванию с помощью аргумента ordering, добавьте дефис перед именем поля. В приведённом примере это будет выглядеть так:

    @admin.display(ordering="-first_name")
    def colored_first_name(self): ...
    

    Аргумент ordering поддерживает поиски по запросу для сортировки по значениям связанных моделей. В этом примере в отображение списка добавляется столбец «имя автора», который можно сортировать по имени:

    class Blog(models.Model):
        title = models.CharField(max_length=255)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)
    
    
    class BlogAdmin(admin.ModelAdmin):
        list_display = ["title", "author", "author_first_name"]
    
        @admin.display(ordering="author__first_name")
        def author_first_name(self, obj):
            return obj.author.first_name
    

    С аргументом ordering можно использовать выражения запросов:

    from django.db.models import Value
    from django.db.models.functions import Concat
    
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        @admin.display(ordering=Concat("first_name", Value(" "), "last_name"))
        def full_name(self):
            return self.first_name + " " + self.last_name
    
  • Элементы list_display также могут быть свойствами

    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        @property
        @admin.display(
            ordering="last_name",
            description="Full name of the person",
            boolean=False,
        )
        def full_name(self):
            return self.first_name + " " + self.last_name
    
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ["full_name"]
    

    Обратите внимание, что @property должен располагаться выше @display. Если вы используете старый способ — задаёте атрибуты отображения напрямую, а не с помощью декоратора display(), — учтите, что нужно использовать функцию property(), а не декоратор @property:

    def my_property(self):
        return self.first_name + " " + self.last_name
    
    
    my_property.short_description = "Full name of the person"
    my_property.admin_order_field = "last_name"
    my_property.boolean = False
    
    full_name = property(my_property)
    
  • Имена полей в list_display также появятся в HTML-выводе в виде CSS-классов: column-<field_name> для каждого элемента <th>. Например, это можно использовать для задания ширины столбцов в CSS-файле.
  • Django будет интерпретировать каждый элемент list_display в следующем порядке:

    • Поле модели или связанное поле.
    • Вызываемый объект.
    • Строка, представляющая атрибут ModelAdmin.
    • Строка, представляющая атрибут модели.

    Например, если first_name является и полем модели, и атрибутом ModelAdmin, будет использовано поле модели.

ModelAdmin.list_display_links

Используйте list_display_links, чтобы указать, какие поля из list_display должны ссылаться на страницу изменения объекта.

По умолчанию на странице списка изменений первая колонка — первое поле, указанное в list_display, — ссылается на страницу изменения соответствующего элемента. Параметр list_display_links позволяет изменить это поведение:

  • Задайте значение None, чтобы отключить все ссылки.
  • Задайте список или кортеж полей (в том же формате, что и list_display), столбцы которых нужно превратить в ссылки.

    Можно указать одно или несколько полей. Если поля присутствуют в list_display, Django не ограничивает количество полей, на которые можно добавить ссылки. Единственное требование: чтобы использовать list_display_links таким образом, необходимо определить list_display.

В этом примере на странице списка изменений поля first_name и last_name будут ссылками:

class PersonAdmin(admin.ModelAdmin):
    list_display = ["first_name", "last_name", "birthday"]
    list_display_links = ["first_name", "last_name"]

В этом примере в таблице на странице списка изменений не будет ссылок:

class AuditEntryAdmin(admin.ModelAdmin):
    list_display = ["timestamp", "message"]
    list_display_links = None
ModelAdmin.list_editable

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

Примечание

list_editable определённым образом взаимодействует с несколькими другими параметрами. Обратите внимание на следующие правила:

  • Любое поле из list_editable должно также присутствовать в list_display. Нельзя редактировать поле, которое не отображается!
  • Одно и то же поле нельзя указывать одновременно в list_editable и list_display_links: поле не может быть одновременно элементом формы и ссылкой.

При нарушении любого из этих правил возникнет ошибка проверки.

ModelAdmin.list_filter

Задайте list_filter, чтобы включить фильтры в правой боковой панели страницы списка изменений административного интерфейса.

В простейшем случае list_filter принимает список или кортеж имён полей, по которым нужно включить фильтрацию, но доступны и более сложные варианты. Подробности см. в разделе Фильтры списков ModelAdmin.

ModelAdmin.list_max_show_all

Задайте list_max_show_all, чтобы определить максимальное число элементов на странице списка изменений административного интерфейса с включённым режимом «Показать все». Ссылка «Показать все» появится на странице списка изменений, только если общее число результатов не превышает это значение. По умолчанию оно равно 200.

ModelAdmin.list_per_page

Задайте list_per_page, чтобы определить число элементов на каждой странице списка изменений административного интерфейса с постраничной навигацией. По умолчанию оно равно 100.

ModelAdmin.list_select_related

Установите list_select_related, чтобы указать Django использовать select_related() при получении списка объектов на странице списка изменений в админке. Это поможет сократить количество запросов к базе данных.

Значением должен быть логический тип, список или кортеж. По умолчанию используется False.

Если значение — True, select_related() будет вызываться всегда. Если задано значение False, Django проверит list_display и вызовет select_related(), если присутствует хотя бы один ForeignKey.

Если вам нужен более точный контроль, используйте кортеж (или список) в качестве значения list_select_related. Пустой кортеж не позволит Django вызывать select_related. Любой другой кортеж будет напрямую передан в select_related в качестве параметров. Например:

class ArticleAdmin(admin.ModelAdmin):
    list_select_related = ["author", "category"]

вызовет select_related('author', 'category').

Если нужно задать динамическое значение на основе запроса, можно реализовать метод get_list_select_related().

Примечание

ModelAdmin игнорирует этот атрибут, если select_related() уже был вызван для QuerySet списка изменений.

ModelAdmin.ordering

Установите ordering, чтобы указать порядок сортировки списков объектов в представлениях админки Django. Значением должен быть список или кортеж в том же формате, что и параметр ordering модели.

Если это значение не задано, админка Django будет использовать порядок сортировки модели по умолчанию.

Если нужно задать динамический порядок сортировки (например, в зависимости от пользователя или языка), можно реализовать метод get_ordering().

Вопросы производительности при упорядочивании и сортировке

Чтобы обеспечить детерминированный порядок результатов, список изменений добавляет pk к порядку сортировки, если не находит единственное или уникальное сочетание полей, задающее полный порядок.

Например, если порядок сортировки по умолчанию задан по неуникальному полю name, список изменений сортируется по name и pk. Это может работать медленно при большом количестве строк, если для name и pk не создан индекс.

ModelAdmin.paginator

Класс пагинатора, используемый для разбиения на страницы. По умолчанию используется django.core.paginator.Paginator. Если пользовательский класс пагинатора не имеет такого же интерфейса конструктора, как django.core.paginator.Paginator, необходимо также предоставить реализацию ModelAdmin.get_paginator().

ModelAdmin.prepopulated_fields

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

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ["title"]}

При задании этого параметра указанные поля будут заполняться с помощью JavaScript на основе назначенных полей. Чаще всего эта возможность используется для автоматической генерации значений полей SlugField на основе одного или нескольких других полей. Значение генерируется путем объединения значений исходных полей с последующим преобразованием результата в допустимый слаг (например, пробелы заменяются дефисами, а буквы ASCII переводятся в нижний регистр).

После сохранения значения JavaScript больше не изменяет предварительно заполненные поля. Обычно нежелательно, чтобы слаги менялись (если слаг входит в URL объекта, это приведет к изменению URL).

prepopulated_fields не принимает поля DateTimeField, ForeignKey, OneToOneField и ManyToManyField.

ModelAdmin.preserve_filters

По умолчанию примененные фильтры сохраняются в представлении списка после создания, редактирования или удаления объекта. Чтобы сбрасывать фильтры, установите для этого атрибута значение False.

ModelAdmin.show_facets

Определяет, отображаются ли счетчики фасетов для фильтров в списке изменений админки. По умолчанию используется ShowFacets.ALLOW.

При отображении счетчики фасетов обновляются с учетом текущих фильтров.

class ShowFacets

Перечисление допустимых значений для ModelAdmin.show_facets.

ALWAYS

Всегда отображать счетчики фасетов.

ALLOW

Отображать счетчики фасетов, если указан параметр строки запроса _facets.

NEVER

Никогда не отображать счетчики фасетов.

Задайте для show_facets нужное значение ShowFacets. Например, чтобы всегда отображать счетчики фасетов без указания параметра запроса:

from django.contrib import admin


class MyModelAdmin(admin.ModelAdmin):
    ...
    # Have facets always shown for this model admin.
    show_facets = admin.ShowFacets.ALWAYS

Вопросы производительности при использовании фасетов

Включение фильтров с фасетами увеличит количество запросов на странице списка изменений админки пропорционально числу фильтров. Эти запросы могут привести к проблемам с производительностью, особенно при работе с большими наборами данных. В таких случаях может быть целесообразно задать для show_facets значение ShowFacets.NEVER, чтобы полностью отключить фасеты.

ModelAdmin.radio_fields

По умолчанию админка Django использует для полей интерфейс с раскрывающимся списком (<select>), если они имеют тип ForeignKey или для них задано choices. Если поле указано в radio_fields, Django вместо этого использует интерфейс с переключателями. Предположим, что group — это ForeignKey модели Person:

class PersonAdmin(admin.ModelAdmin):
    radio_fields = {"group": admin.VERTICAL}

Можно выбрать HORIZONTAL или VERTICAL из модуля django.contrib.admin.

Не добавляйте поле в radio_fields, если оно не имеет тип ForeignKey и для него не задано choices.

ModelAdmin.autocomplete_fields

autocomplete_fields — это список полей ForeignKey и/или ManyToManyField, для которых нужно использовать поля автозаполнения Select2.

По умолчанию для этих полей админка использует интерфейс с раскрывающимся списком (<select>). Иногда нежелательно нести накладные расходы, связанные с выборкой всех связанных экземпляров для отображения в списке.

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

В ModelAdmin связанного объекта необходимо определить search_fields, поскольку оно используется для поиска в поле автозаполнения.

Чтобы предотвратить раскрытие данных неавторизованным пользователям, для использования автозаполнения им необходимо иметь разрешение view или change на связанный объект.

Сортировка и разбиение результатов на страницы управляются методами get_ordering() и get_paginator() связанного ModelAdmin.

В следующем примере у ChoiceAdmin есть поле автозаполнения для ForeignKey, связанного с Question. Результаты фильтруются по полю question_text и сортируются по полю date_created:

class QuestionAdmin(admin.ModelAdmin):
    ordering = ["date_created"]
    search_fields = ["question_text"]


class ChoiceAdmin(admin.ModelAdmin):
    autocomplete_fields = ["question"]

Вопросы производительности при работе с большими наборами данных

Сортировка с помощью ModelAdmin.ordering может привести к проблемам с производительностью, поскольку сортировка большого набора запросов будет выполняться медленно.

Кроме того, если среди полей поиска есть поля, для которых база данных не создала индексы, на очень больших таблицах производительность может оказаться низкой.

В таких случаях рекомендуется реализовать собственный метод ModelAdmin.get_search_results(), использующий полнотекстовый поиск по индексированным данным.

Для очень больших таблиц также может понадобиться изменить Paginator, поскольку пагинатор по умолчанию всегда выполняет запрос count(). Например, можно переопределить реализацию свойства Paginator.count по умолчанию.

ModelAdmin.raw_id_fields

По умолчанию админка Django использует для полей ForeignKey интерфейс с раскрывающимся списком (<select>). Иногда нежелательно нести накладные расходы, связанные с выборкой всех связанных экземпляров для отображения в раскрывающемся списке.

raw_id_fields — это список полей, для которых вместо этого нужно использовать виджет Input в случае ForeignKey или ManyToManyField:

class ArticleAdmin(admin.ModelAdmin):
    raw_id_fields = ["newspaper"]

В виджете raw_id_fields Input должен содержаться первичный ключ, если поле имеет тип ForeignKey, или список значений, разделенных запятыми, если поле имеет тип ManyToManyField. Виджет raw_id_fields отображает рядом с полем кнопку с лупой, позволяющую пользователям найти и выбрать значение:

../../../_images/raw_id_fields.png
ModelAdmin.readonly_fields

По умолчанию админка отображает все поля доступными для редактирования. Данные всех полей, указанных в этом параметре (значением должен быть list или tuple), будут отображаться как есть и без возможности редактирования; кроме того, эти поля исключаются из ModelForm, используемой для создания и редактирования. Обратите внимание: при указании ModelAdmin.fields или ModelAdmin.fieldsets поля только для чтения необходимо включить в список, чтобы они отображались (в противном случае они игнорируются).

Если readonly_fields используется без явного указания порядка с помощью ModelAdmin.fields или ModelAdmin.fieldsets, такие поля будут добавлены в конец, после всех редактируемых полей.

Поле только для чтения может отображать не только данные поля модели, но и результат выполнения метода модели или метода самого класса ModelAdmin. Это работает очень похоже на ModelAdmin.list_display. Так можно использовать интерфейс админки для отображения состояния редактируемых объектов, например:

from django.contrib import admin
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe


class PersonAdmin(admin.ModelAdmin):
    readonly_fields = ["address_report"]

    # description functions like a model field's verbose_name
    @admin.display(description="Address")
    def address_report(self, instance):
        # assuming get_full_address() returns a list of strings
        # for each line of the address and you want to separate each
        # line by a linebreak
        return format_html_join(
            mark_safe("<br>"),
            "{}",
            ((line,) for line in instance.get_full_address()),
        ) or mark_safe("<span class='errors'>I can't determine this address.</span>")
ModelAdmin.save_as

Установите save_as, чтобы включить функцию «сохранить как новый» в формах редактирования админки.

Обычно для объектов доступны три варианта сохранения: «Сохранить», «Сохранить и продолжить редактирование» и «Сохранить и добавить другой». Если save_as имеет значение True, кнопка «Сохранить и добавить другой» будет заменена кнопкой «Сохранить как новый», которая создаст новый объект (с новым идентификатором), а не обновит существующий.

По умолчанию save_as имеет значение False.

ModelAdmin.save_as_continue

При включенном параметре save_as=True после сохранения нового объекта по умолчанию выполняется перенаправление на страницу редактирования этого объекта. Если задать save_as_continue=False, перенаправление будет вести на страницу списка изменений.

По умолчанию save_as_continue имеет значение True.

ModelAdmin.save_on_top

Установите save_on_top, чтобы добавить кнопки сохранения в верхнюю часть форм редактирования админки.

Обычно кнопки сохранения отображаются только в нижней части форм. Если задать save_on_top, кнопки будут отображаться и вверху, и внизу.

По умолчанию save_on_top имеет значение False.

ModelAdmin.search_fields

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

Это должны быть поля текстового типа, например CharField или TextField. Также можно выполнять поиск по связанным объектам типа ForeignKey или ManyToManyField, используя нотацию «перехода» API поиска:

search_fields = ["foreign_key__related_fieldname"]

Например, если у записи блога есть автор, следующее определение позволит искать записи блога по адресу электронной почты автора:

search_fields = ["user__email"]

Когда пользователь выполняет поиск в поле поиска админки, Django разбивает запрос на слова и возвращает все объекты, содержащие каждое из этих слов без учета регистра (используя поиск icontains), причем каждое слово должно присутствовать хотя бы в одном из полей search_fields. Например, если search_fields задано как ['first_name', 'last_name'] и пользователь ищет john lennon, Django выполнит SQL-условие WHERE, эквивалентное следующему:

WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

Поисковый запрос может содержать фразы в кавычках с пробелами. Например, если пользователь ищет "john winston" или 'john winston', Django выполнит SQL-условие WHERE, эквивалентное следующему:

WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')

Если вы не хотите использовать icontains в качестве условия поиска, можно использовать любое условие, добавив его к имени поля. Например, можно использовать exact, задав search_fields как ['first_name__exact'].

Также доступны некоторые (устаревшие) сокращения для задания условия поиска. Можно добавить к полю в search_fields один из следующих символов, что эквивалентно добавлению к полю __<lookup>:

Префикс

Условие поиска

^

istartswith

=

iexact

@

search

None

icontains

Чтобы настроить поиск, используйте ModelAdmin.get_search_results() для реализации дополнительного или альтернативного поведения поиска.

ModelAdmin.search_help_text

Установите search_help_text, чтобы задать поясняющий текст для поля поиска, который будет отображаться под ним.

ModelAdmin.show_full_result_count

Установите show_full_result_count, чтобы определить, следует ли отображать полное количество объектов на отфильтрованной странице админки (например, 99 results (103 total)). Если для этого параметра задано значение False, вместо этого отображается текст вроде 99 results (Show all).

Значение show_full_result_count=True по умолчанию приводит к выполнению запроса для подсчета всех записей в таблице, что может быть затратным, если таблица содержит большое количество строк.

ModelAdmin.sortable_by

По умолчанию на странице списка изменений разрешена сортировка по всем полям модели (а также вызываемым объектам, для которых в декораторе display() указан аргумент ordering или задан атрибут admin_order_field), перечисленным в list_display.

Чтобы отключить сортировку для некоторых столбцов, задайте для sortable_by набор (например, list, tuple или set), содержащий подмножество элементов list_display, которые должны поддерживать сортировку. Пустой набор отключает сортировку для всех столбцов.

Если этот список нужно задавать динамически, реализуйте вместо этого метод get_sortable_by().

ModelAdmin.view_on_site

Установите view_on_site, чтобы определить, отображать ли ссылку «Посмотреть на сайте». Эта ссылка должна вести на URL, по которому можно просмотреть сохраненный объект.

Значением может быть логический флаг или вызываемый объект. Если задано True (значение по умолчанию), URL создается с помощью метода get_absolute_url() объекта.

Если у модели есть метод get_absolute_url(), но вы не хотите отображать кнопку «Посмотреть на сайте», достаточно задать для view_on_site значение False:

from django.contrib import admin


class PersonAdmin(admin.ModelAdmin):
    view_on_site = False

Если это вызываемый объект, он принимает экземпляр модели в качестве параметра. Например:

from django.contrib import admin
from django.urls import reverse


class PersonAdmin(admin.ModelAdmin):
    def view_on_site(self, obj):
        url = reverse("person-detail", kwargs={"slug": obj.slug})
        return "https://example.com" + url

Параметры пользовательских шаблонов

В разделе Переопределение шаблонов админки описано, как переопределить или расширить шаблоны админки по умолчанию. Используйте следующие параметры, чтобы переопределить шаблоны по умолчанию, применяемые представлениями ModelAdmin:

ModelAdmin.add_form_template

Путь к пользовательскому шаблону, используемому в add_view().

ModelAdmin.change_form_template

Путь к пользовательскому шаблону, используемому в change_view().

ModelAdmin.change_list_template

Путь к пользовательскому шаблону, используемому в changelist_view().

ModelAdmin.delete_confirmation_template

Путь к пользовательскому шаблону, используемому в delete_view() для отображения страницы подтверждения при удалении одного или нескольких объектов.

ModelAdmin.delete_selected_confirmation_template

Путь к пользовательскому шаблону, используемому методом действия delete_selected для отображения страницы подтверждения при удалении одного или нескольких объектов. См. документацию по действиям.

ModelAdmin.object_history_template

Путь к пользовательскому шаблону, используемому в history_view().

ModelAdmin.popup_response_template

Путь к пользовательскому шаблону, используемому в response_add(), response_change() и response_delete().

ModelAdmin методы

Предупреждение

При переопределении ModelAdmin.save_model() и ModelAdmin.delete_model() ваш код должен сохранять или удалять объект. Эти методы предназначены не для запрета действий, а для выполнения дополнительных операций.

ModelAdmin.save_model(request, obj, form, change) [источник]

Метод save_model получает HttpRequest, экземпляр модели, экземпляр ModelForm и логическое значение, определяющее, добавляется или изменяется объект. Переопределение этого метода позволяет выполнять операции до или после сохранения. Вызовите super().save_model(), чтобы сохранить объект с помощью Model.save().

Например, чтобы добавить request.user к объекту перед сохранением:

from django.contrib import admin


class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super().save_model(request, obj, form, change)
ModelAdmin.delete_model(request, obj) [источник]

Метод delete_model получает HttpRequest и экземпляр модели. Переопределение этого метода позволяет выполнять операции до или после удаления. Вызовите super().delete_model(), чтобы удалить объект с помощью Model.delete().

ModelAdmin.delete_queryset(request, queryset) [источник]

Метод delete_queryset() получает HttpRequest и QuerySet объектов, подлежащих удалению. Переопределите этот метод, чтобы настроить процесс удаления для действия «удалить выбранные объекты».

ModelAdmin.save_formset(request, form, formset, change) [источник]

Метод save_formset получает HttpRequest, родительский экземпляр ModelForm и логическое значение, определяющее, добавляется или изменяется родительский объект.

Например, чтобы добавить request.user к каждому изменённому экземпляру модели в наборе форм:

class ArticleAdmin(admin.ModelAdmin):
    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        for obj in formset.deleted_objects:
            obj.delete()
        for instance in instances:
            instance.user = request.user
            instance.save()
        formset.save_m2m()

См. также Сохранение объектов в наборе форм.

Предупреждение

Все хуки, возвращающие свойство ModelAdmin, возвращают само свойство, а не копию его значения. Динамическое изменение значения может привести к неожиданным результатам.

Рассмотрим в качестве примера ModelAdmin.get_readonly_fields():

class PersonAdmin(admin.ModelAdmin):
    readonly_fields = ["name"]

    def get_readonly_fields(self, request, obj=None):
        readonly = super().get_readonly_fields(request, obj)
        if not request.user.is_superuser:
            readonly.append("age")  # Edits the class attribute.
        return readonly

В результате readonly_fields становится ["name", "age", "age", ...] даже для суперпользователя, поскольку "age" добавляется каждый раз, когда страницу посещает пользователь, не являющийся суперпользователем.

ModelAdmin.get_ordering(request)

Метод get_ordering принимает request в качестве параметра и должен возвращать list или tuple для сортировки, аналогично атрибуту ordering. Например:

class PersonAdmin(admin.ModelAdmin):
    def get_ordering(self, request):
        if request.user.is_superuser:
            return ["name", "rank"]
        else:
            return ["name"]
ModelAdmin.get_search_results(request, queryset, search_term) [источник]

Метод get_search_results изменяет список отображаемых объектов, оставляя в нём только те, которые соответствуют заданному поисковому запросу. Он принимает запрос, queryset с применёнными текущими фильтрами и поисковый запрос, введённый пользователем. Метод возвращает кортеж, содержащий queryset, изменённый для выполнения поиска, и логическое значение, указывающее, могут ли результаты содержать дубликаты.

Реализация по умолчанию выполняет поиск по полям, указанным в ModelAdmin.search_fields.

Этот метод можно переопределить собственной реализацией поиска. Например, может потребоваться выполнять поиск по целочисленному полю или использовать внешний инструмент, например Solr или Haystack. Необходимо определить, могут ли изменения queryset, внесённые вашим методом поиска, приводить к появлению дубликатов в результатах, и вернуть True во втором элементе возвращаемого значения.

Например, для поиска по name и age можно использовать:

class PersonAdmin(admin.ModelAdmin):
    list_display = ["name", "age"]
    search_fields = ["name"]

    def get_search_results(self, request, queryset, search_term):
        queryset, may_have_duplicates = super().get_search_results(
            request,
            queryset,
            search_term,
        )
        try:
            search_term_as_int = int(search_term)
        except ValueError:
            pass
        else:
            queryset |= self.model.objects.filter(age=search_term_as_int)
        return queryset, may_have_duplicates

Эта реализация эффективнее, чем search_fields = ('name', '=age'), которая приводит к сравнению строк для числового поля, например ... OR UPPER("polls_choice"."votes"::text) = UPPER('4') в PostgreSQL.

ModelAdmin.save_related(request, form, formsets, change) [источник]

Метод save_related получает HttpRequest, родительский экземпляр ModelForm, список встроенных наборов форм и логическое значение, определяющее, добавляется или изменяется родительский объект. Здесь можно выполнять любые операции до или после сохранения объектов, связанных с родительским объектом. Обратите внимание: к этому моменту родительский объект и его форма уже сохранены.

ModelAdmin.get_autocomplete_fields(request)

Метод get_autocomplete_fields() получает HttpRequest и должен возвращать list или tuple имён полей, которые будут отображаться с виджетом автодополнения, описанным выше в разделе ModelAdmin.autocomplete_fields.

ModelAdmin.get_readonly_fields(request, obj=None)

Метод get_readonly_fields получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать list или tuple имён полей, которые будут отображаться только для чтения, как описано выше в разделе ModelAdmin.readonly_fields.

ModelAdmin.get_prepopulated_fields(request, obj=None)

Метод get_prepopulated_fields получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать dictionary, как описано выше в разделе ModelAdmin.prepopulated_fields.

ModelAdmin.get_list_display(request) [источник]

Метод get_list_display получает HttpRequest и должен возвращать list или tuple имён полей, которые будут отображаться на странице списка изменений, как описано выше в разделе ModelAdmin.list_display.

ModelAdmin.get_list_display_links(request, list_display) [источник]

Метод get_list_display_links получает HttpRequest и list или tuple, возвращённый методом ModelAdmin.get_list_display(). Он должен возвращать либо None, либо list или tuple имён полей на странице списка изменений, которые будут ссылаться на страницу изменения объекта, как описано в разделе ModelAdmin.list_display_links.

ModelAdmin.get_exclude(request, obj=None)

Метод get_exclude получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать список полей, как описано в ModelAdmin.exclude.

ModelAdmin.get_fields(request, obj=None)

Метод get_fields получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать список полей, как описано выше в разделе ModelAdmin.fields.

ModelAdmin.get_fieldsets(request, obj=None)

Метод get_fieldsets получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать список 2-кортежей, каждый из которых представляет <fieldset> на странице формы администратора, как описано выше в разделе ModelAdmin.fieldsets.

ModelAdmin.get_list_filter(request) [источник]

Метод get_list_filter получает HttpRequest и должен возвращать последовательность того же типа, что и для атрибута list_filter.

ModelAdmin.get_list_select_related(request) [источник]

Метод get_list_select_related получает HttpRequest и должен возвращать логическое значение или список, как это делает ModelAdmin.list_select_related.

ModelAdmin.get_search_fields(request) [источник]

Метод get_search_fields получает HttpRequest и должен возвращать последовательность того же типа, что и для атрибута search_fields.

ModelAdmin.get_sortable_by(request)

Метод get_sortable_by() получает HttpRequest и должен возвращать коллекцию (например, list, tuple или set) имён полей, по которым можно сортировать на странице списка изменений.

По умолчанию метод возвращает sortable_by, если он задан; в противном случае метод использует get_list_display().

Например, чтобы запретить сортировку по одному или нескольким столбцам:

class PersonAdmin(admin.ModelAdmin):
    def get_sortable_by(self, request):
        return {*self.get_list_display(request)} - {"rank"}
ModelAdmin.get_inline_instances(request, obj=None) [источник]

Метод get_inline_instances получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать list или tuple объектов InlineModelAdmin, как описано ниже в разделе InlineModelAdmin. Например, следующий код возвращает встроенные формы без фильтрации по умолчанию на основе разрешений на добавление, изменение, удаление и просмотр:

class MyModelAdmin(admin.ModelAdmin):
    inlines = [MyInline]

    def get_inline_instances(self, request, obj=None):
        return [inline(self.model, self.admin_site) for inline in self.inlines]

Если вы переопределяете этот метод, убедитесь, что возвращаемые встроенные формы являются экземплярами классов, определённых в inlines, иначе при добавлении связанных объектов может возникнуть ошибка «Bad Request».

ModelAdmin.get_inlines(request, obj)

Метод get_inlines получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать итерируемый объект со встроенными формами. Можно переопределить этот метод, чтобы динамически добавлять встроенные формы в зависимости от запроса или экземпляра модели, вместо того чтобы указывать их в ModelAdmin.inlines.

ModelAdmin.get_urls() [источник]

Метод get_urls объекта ModelAdmin возвращает URL-адреса, используемые для этого ModelAdmin, аналогично URLconf. Поэтому их можно расширить, как описано в разделе Диспетчер URL-адресов, используя обёртку AdminSite.admin_view() для представлений:

from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path


class MyModelAdmin(admin.ModelAdmin):
    def get_urls(self):
        urls = super().get_urls()
        my_urls = [path("my_view/", self.admin_site.admin_view(self.my_view))]
        return my_urls + urls

    def my_view(self, request):
        # ...
        context = dict(
            # Include common variables for rendering the admin template.
            self.admin_site.each_context(request),
            # Anything else you want in the context...
            key=value,
        )
        return TemplateResponse(request, "sometemplate.html", context)

Если вы хотите использовать макет административной панели, унаследуйте класс от admin/base_site.html:

{% extends "admin/base_site.html" %}
{% block content %}
...
{% endblock %}

Примечание

Обратите внимание, что функция self.my_view обёрнута в self.admin_site.admin_view. Это важно, поскольку обеспечивает два условия:

  1. Выполняются проверки разрешений, гарантирующие, что доступ к представлению есть только у активных сотрудников.
  2. Применяется декоратор django.views.decorators.cache.never_cache(), предотвращающий кэширование и гарантирующий актуальность возвращаемой информации.

Примечание

Обратите внимание, что пользовательские шаблоны включаются до стандартных URL-адресов административной панели: шаблоны URL-адресов администратора очень широкие и соответствуют почти чему угодно, поэтому пользовательские URL-адреса обычно следует размещать перед встроенными.

В этом примере доступ к my_view будет осуществляться по адресу /admin/myapp/mymodel/my_view/ (при условии, что URL-адреса административной панели включены в /admin/.)

Если страницу можно кэшировать, но при этом требуется выполнять проверку разрешений, можно передать аргумент cacheable=True в AdminSite.admin_view():

path("my_view/", self.admin_site.admin_view(self.my_view, cacheable=True))

Представления ModelAdmin имеют атрибуты model_admin. Другие представления AdminSite имеют атрибуты admin_site.

ModelAdmin.get_form(request, obj=None, **kwargs) [источник]

Возвращает класс ModelForm для использования в представлениях добавления и изменения административной панели; см. add_view() и change_view().

Базовая реализация использует modelform_factory() для создания подкласса form, изменённого такими атрибутами, как fields и exclude. Например, если требуется предоставить суперпользователям дополнительные поля, можно заменить базовую форму следующим образом:

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_superuser:
            kwargs["form"] = MySuperuserForm
        return super().get_form(request, obj, **kwargs)

Также можно напрямую вернуть пользовательский класс ModelForm.

ModelAdmin.get_formsets_with_inlines(request, obj=None) [источник]

Выдаёт пары (FormSet, InlineModelAdmin) для использования в представлениях добавления и изменения административной панели.

Например, если требуется отображать определённую встроенную форму только в представлении изменения, можно переопределить get_formsets_with_inlines следующим образом:

class MyModelAdmin(admin.ModelAdmin):
    inlines = [MyInline, SomeOtherInline]

    def get_formsets_with_inlines(self, request, obj=None):
        for inline in self.get_inline_instances(request, obj):
            # hide MyInline in the add view
            if not isinstance(inline, MyInline) or obj is not None:
                yield inline.get_formset(request, obj), inline
ModelAdmin.formfield_for_foreignkey(db_field, request, **kwargs)

Метод formfield_for_foreignkey класса ModelAdmin позволяет переопределить стандартное поле формы для поля внешнего ключа. Например, чтобы возвращать подмножество объектов для этого поля внешнего ключа в зависимости от пользователя:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "car":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

В этом примере экземпляр HttpRequest используется для фильтрации поля внешнего ключа Car, чтобы отображались только автомобили, принадлежащие экземпляру User.

Для более сложной фильтрации можно использовать метод ModelForm.__init__(), чтобы фильтровать по instance модели (см. Поля для работы со связями). Например:

class CountryAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["capital"].queryset = self.instance.cities.all()


class CountryAdmin(admin.ModelAdmin):
    form = CountryAdminForm
ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)

Как и метод formfield_for_foreignkey, метод formfield_for_manytomany можно переопределить, чтобы изменить стандартное поле формы для поля «многие ко многим». Например, если владелец может владеть несколькими автомобилями, а автомобили могут принадлежать нескольким владельцам — то есть используется связь «многие ко многим», — можно отфильтровать поле внешнего ключа Car, чтобы отображались только автомобили, принадлежащие User:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "cars":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super().formfield_for_manytomany(db_field, request, **kwargs)
ModelAdmin.formfield_for_choice_field(db_field, request, **kwargs)

Как и методы formfield_for_foreignkey и formfield_for_manytomany, метод formfield_for_choice_field можно переопределить, чтобы изменить стандартное поле формы для поля с объявленными вариантами выбора. Например, если варианты выбора для суперпользователя должны отличаться от вариантов для обычных сотрудников, можно поступить следующим образом:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_choice_field(self, db_field, request, **kwargs):
        if db_field.name == "status":
            kwargs["choices"] = [
                ("accepted", "Accepted"),
                ("denied", "Denied"),
            ]
            if request.user.is_superuser:
                kwargs["choices"].append(("ready", "Ready for deployment"))
        return super().formfield_for_choice_field(db_field, request, **kwargs)

Ограничения choices

Любой атрибут choices, заданный для поля формы, будет действовать только для этого поля формы. Если для соответствующего поля модели заданы варианты выбора, варианты, предоставляемые форме, должны быть допустимым подмножеством этих вариантов; в противном случае отправка формы завершится ошибкой ValidationError при проверке модели перед сохранением.

ModelAdmin.get_changelist(request, **kwargs) [источник]

Возвращает класс Changelist для отображения списка. По умолчанию используется django.contrib.admin.views.main.ChangeList. Наследуя этот класс, можно изменить поведение списка.

ModelAdmin.get_changelist_form(request, **kwargs) [источник]

Возвращает класс ModelForm для использования в Formset на странице списка изменений. Например, чтобы использовать пользовательскую форму:

from django import forms


class MyForm(forms.ModelForm):
    pass


class MyModelAdmin(admin.ModelAdmin):
    def get_changelist_form(self, request, **kwargs):
        return MyForm

Не указывайте атрибут Meta.model

Если вы определяете атрибут Meta.model в ModelForm, необходимо также определить атрибут Meta.fields (или атрибут Meta.exclude). Однако ModelAdmin игнорирует это значение и переопределяет его атрибутом ModelAdmin.list_editable. Проще всего не указывать атрибут Meta.model, поскольку ModelAdmin предоставит правильную модель для использования.

ModelAdmin.get_changelist_formset(request, **kwargs) [источник]

Возвращает класс ModelFormSet для использования на странице списка изменений, если используется list_editable. Например, чтобы использовать пользовательский набор форм:

from django.forms import BaseModelFormSet


class MyAdminFormSet(BaseModelFormSet):
    pass


class MyModelAdmin(admin.ModelAdmin):
    def get_changelist_formset(self, request, **kwargs):
        kwargs["formset"] = MyAdminFormSet
        return super().get_changelist_formset(request, **kwargs)
ModelAdmin.lookup_allowed(lookup, value, request)

Объекты на странице списка изменений можно фильтровать с помощью условий поиска из строки запроса URL. Например, так работает list_filter. Условия поиска похожи на те, что используются в QuerySet.filter() (например, user__email=user@example.com). Поскольку пользователь может изменять условия поиска в строке запроса, их необходимо проверять, чтобы предотвратить несанкционированное раскрытие данных.

Метод lookup_allowed() получает путь условия поиска из строки запроса (например, 'user__email'), соответствующее значение (например, 'user@example.com') и запрос, а затем возвращает логическое значение, указывающее, разрешена ли фильтрация QuerySet списка изменений с использованием этих параметров. Если lookup_allowed() возвращает False, вызывается DisallowedModelAdminLookup (подкласс SuspiciousOperation).

По умолчанию lookup_allowed() разрешает доступ к локальным полям модели, путям полей, используемым в list_filter (но не к путям из get_list_filter()), а также к условиям поиска, необходимым для правильной работы limit_choices_to в raw_id_fields.

Переопределите этот метод, чтобы настроить допустимые условия поиска для подкласса ModelAdmin.

ModelAdmin.has_view_permission(request, obj=None)

Должен возвращать True, если просмотр obj разрешен, и False в противном случае. Если obj равен None, метод должен возвращать True или False, чтобы указать, разрешен ли в целом просмотр объектов этого типа (например, False будет означать, что текущему пользователю не разрешен просмотр ни одного объекта этого типа).

Реализация по умолчанию возвращает True, если у пользователя есть разрешение «change» или «view».

ModelAdmin.has_add_permission(request)

Должен возвращать True, если добавление объекта разрешено, и False в противном случае.

ModelAdmin.has_change_permission(request, obj=None)

Должен возвращать True, если редактирование obj разрешено, и False в противном случае. Если obj равен None, метод должен возвращать True или False, чтобы указать, разрешено ли в целом редактирование объектов этого типа (например, False будет означать, что текущему пользователю не разрешено редактировать ни один объект этого типа).

ModelAdmin.has_delete_permission(request, obj=None)

Должен возвращать True, если удаление obj разрешено, и False в противном случае. Если obj равен None, метод должен возвращать True или False, чтобы указать, разрешено ли в целом удаление объектов этого типа (например, False будет означать, что текущему пользователю не разрешено удалять ни один объект этого типа).

ModelAdmin.has_module_permission(request)

Должен возвращать True, если отображение модуля на главной странице административного сайта и доступ к главной странице модуля разрешены, и False в противном случае. По умолчанию использует User.has_module_perms(). Переопределение этого метода не ограничивает доступ к представлениям просмотра, добавления, изменения или удаления; для этого следует использовать has_view_permission(), has_add_permission(), has_change_permission() и has_delete_permission().

ModelAdmin.get_queryset(request)

Метод get_queryset объекта ModelAdmin возвращает QuerySet всех экземпляров модели, которые можно редактировать через административный сайт. Один из примеров использования переопределения этого метода — отображение объектов, принадлежащих вошедшему в систему пользователю:

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)
ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False) [источник]

Отправляет пользователю сообщение с помощью бэкенда django.contrib.messages. См. пример пользовательского ModelAdmin.

Именованные аргументы позволяют изменить уровень сообщения, добавить дополнительные CSS-классы или не сообщать об ошибке, если фреймворк contrib.messages не установлен. Эти именованные аргументы соответствуют аргументам django.contrib.messages.add_message(); подробности см. в документации этой функции. Отличие заключается в том, что уровень можно передать строковой меткой, а не только целым числом или константой.

ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True) [источник]

Возвращает экземпляр пагинатора, который следует использовать для этого представления. По умолчанию создает экземпляр paginator.

ModelAdmin.response_add(request, obj, post_url_continue=None) [источник]

Определяет HttpResponse для этапа add_view().

response_add вызывается после отправки формы административного интерфейса, сразу после создания и сохранения объекта и всех связанных экземпляров. Вы можете переопределить этот метод, чтобы изменить поведение по умолчанию после создания объекта.

ModelAdmin.response_change(request, obj) [источник]

Определяет HttpResponse для этапа change_view().

response_change вызывается после отправки формы административного интерфейса, сразу после сохранения объекта и всех связанных экземпляров. Вы можете переопределить этот метод, чтобы изменить поведение по умолчанию после изменения объекта.

ModelAdmin.response_delete(request, obj_display, obj_id) [источник]

Определяет HttpResponse для этапа delete_view().

response_delete вызывается после удаления объекта. Вы можете переопределить этот метод, чтобы изменить поведение по умолчанию после удаления объекта.

obj_display — это строка с именем удаленного объекта.

obj_id — это сериализованный идентификатор, используемый для получения объекта, который необходимо удалить.

ModelAdmin.get_formset_kwargs(request, obj, inline, prefix) [источник]

Метод-перехватчик для настройки именованных аргументов, передаваемых конструктору набора форм. Например, чтобы передать request формам набора форм:

class MyModelAdmin(admin.ModelAdmin):
    def get_formset_kwargs(self, request, obj, inline, prefix):
        return {
            **super().get_formset_kwargs(request, obj, inline, prefix),
            "form_kwargs": {"request": request},
        }

Также его можно использовать, чтобы задать initial для форм набора форм.

ModelAdmin.get_changeform_initial_data(request) [источник]

Метод-перехватчик для задания начальных данных в формах изменения административного интерфейса. По умолчанию начальные значения полей берутся из параметров GET. Например, ?name=initial_value задаст начальное значение поля name равным initial_value.

Этот метод должен возвращать словарь вида {'fieldname': 'fieldval'}:

def get_changeform_initial_data(self, request):
    return {"name": "custom_initial_value"}
ModelAdmin.get_deleted_objects(objs, request) [источник]

Метод-перехватчик для настройки процесса удаления в delete_view() и действия «удалить выбранные».

Аргумент objs — это однородный итерируемый объект с элементами для удаления (QuerySet или список экземпляров модели), а request — это HttpRequest.

Этот метод должен возвращать кортеж из четырех элементов (deleted_objects, model_count, perms_needed, protected).

deleted_objects — это список строк, представляющих все объекты, которые будут удалены. Если есть связанные объекты, которые также нужно удалить, список будет вложенным и будет содержать эти связанные объекты. Список форматируется в шаблоне с помощью фильтра unordered_list.

model_count — это словарь, сопоставляющий verbose_name_plural каждой модели с количеством объектов, которые будут удалены.

perms_needed — это множество значений verbose_name моделей, объекты которых пользователь не имеет права удалять.

protected — это список строк, представляющих все защищенные связанные объекты, которые нельзя удалить. Список отображается в шаблоне.

Другие методы

ModelAdmin.add_view(request, form_url='', extra_context=None) [источник]

Представление Django для страницы добавления экземпляра модели. См. примечание ниже.

ModelAdmin.change_view(request, object_id, form_url='', extra_context=None) [источник]

Представление Django для страницы редактирования экземпляра модели. См. примечание ниже.

ModelAdmin.changelist_view(request, extra_context=None) [источник]

Представление Django для страницы списка изменений/действий экземпляров модели. См. примечание ниже.

ModelAdmin.delete_view(request, object_id, extra_context=None) [источник]

Представление Django для страницы подтверждения удаления экземпляра (экземпляров) модели. См. примечание ниже.

ModelAdmin.history_view(request, object_id, extra_context=None) [источник]

Представление Django для страницы с историей изменений указанного экземпляра модели.

В отличие от методов ModelAdmin, которые служат точками расширения и описаны в предыдущем разделе, эти пять методов фактически предназначены для вызова в качестве представлений Django обработчиком диспетчеризации URL-адресов административного приложения, чтобы отображать страницы для операций CRUD с экземплярами модели. Поэтому полное переопределение этих методов существенно изменит поведение административного приложения.

Одна из распространенных причин переопределения этих методов — расширение данных контекста, передаваемых шаблону, который отображает представление. В следующем примере переопределяется представление изменения, чтобы в отображаемый шаблон передавались дополнительные данные сопоставления, которые иначе были бы недоступны:

class MyModelAdmin(admin.ModelAdmin):
    # A template for a very customized change view:
    change_form_template = "admin/myapp/extras/openstreetmap_change_form.html"

    def get_osm_info(self):
        # ...
        pass

    def change_view(self, request, object_id, form_url="", extra_context=None):
        extra_context = extra_context or {}
        extra_context["osm_data"] = self.get_osm_info()
        return super().change_view(
            request,
            object_id,
            form_url,
            extra_context=extra_context,
        )

Эти представления возвращают экземпляры TemplateResponse, позволяющие легко настроить данные ответа перед его отображением. Подробнее см. в документации по TemplateResponse.

ModelAdmin определения ресурсов

Иногда бывает нужно добавить немного CSS и/или JavaScript на страницы добавления/изменения. Это можно сделать с помощью внутреннего класса Media в ModelAdmin:

class ArticleAdmin(admin.ModelAdmin):
    class Media:
        css = {
            "all": ["my_styles.css"],
        }
        js = ["my_code.js"]

Приложение staticfiles добавляет STATIC_URL (или MEDIA_URL, если STATIC_URL равен None) перед путями к ресурсам. Действуют те же правила, что и для обычных определений ресурсов в формах.

jQuery

JavaScript административного интерфейса Django использует библиотеку jQuery.

Чтобы избежать конфликтов со скриптами или библиотеками, предоставленными пользователями, jQuery Django (версия 3.7.1) имеет пространство имен django.jQuery. Если вы хотите использовать jQuery в собственном JavaScript административного интерфейса, не подключая вторую копию, можно использовать объект django.jQuery на страницах списков и добавления/редактирования. Кроме того, собственные формы или виджеты административного интерфейса, зависящие от django.jQuery, должны указывать js=['admin/js/jquery.init.js', …] при объявлении ресурсов формы.

Класс ModelAdmin по умолчанию требует jQuery, поэтому добавлять jQuery в список медиа-ресурсов ModelAdmin не нужно, если в этом нет особой необходимости. Например, если библиотека jQuery должна находиться в глобальном пространстве имен (например, при использовании сторонних плагинов jQuery) или если вам нужна более новая версия jQuery, необходимо подключить собственную копию.

Django предоставляет несжатую и «минифицированную» версии jQuery: соответственно, jquery.js и jquery.min.js.

Классы ModelAdmin и InlineModelAdmin имеют свойство media, возвращающее список объектов Media, в которых хранятся пути к JavaScript-файлам форм и/или наборов форм. Если DEBUG равно True, будут возвращены несжатые версии различных JavaScript-файлов, включая jquery.js; в противном случае будут возвращены «минифицированные» версии.

Добавление пользовательской проверки данных в административный интерфейс

В административном интерфейсе также можно добавить пользовательскую проверку данных. Автоматический административный интерфейс повторно использует django.forms, а класс ModelAdmin позволяет определить собственную форму:

class ArticleAdmin(admin.ModelAdmin):
    form = MyArticleAdminForm

MyArticleAdminForm можно определить в любом месте, если импортировать его там, где это необходимо. Затем в форме можно добавить собственную проверку любого поля:

class MyArticleAdminForm(forms.ModelForm):
    def clean_name(self):
        # do something that validates your data
        return self.cleaned_data["name"]

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

InlineModelAdmin — объекты

class InlineModelAdmin
class TabularInline [исходный код]
class StackedInline [исходный код]

Интерфейс администратора позволяет редактировать модели на той же странице, что и родительскую модель. Такие объекты называются встроенными формами (inlines). Предположим, у вас есть две модели:

from django.db import models


class Author(models.Model):
    name = models.CharField(max_length=100)


class Book(models.Model):
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)

Вы можете редактировать книги, написанные автором, на странице автора. Чтобы добавить встроенные формы к модели, укажите их в ModelAdmin.inlines:

from django.contrib import admin
from myapp.models import Author, Book


class BookInline(admin.TabularInline):
    model = Book


class AuthorAdmin(admin.ModelAdmin):
    inlines = [
        BookInline,
    ]


admin.site.register(Author, AuthorAdmin)

Django предоставляет два подкласса InlineModelAdmin:

  • TabularInline
  • StackedInline

Разница между ними заключается лишь в шаблоне, используемом для их отображения.

InlineModelAdmin — параметры

InlineModelAdmin имеет многие те же возможности, что и ModelAdmin, а также добавляет некоторые собственные (общие возможности определены в суперклассе BaseModelAdmin). К общим возможностям относятся:

  • form
  • fieldsets
  • fields
  • formfield_overrides
  • exclude
  • filter_horizontal
  • filter_vertical
  • ordering
  • prepopulated_fields
  • get_fieldsets()
  • get_queryset()
  • radio_fields
  • readonly_fields
  • raw_id_fields
  • formfield_for_choice_field()
  • formfield_for_foreignkey()
  • formfield_for_manytomany()
  • has_module_permission()

Класс InlineModelAdmin добавляет или настраивает:

InlineModelAdmin.model

Модель, используемая встроенной формой. Этот параметр обязателен.

InlineModelAdmin.fk_name

Имя внешнего ключа в модели. В большинстве случаев оно определяется автоматически, но fk_name необходимо указать явно, если существует несколько внешних ключей на одну и ту же родительскую модель.

InlineModelAdmin.formset

По умолчанию используется BaseInlineFormSet. Собственный набор форм предоставляет множество возможностей для настройки. Встроенные формы построены на основе наборов форм моделей.

InlineModelAdmin.form

По умолчанию значением form является ModelForm. Это значение передаётся в inlineformset_factory() при создании набора форм для этой встроенной формы.

Предупреждение

При написании собственной проверки для форм InlineModelAdmin будьте осторожны с проверками, зависящими от свойств родительской модели. Если родительская модель не пройдёт проверку, она может остаться в некорректном состоянии, как описано в предупреждении в разделе Проверка в ModelForm.

InlineModelAdmin.classes

Список или кортеж дополнительных CSS-классов, применяемых к набору полей, отображаемому для встроенных форм. По умолчанию используется None. Как и для классов, заданных в fieldsets, встроенные формы с классом collapse изначально будут свёрнуты; развернуть их можно с помощью раскрывающегося элемента.

InlineModelAdmin.extra

Задаёт число дополнительных форм, которые будут отображаться в наборе форм сверх начальных форм. По умолчанию — 3. Подробности см. в документации по наборам форм.

Для пользователей с включённым JavaScript браузером отображается ссылка «Добавить ещё», позволяющая добавлять любое количество дополнительных встроенных форм сверх тех, которые создаются на основе аргумента extra.

Динамическая ссылка не будет отображаться, если количество уже отображаемых форм превышает max_num или если у пользователя отключён JavaScript.

Метод InlineModelAdmin.get_extra() также позволяет настроить количество дополнительных форм.

InlineModelAdmin.max_num

Задаёт максимальное количество форм, отображаемых во встроенной форме. Это значение не обязательно соответствует количеству объектов, но может ему соответствовать, если значение достаточно мало. Подробности см. в разделе Ограничение количества редактируемых объектов.

Метод InlineModelAdmin.get_max_num() также позволяет настроить максимальное количество дополнительных форм.

InlineModelAdmin.min_num

Задаёт минимальное количество форм, отображаемых во встроенной форме. Подробности см. в modelformset_factory().

Метод InlineModelAdmin.get_min_num() также позволяет настроить минимальное количество отображаемых форм.

InlineModelAdmin.raw_id_fields

По умолчанию интерфейс администратора Django использует для полей, являющихся ForeignKey, выпадающий список (<select>). Иногда нежелательно загружать все связанные объекты для отображения в этом списке.

raw_id_fields — это список полей, для которых вы хотите использовать виджет Input вместо обычного виджета для ForeignKey или ManyToManyField:

class BookInline(admin.TabularInline):
    model = Book
    raw_id_fields = ["pages"]
InlineModelAdmin.template

Шаблон, используемый для отображения встроенной формы на странице.

InlineModelAdmin.verbose_name

Переопределение значения verbose_name из внутреннего класса Meta модели.

InlineModelAdmin.verbose_name_plural

Переопределение значения verbose_name_plural из внутреннего класса Meta модели. Если это значение не задано, но определено InlineModelAdmin.verbose_name, Django будет использовать InlineModelAdmin.verbose_name + 's'.

InlineModelAdmin.can_delete

Определяет, можно ли удалять объекты встроенной формы. По умолчанию — True.

InlineModelAdmin.show_change_link

Определяет, будут ли у объектов встроенной формы, которые можно изменять в интерфейсе администратора, ссылки на форму изменения. По умолчанию — False.

InlineModelAdmin.get_formset(request, obj=None, **kwargs)

Возвращает класс BaseInlineFormSet для использования в представлениях добавления и изменения в интерфейсе администратора. obj — редактируемый родительский объект или None при добавлении нового родительского объекта. См. пример для ModelAdmin.get_formsets_with_inlines.

InlineModelAdmin.get_extra(request, obj=None, **kwargs)

Возвращает количество дополнительных форм для встроенной формы. По умолчанию возвращает атрибут InlineModelAdmin.extra.

Переопределите этот метод, чтобы программно определять количество дополнительных форм для встроенной формы. Например, это значение может зависеть от экземпляра модели (передаваемого как именованный аргумент obj):

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

    def get_extra(self, request, obj=None, **kwargs):
        extra = 2
        if obj:
            return extra - obj.binarytree_set.count()
        return extra
InlineModelAdmin.get_max_num(request, obj=None, **kwargs)

Возвращает максимальное количество дополнительных форм для встроенной формы. По умолчанию возвращает атрибут InlineModelAdmin.max_num.

Переопределите этот метод, чтобы программно определять максимальное количество форм для встроенной формы. Например, это значение может зависеть от экземпляра модели (передаваемого как именованный аргумент obj):

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

    def get_max_num(self, request, obj=None, **kwargs):
        max_num = 10
        if obj and obj.parent:
            return max_num - 5
        return max_num
InlineModelAdmin.get_min_num(request, obj=None, **kwargs)

Возвращает минимальное количество форм для встроенной формы. По умолчанию возвращает атрибут InlineModelAdmin.min_num.

Переопределите этот метод, чтобы программно определять минимальное количество форм для встроенной формы. Например, это значение может зависеть от экземпляра модели (передаваемого как именованный аргумент obj).

InlineModelAdmin.has_add_permission(request, obj)

Должен возвращать True, если добавление объекта встроенной формы разрешено, и False в противном случае. obj — редактируемый родительский объект или None при добавлении нового родительского объекта.

InlineModelAdmin.has_change_permission(request, obj=None)

Должен возвращать True, если редактирование объекта встроенной формы разрешено, и False в противном случае. obj — редактируемый родительский объект.

InlineModelAdmin.has_delete_permission(request, obj=None)

Должен возвращать True, если удаление объекта встроенной формы разрешено, и False в противном случае. obj — редактируемый родительский объект.

Примечание

Аргумент obj, передаваемый методам InlineModelAdmin, — это редактируемый родительский объект или None при добавлении нового родительского объекта.

Работа с моделью, содержащей два или более внешних ключа на одну родительскую модель

Иногда модель может содержать несколько внешних ключей на одну и ту же модель. Например, возьмём такую модель:

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=128)


class Friendship(models.Model):
    to_person = models.ForeignKey(
        Person, on_delete=models.CASCADE, related_name="friends"
    )
    from_person = models.ForeignKey(
        Person, on_delete=models.CASCADE, related_name="from_friends"
    )

Если вы хотите отобразить встроенную форму на страницах добавления или изменения Person в интерфейсе администратора, необходимо явно определить внешний ключ, поскольку Django не может сделать это автоматически:

from django.contrib import admin
from myapp.models import Friendship, Person


class FriendshipInline(admin.TabularInline):
    model = Friendship
    fk_name = "to_person"


class PersonAdmin(admin.ModelAdmin):
    inlines = [
        FriendshipInline,
    ]


admin.site.register(Person, PersonAdmin)

Работа с моделями «многие-ко-многим»

По умолчанию виджеты администратора для связей «многие-ко-многим» отображаются в модели, содержащей фактическую ссылку на ManyToManyField. В зависимости от определения ModelAdmin каждое поле «многие-ко-многим» в модели будет представлено стандартным HTML-элементом <select multiple>, горизонтальным или вертикальным фильтром либо виджетом raw_id_fields. Однако эти виджеты также можно заменить встроенными формами.

Предположим, у нас есть следующие модели:

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=128)


class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, related_name="groups")

Чтобы отображать связи «многие-ко-многим» с помощью встроенной формы, можно определить для связи объект InlineModelAdmin:

from django.contrib import admin
from myapp.models import Group


class MembershipInline(admin.TabularInline):
    model = Group.members.through


class GroupAdmin(admin.ModelAdmin):
    inlines = [
        MembershipInline,
    ]
    exclude = ["members"]


admin.site.register(Group, GroupAdmin)

В этом примере стоит отметить две особенности.

Во-первых, класс MembershipInline ссылается на Group.members.through. Атрибут through указывает на модель, которая управляет связью «многие-ко-многим». Django автоматически создаёт эту модель при определении поля «многие-ко-многим».

Во-вторых, в GroupAdmin необходимо вручную исключить поле members. Django отображает виджет администратора для поля «многие-ко-многим» в модели, которая определяет связь (в данном случае — Group). Если вы хотите представить связь «многие-ко-многим» с помощью встроенной модели, необходимо указать интерфейсу администратора Django не отображать этот виджет — иначе на странице администратора окажутся два виджета для управления связью.

Обратите внимание: при использовании этого приёма сигналы m2m_changed не вызываются. Это происходит потому, что с точки зрения интерфейса администратора through — просто модель с двумя полями внешнего ключа, а не связь «многие-ко-многим».

Во всех остальных отношениях InlineModelAdmin ничем не отличается от любой другой. Её внешний вид можно настроить с помощью обычных свойств ModelAdmin.

Работа с промежуточными моделями «многие-ко-многим»

Если указать промежуточную модель с помощью аргумента through в ManyToManyField, интерфейс администратора по умолчанию не будет отображать виджет. Это связано с тем, что для каждого экземпляра такой промежуточной модели требуется больше информации, чем можно отобразить в одном виджете, а требуемое расположение нескольких виджетов зависит от промежуточной модели.

Однако мы всё же хотим иметь возможность редактировать эти данные во встроенной форме. К счастью, это можно сделать с помощью встроенных моделей администратора. Предположим, у нас есть следующие модели:

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=128)


class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through="Membership")


class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["person", "group"], name="unique_person_group"
            )
        ]

Сначала для отображения этой промежуточной модели в интерфейсе администратора определим класс встроенной формы для модели Membership:

class MembershipInline(admin.TabularInline):
    model = Membership
    extra = 1

В этом примере используются значения InlineModelAdmin по умолчанию для модели Membership, а количество дополнительных форм добавления ограничено одной. Настроить это можно с помощью любых параметров, доступных классам InlineModelAdmin.

Теперь создайте представления администратора для моделей Person и Group:

class PersonAdmin(admin.ModelAdmin):
    inlines = [MembershipInline]


class GroupAdmin(admin.ModelAdmin):
    inlines = [MembershipInline]

Наконец, зарегистрируйте модели Person и Group на сайте администратора:

admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)

Теперь сайт администратора настроен для редактирования объектов Membership во встроенной форме как на страницах сведений Person, так и Group.

Использование универсальных связей во встроенной форме

Встроенную форму можно использовать с объектами, связанными универсальной связью. Предположим, у вас есть следующие модели:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models


class Image(models.Model):
    image = models.ImageField(upload_to="images")
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")


class Product(models.Model):
    name = models.CharField(max_length=100)

Чтобы разрешить редактирование и создание экземпляра Image в представлениях добавления и изменения Product, используйте GenericTabularInline или GenericStackedInline (оба класса являются подклассами GenericInlineModelAdmin), предоставляемые модулем admin. Они реализуют соответственно табличное и блочное визуальное представление форм для встроенных объектов, как и их аналоги без универсальных связей. Они ведут себя так же, как любые другие встроенные формы. В admin.py для этого примера приложения:

from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline

from myapp.models import Image, Product


class ImageInline(GenericTabularInline):
    model = Image


class ProductAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]


admin.site.register(Product, ProductAdmin)

Более подробную информацию см. в документации по contenttypes.

Переопределение шаблонов администратора

Вы можете переопределить многие шаблоны, которые модуль администратора использует для создания различных страниц сайта администратора. Некоторые из них можно переопределить для конкретного приложения или модели.

Настройка каталогов шаблонов администратора проекта

Файлы шаблонов администратора находятся в каталоге django/contrib/admin/templates/admin.

Чтобы переопределить один или несколько из них, сначала создайте каталог admin в каталоге templates вашего проекта. Это может быть любой из каталогов, указанных в параметре DIRS серверной части DjangoTemplates в настройке TEMPLATES. Если вы настроили параметр 'loaders', убедитесь, что 'django.template.loaders.filesystem.Loader' указан перед 'django.template.loaders.app_directories.Loader', чтобы система загрузки шаблонов находила ваши шаблоны раньше шаблонов, входящих в состав django.contrib.admin.

Внутри этого каталога admin создайте подкаталоги с именами ваших приложений. Внутри них создайте подкаталоги с именами моделей. Обратите внимание: при поиске каталога приложение администратора преобразует имя модели в нижний регистр, поэтому, если ваше приложение будет работать в файловой системе с учётом регистра, назовите каталог полностью строчными буквами.

Чтобы переопределить шаблон администратора для конкретного приложения, скопируйте шаблон из каталога django/contrib/admin/templates/admin, внесите изменения и сохраните его в одном из созданных каталогов.

Например, если мы хотим добавить инструмент в представление списка изменений для всех моделей приложения с именем my_app, нужно скопировать contrib/admin/templates/admin/change_list.html в каталог templates/admin/my_app/ нашего проекта и внести необходимые изменения.

Если мы хотим добавить инструмент в представление списка изменений только для конкретной модели с именем «Page», нужно скопировать тот же файл в каталог templates/admin/my_app/page нашего проекта.

Переопределение и замена шаблона администратора

Благодаря модульной структуре шаблонов администратора обычно нет необходимости и не рекомендуется заменять шаблон целиком. Почти всегда лучше переопределить только тот раздел шаблона, который требуется изменить.

Продолжим предыдущий пример: мы хотим добавить новую ссылку рядом с инструментом History для модели Page. Изучив change_form.html, мы выяснили, что нужно переопределить только блок object-tools-items. Поэтому наш новый шаблон change_form.html будет выглядеть так:

{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
    <li>
        <a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% translate "History" %}</a>
    </li>
    <li>
        <a href="mylink/" class="historylink">My Link</a>
    </li>
    {% if has_absolute_url %}
        <li>
            <a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% translate "View on site" %}</a>
        </li>
    {% endif %}
{% endblock %}

Вот и всё! Если мы разместим этот файл в каталоге templates/admin/my_app, ссылка появится на форме изменения всех моделей приложения my_app.

Шаблоны, которые можно переопределить для приложения или модели

Не каждый шаблон в contrib/admin/templates/admin можно переопределить отдельно для приложения или модели. К таким шаблонам относятся:

  • actions.html
  • app_index.html
  • change_form.html
  • change_form_object_tools.html
  • change_list.html
  • change_list_object_tools.html
  • change_list_results.html
  • date_hierarchy.html
  • delete_confirmation.html
  • object_history.html
  • pagination.html
  • popup_response.html
  • prepopulated_fields_js.html
  • search_form.html
  • submit_line.html

Шаблоны, которые нельзя переопределить таким способом, всё ещё можно переопределить для всего проекта: поместите новую версию в каталог templates/admin. Это особенно полезно для создания собственных страниц ошибок 404 и 500.

Примечание

Некоторые шаблоны администратора, например change_list_results.html, используются для отображения пользовательских тегов включения. Их можно переопределить, однако в таких случаях, вероятно, лучше создать собственную версию соответствующего тега и присвоить ей другое имя. Так вы сможете использовать его выборочно.

Шаблоны главной страницы и входа

Если вы хотите изменить шаблоны главной страницы, входа или выхода, лучше создать собственный экземпляр AdminSite (см. ниже) и изменить свойства AdminSite.index_template , AdminSite.login_template или AdminSite.logout_template.

Поддержка тем оформления

Для определения цветов и шрифтов интерфейс администратора использует переменные CSS. Благодаря этому тему можно изменить, не переопределяя множество отдельных правил CSS. Например, если вы предпочитаете фиолетовый цвет синему, можно добавить в проект переопределение шаблона admin/base.html:

{% extends 'admin/base.html' %}

{% block extrastyle %}{{ block.super }}
<style>
html[data-theme="light"], :root {
  --primary: #9774d5;
  --secondary: #785cab;
  --link-fg: #7c449b;
  --link-selected-fg: #8f5bb2;
}
</style>
{% endblock %}

Список переменных CSS определён в файле django/contrib/admin/static/admin/css/base.css.

Переменные тёмного режима, учитывающие медиазапрос prefers-color-scheme, определены в файле django/contrib/admin/static/admin/css/dark_mode.css. Этот файл подключается к документу в {% block dark-mode-vars %}.

extrabody — блок

Добавлено в Django 5.2.

Вы можете добавить пользовательский HTML, JavaScript или другое содержимое, которое будет отображаться непосредственно перед закрывающим тегом </body> шаблонов, расширяющих admin/base.html, переопределив блок extrabody. Например, если при загрузке страницы должно появляться предупреждение, можно добавить в проект переопределение шаблона admin/base.html:

{% extends 'admin/base.html' %}

{% block extrabody %}
    {{ block.super }}
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            window.alert('Welcome!');
        });
    </script>
{% endblock extrabody %}

AdminSite объекты

class AdminSite(name='admin') [исходный код]

Сайт администрирования Django представлен экземпляром django.contrib.admin.sites.AdminSite; по умолчанию экземпляр этого класса создается как django.contrib.admin.site, и вы можете зарегистрировать в нем свои модели и экземпляры ModelAdmin.

Если вы хотите настроить сайт администрирования по умолчанию, вы можете переопределить его.

При создании экземпляра AdminSite вы можете указать уникальное имя экземпляра, передав аргумент name конструктору. Это имя используется для идентификации экземпляра, в частности при обратном разрешении URL-адресов админки. Если имя экземпляра не указано, будет использоваться имя экземпляра по умолчанию admin. Пример настройки класса Настройка класса AdminSite см. в разделе AdminSite.

django.contrib.admin.sites.all_sites

WeakSet содержит все экземпляры сайта администрирования.

AdminSite атрибуты

Шаблоны могут переопределять или расширять базовые шаблоны админки, как описано в разделе Переопределение шаблонов админки.

AdminSite.site_header

Текст, отображаемый в верхней части каждой страницы админки, в виде <div> (строки). По умолчанию это «Администрирование Django».

AdminSite.site_title

Текст, отображаемый в конце <title> каждой страницы админки (строка). По умолчанию это «Администрирование сайта Django».

AdminSite.site_url

URL ссылки «Просмотреть сайт» в верхней части каждой страницы админки. По умолчанию site_url имеет значение /. Установите значение None, чтобы удалить ссылку.

Для сайтов, работающих по подчиненному пути, метод each_context() проверяет, задано ли в текущем запросе значение request.META['SCRIPT_NAME'], и использует его, если site_url не задано в значение, отличное от /.

AdminSite.index_title

Текст, отображаемый в верхней части главной страницы админки (строка). По умолчанию это «Администрирование сайта».

AdminSite.index_template

Путь к пользовательскому шаблону, который будет использоваться главным представлением индекса сайта администрирования.

AdminSite.app_index_template

Путь к пользовательскому шаблону, который будет использоваться представлением индекса приложения сайта администрирования.

AdminSite.empty_value_display

Строка, используемая для отображения пустых значений в списке изменений сайта администрирования. По умолчанию используется тире. Значение также можно переопределить отдельно для каждого ModelAdmin и для пользовательского поля внутри ModelAdmin, задав атрибут empty_value_display для поля. Примеры см. в разделе ModelAdmin.empty_value_display.

AdminSite.enable_nav_sidebar

Логическое значение, определяющее, следует ли показывать боковую панель навигации на больших экранах. По умолчанию установлено значение True.

AdminSite.final_catch_all_view

Логическое значение, определяющее, следует ли добавлять в админку заключительное универсальное представление, перенаправляющее не прошедших аутентификацию пользователей на страницу входа. По умолчанию установлено значение True.

Предупреждение

Не рекомендуется устанавливать значение False, поскольку это представление защищает от потенциальной проблемы конфиденциальности, связанной с перебором моделей.

AdminSite.login_template

Путь к пользовательскому шаблону, который будет использоваться представлением входа на сайт администрирования.

AdminSite.login_form

Подкласс AuthenticationForm, который будет использоваться представлением входа на сайт администрирования.

AdminSite.logout_template

Путь к пользовательскому шаблону, который будет использоваться представлением выхода с сайта администрирования.

AdminSite.password_change_form
Новое в Django 6.0.

Подкласс PasswordChangeForm, который будет использоваться представлением смены пароля на сайте администрирования.

AdminSite.password_change_template

Путь к пользовательскому шаблону, который будет использоваться представлением смены пароля на сайте администрирования.

AdminSite.password_change_done_template

Путь к пользовательскому шаблону, который будет использоваться представлением завершения смены пароля на сайте администрирования.

AdminSite методы

AdminSite.each_context(request) [исходный код]

Возвращает словарь переменных, которые нужно добавить в контекст шаблона для каждой страницы сайта администрирования.

По умолчанию включает следующие переменные и значения:

  • site_header: AdminSite.site_header
  • site_title: AdminSite.site_title
  • site_url: AdminSite.site_url
  • has_permission: AdminSite.has_permission()
  • available_apps: список приложений из реестра приложений, доступных текущему пользователю. Каждый элемент списка — это словарь, представляющий приложение со следующими ключами:

    • app_label: метка приложения
    • app_url: URL страницы индекса приложения в админке
    • has_module_perms: логическое значение, указывающее, разрешены ли текущему пользователю просмотр и доступ к странице индекса модуля
    • models: список моделей, доступных в приложении

    Каждая модель представлена словарем со следующими ключами:

    • model: класс модели
    • object_name: имя класса модели
    • name: множественное имя модели
    • perms: dict отслеживания разрешений на add, change, delete и view
    • admin_url: URL списка изменений модели в админке
    • add_url: URL админки для добавления нового экземпляра модели
  • is_popup: отображается ли текущая страница во всплывающем окне
  • is_nav_sidebar_enabled: AdminSite.enable_nav_sidebar
  • log_entries: AdminSite.get_log_entries()
AdminSite.get_app_list(request, app_label=None) [исходный код]

Возвращает список приложений из реестра приложений, доступных текущему пользователю. Чтобы получить сведения об одном приложении, можно дополнительно передать аргумент app_label. Каждый элемент списка — это словарь, представляющий приложение со следующими ключами:

  • app_label: метка приложения
  • app_url: URL страницы индекса приложения в админке
  • has_module_perms: логическое значение, указывающее, разрешены ли текущему пользователю просмотр и доступ к странице индекса модуля
  • models: список моделей, доступных в приложении
  • name: имя приложения

Каждая модель представлена словарем со следующими ключами:

  • model: класс модели
  • object_name: имя класса модели
  • name: множественное имя модели
  • perms: dict отслеживания разрешений на add, change, delete и view
  • admin_url: URL списка изменений модели в админке
  • add_url: URL админки для добавления нового экземпляра модели

Списки приложений и моделей сортируются по алфавиту в соответствии с их именами. Вы можете переопределить этот метод, чтобы изменить порядок по умолчанию на главной странице админки.

AdminSite.has_permission(request) [исходный код]

Возвращает True, если пользователь для заданного HttpRequest имеет разрешение просматривать хотя бы одну страницу сайта администрирования. По умолчанию требуется, чтобы и User.is_active, и User.is_staff имели значение True.

AdminSite.register(model_or_iterable, admin_class=None, **options) [исходный код]

Регистрирует указанный класс модели (или итерируемый объект с классами) в заданном admin_class. По умолчанию admin_class имеет значение ModelAdmin (параметры админки по умолчанию). Если переданы именованные аргументы, например list_display, они будут применены как параметры класса админки.

Вызывает ImproperlyConfigured, если модель является абстрактной, и django.contrib.admin.exceptions.AlreadyRegistered, если модель уже зарегистрирована.

AdminSite.unregister(model_or_iterable) [исходный код]

Отменяет регистрацию указанного класса модели (или итерируемого объекта с классами).

Вызывает django.contrib.admin.exceptions.NotRegistered, если модель еще не зарегистрирована.

AdminSite.get_model_admin(model) [исходный код]

Возвращает класс админки для указанного класса модели. Вызывает django.contrib.admin.exceptions.NotRegistered, если модель не зарегистрирована.

AdminSite.get_log_entries(request) [исходный код]

Возвращает queryset связанных экземпляров LogEntry, отображаемых на главной странице сайта. Этот метод можно переопределить, чтобы фильтровать записи журнала по другим критериям.

Подключение экземпляров AdminSite к вашему URLconf

Последний шаг при настройке админки Django — подключить экземпляр AdminSite к вашему URLconf. Для этого направьте URL на метод AdminSite.urls. Использовать include() не требуется.

В этом примере мы регистрируем экземпляр AdminSite по умолчанию django.contrib.admin.site по URL /admin/

# urls.py
from django.contrib import admin
from django.urls import path

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

Настройка класса AdminSite

Если вы хотите создать собственный сайт администрирования с индивидуальным поведением, можете создать подкласс AdminSite и переопределить или добавить всё, что вам нужно. Затем создайте экземпляр подкласса AdminSite (так же, как создаете экземпляр любого другого класса Python) и зарегистрируйте в нем свои модели и подклассы ModelAdmin вместо регистрации на сайте по умолчанию. Наконец, измените myproject/urls.py, чтобы он ссылался на ваш подкласс AdminSite.

myapp/admin.py
from django.contrib import admin

from .models import MyModel


class MyAdminSite(admin.AdminSite):
    site_header = "Monty Python administration"


admin_site = MyAdminSite(name="myadmin")
admin_site.register(MyModel)
myproject/urls.py
from django.urls import path

from myapp.admin import admin_site

urlpatterns = [
    path("myadmin/", admin_site.urls),
]

Обратите внимание, что при использовании собственного экземпляра AdminSite вам может понадобиться отключить автоматическое обнаружение модулей admin, поскольку вы, вероятно, будете импортировать все модули admin отдельных приложений в свой модуль myproject.admin. Это означает, что в настройке INSTALLED_APPS нужно указать 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin'.

Переопределение сайта администрирования по умолчанию

Вы можете переопределить django.contrib.admin.site по умолчанию, задав для атрибута default_site пользовательского AppConfig путь импорта с точками к подклассу AdminSite или к вызываемому объекту, возвращающему экземпляр сайта.

myproject/admin.py
from django.contrib import admin


class MyAdminSite(admin.AdminSite): ...
myproject/apps.py
from django.contrib.admin.apps import AdminConfig


class MyAdminConfig(AdminConfig):
    default_site = "myproject.admin.MyAdminSite"
myproject/settings.py
INSTALLED_APPS = [
    # ...
    "myproject.apps.MyAdminConfig",  # replaces 'django.contrib.admin'
    # ...
]

Несколько сайтов администрирования в одном URLconf

На одном сайте, работающем на Django, можно создать несколько экземпляров сайта администрирования. Создайте несколько экземпляров AdminSite и разместите каждый по отдельному URL.

В этом примере URL-адреса /basic-admin/ и /advanced-admin/ ведут к разным версиям сайта администрирования — экземплярам AdminSite myproject.admin.basic_site и myproject.admin.advanced_site соответственно:

# urls.py
from django.urls import path
from myproject.admin import advanced_site, basic_site

urlpatterns = [
    path("basic-admin/", basic_site.urls),
    path("advanced-admin/", advanced_site.urls),
]

Экземпляры AdminSite принимают в конструкторе один аргумент — имя, которое может быть любым. Этот аргумент становится префиксом имен URL для обратного разрешения. Это необходимо только в том случае, если вы используете более одного AdminSite.

Добавление представлений на сайты администрирования

Как и ModelAdmin, AdminSite предоставляет метод get_urls(), который можно переопределить для определения дополнительных представлений сайта. Чтобы добавить новое представление на сайт администрирования, расширьте базовый метод get_urls(), включив в него шаблон URL для нового представления.

Примечание

Любое представление, использующее шаблоны админки или расширяющее базовый шаблон админки, должно задать request.current_app перед отображением шаблона. Ему следует присвоить значение self.name, если представление находится в AdminSite, или self.admin_site.name, если представление находится в ModelAdmin.

Добавление функции сброса пароля

Вы можете добавить функцию сброса пароля на сайт администрирования, добавив несколько строк в свой URLconf. В частности, добавьте следующие четыре шаблона:

from django.contrib import admin
from django.contrib.auth import views as auth_views

path(
    "admin/password_reset/",
    auth_views.PasswordResetView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="admin_password_reset",
),
path(
    "admin/password_reset/done/",
    auth_views.PasswordResetDoneView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="password_reset_done",
),
path(
    "reset/<uidb64>/<token>/",
    auth_views.PasswordResetConfirmView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="password_reset_confirm",
),
path(
    "reset/done/",
    auth_views.PasswordResetCompleteView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="password_reset_complete",
),

(Предполагается, что вы добавили админку по адресу admin/; URL-адреса, начинающиеся с ^admin/, необходимо разместить перед строкой, подключающей само приложение админки.)

Наличие именованного URL admin_password_reset приведет к появлению ссылки «Забыли пароль?» на стандартной странице входа в админку под полем пароля.

LogEntry объекты

class models.LogEntry

Класс LogEntry отслеживает добавление, изменение и удаление объектов через интерфейс администрирования.

LogEntry атрибуты

LogEntry.action_time

Дата и время действия.

LogEntry.user

Пользователь (экземпляр AUTH_USER_MODEL), выполнивший действие.

LogEntry.content_type

ContentType измененного объекта.

LogEntry.object_id

Текстовое представление первичного ключа измененного объекта.

LogEntry.object_repr

repr() объекта после изменения.

LogEntry.action_flag

Тип зарегистрированного действия: ADDITION, CHANGE, DELETION.

Например, чтобы получить список всех добавлений, выполненных через админку:

from django.contrib.admin.models import ADDITION, LogEntry

LogEntry.objects.filter(action_flag=ADDITION)
LogEntry.change_message

Подробное описание изменения. Например, при редактировании сообщение содержит список измененных полей. Сайт администрирования Django форматирует это содержимое как структуру JSON, чтобы get_change_message() мог сформировать сообщение на текущем языке пользователя. Однако пользовательский код может задать это значение в виде обычной строки. Рекомендуется использовать метод get_change_message() для получения этого значения вместо прямого обращения к нему.

LogEntry методы

LogEntry.get_edited_object() [исходный код]

Вспомогательный метод, возвращающий связанный объект.

LogEntry.get_change_message() [исходный код]

Форматирует и переводит change_message на текущий язык пользователя. Сообщения, созданные до Django 1.10, всегда будут отображаться на языке, на котором они были записаны.

Обратное разрешение URL-адресов административного сайта

При развёртывании AdminSite представления, предоставляемые этим сайтом, доступны с помощью системы обратного разрешения URL-адресов Django.

AdminSite предоставляет следующие именованные шаблоны URL:

Страница

Имя URL

Параметры

Главная страница

index

Вход

login

Выход

logout

Изменение пароля

password_change

Завершение изменения пароля

password_change_done

JavaScript для i18n

jsi18n

Главная страница приложения

app_list

app_label

Перенаправление на страницу объекта

view_on_site

content_type_id, object_id

Каждый экземпляр ModelAdmin предоставляет дополнительный набор именованных URL:

Страница

Имя URL

Параметры

Список объектов

{{ app_label }}_{{ model_name }}_changelist

Добавление

{{ app_label }}_{{ model_name }}_add

История

{{ app_label }}_{{ model_name }}_history

object_id

Удаление

{{ app_label }}_{{ model_name }}_delete

object_id

Изменение

{{ app_label }}_{{ model_name }}_change

object_id

UserAdmin предоставляет именованный URL:

Страница

Имя URL

Параметры

Изменение пароля

auth_user_password_change

user_id

Эти именованные URL зарегистрированы в пространстве имён приложения admin и в пространстве имён экземпляра, соответствующем имени экземпляра Site.

Итак, если вам нужно получить ссылку на представление изменения для определённого объекта Choice (из приложения polls) в административном интерфейсе по умолчанию, вызовите:

>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse("admin:polls_choice_change", args=(c.id,))

Будет найден первый зарегистрированный экземпляр административного приложения (независимо от имени экземпляра), а результатом станет представление для изменения экземпляров poll.Choice в этом экземпляре.

Чтобы найти URL в конкретном экземпляре административного интерфейса, передайте имя этого экземпляра в качестве подсказки current_app вызову reverse. Например, если вам нужно представление административного интерфейса именно из экземпляра с именем custom, вызовите:

>>> change_url = reverse("admin:polls_choice_change", args=(c.id,), current_app="custom")

Подробнее см. документацию о обратном разрешении URL с пространствами имён.

Для упрощения обратного разрешения URL административного интерфейса в шаблонах Django предоставляет фильтр admin_urlname, который принимает действие в качестве аргумента:

{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

Действие в приведённых выше примерах соответствует последней части имён URL экземпляров ModelAdmin, описанных выше. Переменная opts может быть любым объектом с атрибутами app_label и model_name; обычно её предоставляет представление административного интерфейса для текущей модели.

Декоратор display

display(*, boolean=None, ordering=None, description=None, empty_value=None) [исходный код]

Этот декоратор можно использовать для задания определённых атрибутов пользовательских функций отображения, применяемых с list_display или readonly_fields:

@admin.display(
    boolean=True,
    ordering="-publish_date",
    description="Is Published?",
)
def is_published(self, obj):
    return obj.publish_date is not None

Это эквивалентно непосредственному заданию некоторых атрибутов (с исходными, более длинными именами) функции:

def is_published(self, obj):
    return obj.publish_date is not None


is_published.boolean = True
is_published.admin_order_field = "-publish_date"
is_published.short_description = "Is Published?"

Также обратите внимание, что параметр декоратора empty_value соответствует атрибуту empty_value_display, присваиваемому непосредственно функции. Его нельзя использовать вместе с boolean — эти параметры взаимоисключающие.

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

@admin.display
def published_year(self, obj):
    return obj.publish_date.year

В этом случае он не добавит к функции никаких атрибутов.

Декоратор staff_member_required

staff_member_required(redirect_field_name='next', login_url='admin:login') [исходный код]

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

  • Если пользователь вошёл в систему, является сотрудником (User.is_staff=True) и активен (User.is_active=True), представление выполняется обычным образом.
  • В противном случае запрос будет перенаправлен на URL, указанный параметром login_url, а исходный запрошенный путь будет передан в переменной строки запроса, заданной параметром redirect_field_name. Например: /admin/login/?next=/admin/polls/question/3/.

Пример использования:

from django.contrib.admin.views.decorators import staff_member_required


@staff_member_required
def my_view(request): ...

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/6.0/ref/contrib/admin/index/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API