Spec-Zone.ru › Django 5.1

Сайт администрирования 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 admin
  • Настройка JavaScript в администрировании

См. также

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

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

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, в одном наборе полей в том же порядке, в котором поля определены в модели.

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-стилевом таблице админки определены две особенно полезные класса: 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)
    
    Изменено в Django 5.0:

    Добавлена поддержка атрибута boolean для свойств.

  • Имена полей в 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.

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

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

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

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

Примечание

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

ModelAdmin.ordering

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

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

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

Учет производительности при сортировке

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

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

ModelAdmin.paginator

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

ModelAdmin.prepopulated_fields

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

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

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

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

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

ModelAdmin.preserve_filters

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

ModelAdmin.show_facets
Новое в Django 5.0.

Управляет отображением подсчетов фильтров на странице администрирования. По умолчанию ShowFacets.ALLOW.

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

class ShowFacets
Новое в Django 5.0.

Перечисление разрешенных значений для 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

Учет производительности с фильтрами

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

ModelAdmin.radio_fields

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

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

У вас есть возможность использовать HORIZONTAL или VERTICAL из модуля django.contrib.admin.

Не включайте поле в radio_fields , если это не ForeignKey или не имеет choices установленным.

ModelAdmin.autocomplete_fields

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

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

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

Вы должны определить 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 использует интерфейс выбора (<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-фразы:

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

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

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

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

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

Префикс Поиск
^ istartswith
= iexact
@ search
None icontains

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

ModelAdmin.search_help_text

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

ModelAdmin.show_full_result_count

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

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

ModelAdmin.sortable_by

По умолчанию страница списка изменений позволяет сортировать по всем полям модели (и вызовам, использующим 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 к каждому изменённому экземпляру модели formset:

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

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

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

ModelAdmin.get_autocomplete_fields(request)

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request) [source]

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

ModelAdmin.get_list_display_links(request, list_display) [source]

Метод get_list_display_links получает HttpRequest и список или кортеж, возвращённый методом ModelAdmin.get_list_display(). Он должен вернуть список, кортеж или строку имён полей на странице списка изменений, которые будут связаны со страницей изменения, как описано в разделе 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-х элементов, где каждая пара представляет собой набор полей на странице формы администрирования, как описано в разделе 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 и должен вернуть набор (например, список, кортеж или итератор) имён полей, которые будут сортироваться на странице списка изменений.

По умолчанию он возвращает значение атрибута 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. Например, следующее вернёт inline-объекты без фильтрации по умолчанию, основанной на разрешениях для добавления, изменения, удаления и просмотра:

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]

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

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

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


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

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

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

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

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

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

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

ModelAdmin.get_changelist(request, **kwargs) [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.

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

Добавлен аргумент request.

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-адреса приложения admin для отображения страниц, связанных с операциями CRUD над экземплярами моделей. Полностью переопределение этих методов значительно изменит поведение приложения admin.

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

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

    def get_osm_info(self):
        # ...
        pass

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

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

ModelAdmin определения активов

В некоторых случаях вам может потребоваться добавить немного CSS и/или JavaScript в представления добавления/редактирования. Это можно сделать, используя внутренний класс Media в вашем ModelAdmin:

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

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

jQuery

В JavaScript админки Django используется библиотека jQuery.

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

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

jQuery был обновлён с 3.6.4 до 3.7.1.

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

Django предоставляет как нескомпрессированные, так и сжатые версии jQuery, как jquery.js и jquery.min.js соответственно.

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

Добавление пользовательской валидации в админку

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

class ArticleAdmin(admin.ModelAdmin):
    form = MyArticleAdminForm

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

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

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

InlineModelAdmin объекты

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

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

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


class BookInline(admin.TabularInline):
    model = Book


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

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

  • TabularInline
  • StackedInline

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

InlineModelAdmin параметры

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

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

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

InlineModelAdmin.model

Модель, используемая вложенным элементом. Это необходимо.

InlineModelAdmin.fk_name

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

InlineModelAdmin.formset

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

InlineModelAdmin.form

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

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

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

InlineModelAdmin.classes

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

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

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

InlineModelAdmin.extra

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

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

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

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

InlineModelAdmin.max_num

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

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

InlineModelAdmin.min_num

Это контролирует минимальное количество отображаемых форм во вложенном элементе. Дополнительную информацию см. в modelformset_factory().

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

InlineModelAdmin.raw_id_fields

По умолчанию Django в админ-панели использует интерфейс выпадающего списка (<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 класса модели.

END_OF_DOCUMENT_MARKER
InlineModelAdmin.verbose_name_plural

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

InlineModelAdmin.can_delete

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

InlineModelAdmin.show_change_link

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

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

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

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

InlineModelAdmin.has_add_permission(request, obj)

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

InlineModelAdmin.has_change_permission(request, obj=None)

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

InlineModelAdmin.has_delete_permission(request, obj=None)

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

Примечание

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

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

Иногда возможно иметь более одного внешнего ключа к одной и той же модели. Рассмотрим следующую модель:

from django.db import models


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

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

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


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


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

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

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

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

from django.db import models


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


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

Если вы хотите отобразить отношения многие-ко-многим с помощью вложенной модели, вы можете сделать это, определив объект InlineModelAdmin для этого отношения:

from django.contrib import admin


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


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


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

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

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

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

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

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

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

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

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

from django.db import models


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


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


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

Первый шаг по отображению этой промежуточной модели в администрировании заключается в определении класса вложенной модели для модели Membership:

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

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

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

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


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

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

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

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

Использование общих отношений как вложенных моделей

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

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


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


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

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

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

from myapp.models import Image, Product


class ImageInline(GenericTabularInline):
    model = Image


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


admin.site.register(Product, ProductAdmin)

См. документацию по contenttypes для более подробной информации.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Не каждый шаблон в contrib/admin/templates/admin можно переопределить по приложению или по модели. Следующие можно:

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

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

Примечание

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

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

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

Поддержка тем

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

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

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

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

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

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 администрирование».

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

В более ранних версиях site_header использовался тег <h1>.

AdminSite.site_title

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

AdminSite.site_url

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

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

AdminSite.index_title

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

AdminSite.index_template

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

AdminSite.app_index_template

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

AdminSite.empty_value_display

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

AdminSite.enable_nav_sidebar

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

AdminSite.final_catch_all_view

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

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

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

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 права доступа
    • 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 права доступа
  • 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 5.0.

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

AdminSite.get_log_entries(request) [source]
Новое в Django 5.0.

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

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

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

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

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

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

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

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

myapp/admin.py
from django.contrib import admin

from .models import MyModel


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


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

from myapp.admin import admin_site

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

Обратите внимание, что при использовании собственного экземпляра AdminSite вам, вероятно, не потребуется автоматическое обнаружение модулей admin, так как вы, скорее всего, импортируете все модули admin для каждого приложения в свой модуль myproject.admin. Это означает, что вам нужно поместить '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 форматирует это содержимое как структуру 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
JavaScript i18n jsi18n
Страница списка приложения app_list app_label
Перенаправление на страницу объекта view_on_site content_type_id, object_id

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

Страница Имя URL Параметры
Список изменений {{ app_label }}_{{ model_name }}_changelist
Добавить {{ app_label }}_{{ model_name }}_add
История {{ app_label }}_{{ model_name }}_history object_id
Удалить {{ app_label }}_{{ model_name }}_delete object_id
Изменить {{ app_label }}_{{ model_name }}_change object_id

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

Страница Имя URL Параметры
Изменение пароля auth_user_password_change user_id

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

Так что, если вам нужно получить ссылку на представление «Изменение» для конкретного объекта Choice (из приложения «опросы») в стандартном администрировании, вы бы вызвали:

>>> 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.1/ref/contrib/admin/index/

Spec-Zone.ru

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