Spec-Zone.ru › Django 5.2

Сайт администрирования 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-адреса администрирования к вашей URLconf.

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

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

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

Другие темы

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

См. также

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

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

ModelAdmin объекты

class ModelAdmin [source]

Класс 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) [source]

Также есть декоратор для регистрации ваших классов 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 по умолчанию для администрирования. Он вызывает autodiscover(), когда Django запускается.

class apps.SimpleAdminConfig

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

default_site

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

autodiscover() [source]

Эта функция пытается импортировать модуль admin в каждом установленных приложении. Такие модули должны регистрировать модели в администрировании.

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

Если вы используете настраиваемое AdminSite, то обычно вы импортируете все подклассы ModelAdmin в свой код и регистрируете их в настраиваемом AdminSite. В этом случае, чтобы отключить автоматическое обнаружение, вы должны поместить 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в вашей настройке 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> на странице формы администрирования. (Кортеж — это «раздел» формы.)

Пары кортежей имеют формат (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-стиле администрирования Django определены две особенно полезные класса: collapse и wide.

    Пример:

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

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

    Изменено в Django 5.1:

    fieldsets с использованием класса collapse теперь используют элементы <details> и <summary>, при условии, что они определяют name.

  • 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

В приведенном выше примере поле «возраст» будет исключено, но поле «имя» будет включено в сгенерированную форму.

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"]
    
Изменено в Django 5.1:

Добавлена поддержка использования __ поисковых запросов при работе со связанными полями.

Несколько особых случаев, которые следует учитывать при использовании 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 также будут отображаться как CSS классы в HTML выводе, в форме 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 List Filters для получения подробностей.

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 admin. Это должен быть список или кортеж в том же формате, что и параметр ordering модели.

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

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

Рекомендации по производительности при сортировке и упорядочивании

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

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

ModelAdmin.paginator

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

ModelAdmin.prepopulated_fields

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

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

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

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

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

Рекомендации по производительности при использовании фильтров

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

ModelAdmin.radio_fields

По умолчанию админ-панель Django использует интерфейс select-box (<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

Список полей ForeignKey и/или ManyToManyField, которые вы хотите изменить на автодополняемые поля Select2.

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

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

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

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

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

В следующем примере поле 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 admin использует интерфейс выпадающего списка (<select>) для полей, которые ForeignKey. Иногда вам не нужно загружать все связанные записи для отображения в выпадающем списке.

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 с помощью обозначения поиска «follow»:

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 (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 (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

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

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

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

ModelAdmin.view_on_site

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

Это значение может быть либо булевым флагом, либо вызываемым объектом. Если True (по умолчанию), будет использоваться метод объекта get_absolute_url() для генерации 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) [source]

Метод 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) [source]

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

ModelAdmin.delete_queryset(request, queryset) [source]

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

ModelAdmin.save_formset(request, form, formset, change) [source]

Метод 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) [source]

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

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

Этот метод может быть переопределён вашей собственной пользовательской функцией поиска. Например, вы можете захотеть выполнить поиск по целочисленному полю или использовать сторонний инструмент, такой как Solr или Haystack. Вы должны определить, могут ли изменения набора данных, реализованные вашим методом поиска, ввести дубликаты в результаты, и вернуть 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) [source]

Метод 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) [source]

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

ModelAdmin.get_list_display_links(request, list_display) [source]

Метод 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-tuples), где каждая пара представляет собой <fieldset> на странице формы администрирования, как описано выше в разделе ModelAdmin.fieldsets.

ModelAdmin.get_list_filter(request) [source]

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

ModelAdmin.get_list_select_related(request) [source]

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

ModelAdmin.get_search_fields(request) [source]

Метод 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) [source]

Метод get_inline_instances получает HttpRequest и obj, редактируемое (или None в форме добавления), и ожидается, что он вернёт итератор или список объектов 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() [source]

Метод 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) [source]

Возвращает класс 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) [source]

Возвращает пары (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__() для фильтрации на основе экземпляра вашей модели (см. Поля, обрабатывающие связи). Например:

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) [source]

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

ModelAdmin.get_changelist_form(request, **kwargs) [source]

Возвращает класс 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) [source]

Возвращает класс 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, если пользователь имеет разрешение «изменить» или «просмотреть».

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) [source]

Отправляет сообщение пользователю с помощью бэкенда 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) [source]

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

ModelAdmin.response_add(request, obj, post_url_continue=None) [source]

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

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

ModelAdmin.response_change(request, obj) [source]

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

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

ModelAdmin.response_delete(request, obj_display, obj_id) [source]

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

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

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

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

ModelAdmin.get_formset_kwargs(request, obj, inline, prefix) [source]

Вспомогательная функция для настройки ключевых аргументов, передаваемых в конструктор набора форм. Например, чтобы передать 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) [source]

Вспомогательная функция для начальных данных в формах изменения администрирования. По умолчанию поля получают начальные значения из параметров 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) [source]

Вспомогательная функция для настройки процесса удаления для delete_view() и действия «удалить выбранные» действие.

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

Этот метод должен вернуть кортеж из 4 элементов (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) [source]

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

ModelAdmin.change_view(request, object_id, form_url='', extra_context=None) [source]

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

ModelAdmin.changelist_view(request, extra_context=None) [source]

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

ModelAdmin.delete_view(request, object_id, extra_context=None) [source]

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

ModelAdmin.history_view(request, object_id, extra_context=None) [source]

Представление 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 admin использует библиотеку jQuery.

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

Класс ModelAdmin по умолчанию требует jQuery, поэтому нет необходимости добавлять jQuery в список ресурсов media вашего 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, иначе могут возникнуть ошибки. Обратитесь к документации форм по пользовательской валидации и, более конкретно, к примечаниям о валидации форм модели для получения дополнительной информации.

InlineModelAdmin объекты

class InlineModelAdmin
class TabularInline [source]
class StackedInline [source]

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

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. Использование собственного formset предоставляет множество возможностей настройки. Инлайны построены вокруг наборов форм моделей.

InlineModelAdmin.form

Значение для form по умолчанию ModelForm. Это то, что передается в inlineformset_factory() при создании formset для этого инлайна.

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

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

InlineModelAdmin.classes

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

Изменено в Django 5.1:

fieldsets, использующие класс collapse, теперь используют элементы <details> и <summary>, при условии, что они определяют name.

InlineModelAdmin.extra

Это контролирует количество дополнительных форм, которые отобразит formset помимо начальных форм. По умолчанию 3. Более подробную информацию см. в документации по formsets.

Для пользователей с браузерами, поддерживающими 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 использует интерфейс выпадающего списка (<select>) для полей, которые являются ForeignKey. Иногда вам не нужно нести издержки на выбор всех связанных экземпляров для отображения в выпадающем списке.

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

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

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

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

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

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

Переопределите этот метод, чтобы программно определить количество дополнительных inline-форм. Например, это может зависеть от экземпляра модели (переданного в качестве ключевого аргумента 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)

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

Переопределите этот метод, чтобы программно определить максимальное количество inline-форм. Например, это может зависеть от экземпляра модели (переданного в качестве ключевого аргумента 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)

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

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

InlineModelAdmin.has_add_permission(request, obj)

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

InlineModelAdmin.has_change_permission(request, obj=None)

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

InlineModelAdmin.has_delete_permission(request, obj=None)

Должно возвращать True, если удаление inline-объекта разрешено, и 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"
    )

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

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 виджетом. Однако также возможно заменить эти виджеты inline-элементами.

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

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")

Если вы хотите отобразить отношения "многие ко многим" с помощью inline-элемента, вы можете сделать это, определив объект 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). Если вы хотите использовать inline-модель для представления отношения "многие ко многим", вы должны указать Django, чтобы не отображать этот виджет — в противном случае у вас на странице админки окажется два виджета для управления отношением.

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

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

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

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

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

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)

Первым шагом в отображении этой промежуточной модели в админке является определение класса inline для модели 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 inline из страниц деталей Person или Group.

Использование обобщенных связей в качестве inline-элемента

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

from django.contrib.contenttypes.fields import GenericForeignKey
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. Они реализуют табличный и стековый макеты для форм, представляющих inline-объекты, соответственно, как и их необобщенные аналоги. Они ведут себя как любые другие inline-элементы. В вашем 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/ нашего проекта и внесли необходимые изменения.

Если мы хотели добавить инструмент в представление списка изменений только для определенной модели с именем «Страница», мы бы скопировали тот же файл в каталог 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') [source]

Сайт 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 administration».

AdminSite.site_title

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

AdminSite.site_url

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

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

AdminSite.index_title

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

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

Булево значение, определяющее, добавлять ли конечное представление catch-all в администрирование, которое перенаправляет неавторизованных пользователей на страницу входа. По умолчанию, оно установлено в True.

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

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

END_OF_DOCUMENT_MARKER

AdminSite методы

AdminSite.each_context(request) [source]

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

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

  • 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) [source]

Возвращает список приложений из реестра приложений, доступных текущему пользователю. Вы можете передать аргумент 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) [source]

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

AdminSite.register(model_or_iterable, admin_class=None, **options) [source]

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

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

AdminSite.unregister(model_or_iterable) [source]

Дерегистрирует указанный класс модели (или итерируемый объект классов).

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

AdminSite.get_model_admin(model) [source]

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

AdminSite.get_log_entries(request) [source]

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

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

Последний шаг настройки Django admin — подключение вашего экземпляра 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),
]

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

Переопределение стандартного админ-сайта

Вы можете переопределить стандартный 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() для включения шаблона для вашего нового представления.

Примечание

Любое представление, которое вы отображаете, используя админ-шаблоны или расширяя базовый админ-шаблон, должно установить 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 admin-панель форматирует это содержимое как JSON-структуру, так что get_change_message() может пересобрать сообщение, переведённое на текущий язык пользователя. Однако пользовательский код может установить это значение как обычную строку. Рекомендуется использовать метод get_change_message() для получения этого значения, а не обращаться к нему напрямую.

LogEntry методы

LogEntry.get_edited_object() [source]

Сокращение, возвращающее ссылку на объект.

LogEntry.get_change_message() [source]

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

Обращение к URL-адресам администрирования

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

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

Страница

Имя URL-адреса

Параметры

Главная

index

Вход

login

Выход

logout

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

password_change

Изменение пароля (выполнено)

password_change_done

i18n JavaScript

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 и с пространством имён экземпляра, соответствующим имени экземпляра сайта.

Таким образом, если вам нужно получить ссылку на представление изменения для конкретного объекта 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 для обратного вызова. Например, если вам нужен представление администрирования из экземпляра администрирования под названием 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) [source]

Этот декоратор можно использовать для установки определённых атрибутов для пользовательских функций отображения, которые могут использоваться с 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') [source]

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

  • Если пользователь авторизован, является сотрудником (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/5.2/ref/contrib/admin/index/

Spec-Zone.ru

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