• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Интерфейс администратора Django

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

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

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

Обзор

Интерфейс администратора по умолчанию включен, если вы создавали проект командой startproject.

Если необходимо самостоятельно его включить, вот требования:

  1. Интерфейс администратора имеет четыре зависимости - django.contrib.auth, django.contrib.contenttypes, django.contrib.messages and 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.

После всего это вы можете использовать интерфейс администратора Django посетив соответствующий URL (/admin/ по умолчанию).

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

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

Другие разделы

См.также

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

Вопросы? Обратитесь к FAQ: Админка.

Объект ModelAdmin

class ModelAdmin

Класс ModelAdmin – это отображение модели в интерфейсе администратора. Его код добавляют обычно в файл admin.py вашего приложения. Давайте рассмотрим простой пример ModelAdmin:

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


class AuthorAdmin(admin.ModelAdmin):
    pass


admin.site.register(Author, AuthorAdmin)

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

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

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

admin.site.register(Author)

Декоратор для регистрации

register(*models, site=django.contrib.admin.sites.site)

Существует также декоратор для регистрации ваших классов ModelAdmin:

from django.contrib import admin
from .models import Author


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

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

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). Если вы используете Python 3 и не заботитесь о поддержке Python 2, вы можете использовать super().__init__(*args, **kwargs) . Иначе вам следует использовать admin.site.register() вместо декоратора.

Изучаем файлы админки

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

class apps.AdminConfig

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

class apps.SimpleAdminConfig

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

default_site

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

autodiscover()

Эта функция пытается импортировать модуль 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"

Поле в list_filter может указывать и на связанный объект используя __, например:

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

Так как модель содержит только три поля, name, title и birth_date, полученные формы будут содержать одинаковые поля.

ModelAdmin.fields

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

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

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

Для более сложных настроек используйте fieldsets.

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

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

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

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

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

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

ModelAdmin.fieldsets

Позволяет изменить макет страниц добавления и редактирования объекта.

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

Эти 2 кортежа имеют формат «(имя, параметры поля)», где «имя» — это строка, представляющая заголовок набора полей, а «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

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

Словарь 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 может содержать значения из ModelAdmin.readonly_fields, чтобы отображать поля без возможности их редактирования.

    Добавление функции в fields аналогично добавлению в параметр fields - функция должна быть указанна в readonly_fields.

  • classes

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

    Например:

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

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

  • description

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

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

TabularInline имеет ограниченную поддержку наборов полей

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

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

ModelAdmin.filter_horizontal

По умолчанию, поле ManyToManyField отображается как <select multiple>. Однако, это поле тяжело использовать при большом количестве объектов. Добавив ManyToManyField в этот атрибут, будет использоваться «виджет» с JavaScript фильтром для поиска. Смотрите описание filter_vertical про использование вертикального «виджета».

ModelAdmin.filter_vertical

Аналогичен filter_horizontal, но использует вертикальный «виджет».

ModelAdmin.form

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

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

Опустите атрибут Meta.model.

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

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

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

Если и ModelForm и ModelAdmin определяют опцию exclude, ModelAdmin будет иметь больший приоритет:

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


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


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

В этом примере, поле «age» не будет добавлено в форму в отличии от поля «name».

ModelAdmin.formfield_overrides

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

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

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

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


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

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

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

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

formfield_overrides не позволяет переопределить «виджет» для полей из raw_id_fields или radio_fields, потому что raw_id_fields и radio_fields переопределяют виджет.

ModelAdmin.inlines

Смотрите описание ниже InlineModelAdmin, а также ModelAdmin.get_formsets_with_inlines().

ModelAdmin.list_display

list_display указывает какие поля отображать на странице списка объектов.

Например:

list_display = ["first_name", "last_name"]

Если list_display не указан, Django отобразить только результат __str__()``(``__unicode__() для Python 2) объекта.

Существует пять типов значений, которые можно использовать в 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]
    
  • Функция, которая принимает один аргумент - объект модели. Например:

    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()
    
  • Название атрибута ModelAdmin. Работает так же, как и функция. Например:

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

Несколько особенностей list_display:

  • Если указано поле ForeignKey, Django покажет результат __str__() (__unicode__() для Python 2) связанного объекта.

  • ManyToManyField не поддерживается, так как это влечет к созданию SQL запроса для каждого объекта. Если вам необходимо сделать это в любом случае, создайте метод модели и используйте его в list_display. (Смотрите ниже подробности про использование методов в list_display.)

  • Если поле имеет тип BooleanField, Django отобразит красивый значок «да», «нет» или «неизвестно» вместо «True», «False» или «None».

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

    Вы можете также использовать AdminSite.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 со значением, установленным в Правда:

    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__() (__unicode__() в Python 2) можно использовать в list_display как и любой другой метод модели:

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

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

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

    В этом примере Django будет использовать поле first_name при сортировке по colored_first_name.

    Чтобы указать порядок убывания с помощью аргумента «ordering», вы можете использовать префикс дефиса в имени поля. Используя приведенный выше пример, это будет выглядеть так:

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

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

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

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

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

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

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

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

  • Django попытается интерпретировать каждый элемент list_display в следующем порядке:

    • Поле модели или из связанного поля.

    • Метод или любой другой вызываемый объект.

    • Строка, представляющая атрибут ModelAdmin.

    • Строка, представляющая атрибут модели.

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

Используйте 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.

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

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

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

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

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

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

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

Примечание

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

ModelAdmin.ordering

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

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

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

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

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

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

ModelAdmin.paginator

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

ModelAdmin.prepopulated_fields

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

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

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

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

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

ModelAdmin.preserve_filters

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

ModelAdmin.show_facets

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

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

class ShowFacets

Перечисление разрешенных значений для ModelAdmin.show_facets.

ALWAYS

Всегда показывать количество фасетов.

ALLOW

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

NEVER

Никогда не показывайте количество фасетов.

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

from django.contrib import admin


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

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

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

ModelAdmin.radio_fields

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

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

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

Не добавляйте в radio_fields поля, которые не являются ForeignKey или не содержат choices.

ModelAdmin.autocomplete_fields

autocomplete_fields — это список полей ForeignKey и/или ManyToManyField, которые вы хотите изменить на ``Select2 <https://select2.org/>`_ входные данные автозаполнения.

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

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

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

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

Порядок и нумерация результатов контролируются соответствующими методами get_ordering() и get_paginator() ModelAdmin.

В следующем примере ChoiceAdmin имеет поле автозаполнения для ForeignKey в вопросе. Результаты фильтруются по полю «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. Если связанных объектов очень много, создание <select> может быть очень затратным процессом.

raw_id_fields содержит список полей, которые будут использовать поле Input для ForeignKey или ManyToManyField:

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

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

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

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

Если readonly_fields используется без определения порядка полей через атрибуты ModelAdmin.fields или ModelAdmin.fieldsets, поля из этой настройки будут отображаться после редактируемых полей.

Read-only поле может показывать данные не только поля модели, но и метода, а также метода определенного в подклассе 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 равен False.

ModelAdmin.save_on_top

Укажите save_on_top, чтобы добавить кнопки сохранения в верхней части страницы редактирования объекта.

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

По умолчанию save_on_top равен False.

ModelAdmin.search_fields

search_fields позволяет добавить поиск на страницу списка объектов. Этот атрибут должен содержать список полей, которые будут использоваться при поиске.

Эти поля должны быть текстовыми, таким как CharField или TextField. Вы можете указать поля из связанных объектов используя __:

search_fields = ["foreign_key__related_fieldname"]

Например, у нас есть модель записи в блоге с полем автора. Следующая настройка позволит искать записи по email адресу автора:

search_fields = ["user__email"]

При поиске Django разбивает поисковый запрос на слова и возвращает объекты, которые содержат эти слова в одном из указанных в 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

@

поиск

Никто

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

ModelAdmin.view_on_site

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

Можно указать булево или функцию. При True (по умолчанию) будет использоваться метод get_absolute_url() объекта для получения ссылки.

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

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

Путь к шаблону, который используется change_view().

Методы ModelAdmin

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

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

ModelAdmin.save_model(request, obj, form, change)

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

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

from django.contrib import admin


class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super().save_model(request, obj, form, change)
ModelAdmin.delete_model(request, obj)

Метод delete_model принимает объект HttpRequest и экземпляр модели, который удаляется. В этом методе вы может выполнить дополнительные операции до или после удаления.

ModelAdmin.delete_queryset(request, queryset)

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

ModelAdmin.save_formset(request, form, formset, change)

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

Например, добавление request.user к каждому объекту, измененному в наборе форм:

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

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

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

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

Давайте возьмем ModelAdmin.get_readonly_fields() в качестве примера:

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

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

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

ModelAdmin.get_ordering(request)

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

class PersonAdmin(admin.ModelAdmin):
    def get_ordering(self, request):
        if request.user.is_superuser:
            return ["name", "rank"]
        else:
            return ["name"]
ModelAdmin.get_search_results(request, queryset, search_term)

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

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

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

Например, для поиска по численным полям можно сделать:

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.

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

ModelAdmin.get_autocomplete_fields(request)

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request)

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

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

ModelAdmin.get_exclude(request, obj=None)

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

ModelAdmin.get_fields(request, obj=None)

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

ModelAdmin.get_fieldsets(request, obj=None)

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

ModelAdmin.get_list_filter(request)

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

Метод get_list_select_related принимает HttpRequest должен вернуть значение формата, соответствующего параметру list_filter.

ModelAdmin.get_search_fields(request)

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

ModelAdmin.get_sortable_by(request)

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

Его реализация по умолчанию возвращает sortable_by, если он установлен, в противном случае она передается get_list_display().

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

class PersonAdmin(admin.ModelAdmin):
    def get_sortable_by(self, request):
        return {*self.get_list_display(request)} - {"rank"}
ModelAdmin.get_inline_instances(request, obj=None)

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

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

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

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

ModelAdmin.get_inlines(request, obj)

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

ModelAdmin.get_urls()

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

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


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

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

Вы можете использовать базовый шаблон админки admin/base_site.html:

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

Примечание

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

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

  2. Декоратор django.views.decorators.cache.never_cache() применяется для предотвращения кэширования и обеспечения актуальности возвращаемой информации.

Примечание

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

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

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

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

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

ModelAdmin.get_form(request, obj=None, **kwargs)

Возвращает класс ModelForm используемый при добавлении и редактировании объектов, смотрите описание add_view() и change_view().

Базовая реализация использует modelform_factory() для создания form с измененными параметрами fields и exclude. Поэтому, если вы, например, захотите добавить поля форме для суперпользователя, вы можете изменить базовый класс формы:

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

Вы также можете вернуть собственный класс ModelForm.

ModelAdmin.get_formsets_with_inlines(request, obj=None)

Выполняет yield по парам (FormSet, InlineModelAdmin), чтобы вернуть набор форм для страницы создания и изменения.

Например, если некоторый «inline» необходимо отображать только при редактировании, можно переопределить метод 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 позволяет вам переопределить поле для внешнего ключа. Например, изменить выбор объектов в зависимости от пользователя:

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 по текущему пользователю.

Для более сложных фильтров вы можете использовать метод ModelForm.__init__() для фильтрации на основе экземпляра вашей модели (см. fields-that-handle-relationships). Например:

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, чтобы отображать машины только текущего пользователя:

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

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

ModelAdmin.get_changelist(request, **kwargs)

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

ModelAdmin.get_changelist_form(request, **kwargs)

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

from django import forms


class MyForm(forms.ModelForm):
    pass


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

Опустите атрибут Meta.model.

Meta.model

ModelAdmin.get_changelist_formset(request, **kwargs)

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

from django.forms import BaseModelFormSet


class MyAdminFormSet(BaseModelFormSet):
    pass


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

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

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

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

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

ModelAdmin.has_view_permission(request, obj=None)

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

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

ModelAdmin.has_add_permission(request)

Должен возвращать True, если пользователю позволено добавлять новый объект, иначе False.

ModelAdmin.has_change_permission(request, obj=None)

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

ModelAdmin.has_delete_permission(request, obj=None)

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

ModelAdmin.has_module_permission(request)

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

ModelAdmin.get_queryset(request)

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

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)
ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False)

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

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

ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)

Возвращает объект для постраничного отображения. По умолчанию возвращает объект paginator.

ModelAdmin.response_add(request, obj, post_url_continue=None)

Указывает HttpResponse для add_view().

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

ModelAdmin.response_change(request, obj)

Создает HttpResponse для change_view().

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

ModelAdmin.response_delete(request, obj_display, obj_id)

Создает HttpResponse для delete_view().

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

obj_display - строка с названием удаленного объекта.

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

ModelAdmin.get_formset_kwargs(request, obj, inline, prefix)

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

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},
        }

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

ModelAdmin.get_changeform_initial_data(request)

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

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

def get_changeform_initial_data(self, request):
    return {"name": "custom_initial_value"}
ModelAdmin.get_deleted_objects(objs, request)

Перехватчик для настройки процесса удаления delete_view() и действия «удалить выбранное» :doc:` </ref/contrib/admin/actions>`.

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

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

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

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

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

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

Остальные методы

ModelAdmin.add_view(request, form_url='', extra_context=None)

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

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

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

ModelAdmin.changelist_view(request, extra_context=None)

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

ModelAdmin.delete_view(request, object_id, extra_context=None)

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

ModelAdmin.history_view(request, object_id, extra_context=None)

Представление Django для страницы истории изменений объекта модели.

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

Одна из причин переопределить эти методы – добавить данные в контекст шаблона. В этом примере представление для изменения объекта добавляет дополнительные данные в контекст, чтобы отобразить их в шаблоне:

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

    def get_osm_info(self):
        # ...
        pass

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

Эти представления возвращают объект TemplateResponse, что позволяет легко изменить данные ответа перед выполнением шаблона. Подробности смотрите в разделе о TemplateResponse.

Добавление статических файлов в ModelAdmin

В некоторых ситуациях вам может понадобиться добавить CSS и/или JavaScript файлы в представления добавления или изменения объектов. Вы можете выполнить это добавив класс Media в ModelAdmin:

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

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

jQuery

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

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

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

Django содержит сжатую и „minified“ версию jQuery, как jquery.js и jquery.min.js соответственно.

ModelAdmin и InlineModelAdmin содержат свойство media, которое возвращает список объектов Media, которые содержат путь к JavaScript файлам для форм и наборов форм. Если DEBUG равна True, будет использована несжатая версия 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, чтобы избежать проблем и ошибок. Подробности смотрите в документации о формах раздел про проверку полей и, особенно, раздел о переопределении метода clean() в ModelForm.

Объект InlineModelAdmin

class InlineModelAdmin
class TabularInline
class StackedInline

Интерфейс администратора позволяет редактировать связанные объекты на одной странице с родительским объектом. Это называется «inlines». Например, у нас есть две модели:

from django.db import models


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


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

Вы можете редактировать книги автора на странице редактирования автора. Вы добавляете «inlines» к модели добавив их в ModelAdmin.inlines:

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


class BookInline(admin.TabularInline):
    model = Book


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


admin.site.register(Author, AuthorAdmin)

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

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

Параметры InlineModelAdmin

InlineModelAdmin содержит некоторые возможности ModelAdmin и собственные. Общие методы и атрибуты определены в классе BaseModelAdmin, вот они:

Параметры класса InlineModelAdmin:

InlineModelAdmin.model

Модель используемая в «inline». Обязательный параметр.

InlineModelAdmin.fk_name

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

InlineModelAdmin.formset

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

InlineModelAdmin.form

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

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

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

InlineModelAdmin.classes

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

InlineModelAdmin.extra

Это контролирует количество дополнительных форм, которые будет отображаться в наборе форм в дополнение к исходным формам. По умолчанию — 3. Дополнительную информацию см. в документации по наборам форм </topics/forms/formsets>`.

Если JavaScript включен в браузере, ссылка «Add another» позволит добавить новую пустую форму в дополнение к формам указанным параметром 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. Если связанных объектов очень много, создание <select> может быть очень затратным процессом.

raw_id_fields содержит список полей, которые будут использовать поле Input для ForeignKey или ManyToManyField:

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

Шаблон для отображения.

InlineModelAdmin.verbose_name

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

InlineModelAdmin.verbose_name_plural

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

InlineModelAdmin.can_delete

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

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

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

Возвращает BaseInlineFormSet, который будет использоваться на странице создания/редактирования. Смотрите 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.

InlineModelAdmin.has_change_permission(request, obj=None)

Должен возвращать True, если пользователю позволено добавлять новый объект, иначе False.

InlineModelAdmin.has_delete_permission(request, obj=None)

Должен возвращать True, если пользователю позволено добавлять новый объект, иначе False.

Примечание

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

Работа с моделью с несколькими внешними ключами к одной модели

Модель может содержать несколько внешних ключей к одной модели, например:

from django.db import models


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


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

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

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


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


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


admin.site.register(Person, PersonAdmin)

Работа со связями многие-ко-многим

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

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

from django.db import models


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


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

Необходимо определить объект InlineModelAdmin для связи многое-ко-многим:

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


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


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


admin.site.register(Group, GroupAdmin)

Есть две вещи в этом примере, которые следует отметить.

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

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

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

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

Работа с промежуточной моделью связи многое-ко-многим

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

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

from django.db import models


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


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


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

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

Для начала определим отображение модели 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.

Использование связей с несколькими моделями в интерфейсе администратора

Вы можете использовать «inline» для связей с несколькими моделями(generic relations). Предположим, у вас есть следующие модели:

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


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


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

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

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

from myapp.models import Image, Product


class ImageInline(GenericTabularInline):
    model = Image


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


admin.site.register(Product, ProductAdmin)

Подробности смотрите в разделе о contenttypes.

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

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

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

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

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

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

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

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

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

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

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

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

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

Вот и все! Добавим шаблон в каталог templates/admin/my_app и ссылка появится на странице редактирования объекта для всех моделей приложения my_app.

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

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

  • app_index.html

  • app_index.html

  • change_form.html

  • change_form.html

  • change_list.html

  • change_list.html

  • change_list.html

  • object_history.html

  • delete_confirmation.html

  • object_history.html

  • change_list.html

  • app_index.html

  • app_index.html

  • change_form.html

  • app_index.html

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

Примечание

Некоторые шаблоны, такие как change_list_request.html используются для отображения включаемых тегов(inclusion tags). Вы можете переопределить их, но лучше создать собственную версию тега, которая будет использовать новый шаблон. В этом случае вы сможете использовать оба шаблона.

Главный шаблон и шаблон страницы входа

Чтобы переопределить шаблоны главной страницы и страниц входа/выхода, лучше создать собственный экземпляр 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 %}.

блок экстратела

New in Django 5.2.

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

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

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

Объект AdminSite

class AdminSite(name='admin')

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

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

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

django.contrib.admin.sites.all_sites

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

Атрибуты AdminSite

Можно переопределить или заменить основные шаблоны в интерфейсе администратора как это описано в разделе Переопределение шаблонов в интерфейсе администратора.

AdminSite.site_header

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

AdminSite.site_title

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

AdminSite.site_url

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

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

AdminSite.index_title

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

AdminSite.index_template

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

AdminSite.app_index_template

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

AdminSite.empty_value_display

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

AdminSite.enable_nav_sidebar

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

AdminSite.final_catch_all_view

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

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

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_form
New in Django 6.0.

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

Методы AdminSite

AdminSite.each_context(request)

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

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

  • site_header: AdminSite.site_header

  • site_title: AdminSite.site_title

  • site_url: AdminSite.site_url

  • has_permission: AdminSite.has_permission()

  • available_apps: список приложений из регистра приложений, которые доступны для текущего пользователя. Каждый элемент списка содержит словарь, который представляет приложение, со следующими ключами:

    • app_label: название приложения

    • app_url: URL главное страницы приложения в админке

    • has_module_perms: булево, которые указывает есть ли у пользователя права к главной странице приложения в админке

    • models: список моделей прилоджения

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

    • модель: класс модели

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

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

  • app_label: название приложения

  • app_url: URL главное страницы приложения в админке

  • has_module_perms: булево, которые указывает есть ли у пользователя права к главной странице приложения в админке

  • models: список моделей прилоджения

  • name: имя приложения

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

  • модель: класс модели

  • object_name: название класса модели

  • name: множественное название модели

  • perms: dict со значениями прав add, change и delete

  • admin_url: URL к странице списка объектов модели в админке

  • add_url: URL к странице добавления объекта модели в админке

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

AdminSite.has_permission(request)

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

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

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

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

AdminSite.unregister(model_or_iterable)

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

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

AdminSite.get_model_admin(model)

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

AdminSite.get_log_entries(request)

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

Добавление экземпляра AdminSite в URLconf

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

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

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

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

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

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

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 и регистрацию их в стандартной админке. Для этого укажите 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в настройке INSTALLED_APPS. Скорее всего в этом случае вы будете импортировать модули admin в вашем модуле myproject.admin.

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

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

myproject/admin.py
from django.contrib import admin


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


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

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

Django позволяет легко создать несколько интерфейсов администратора для одного сайта. Просто создайте несколько экземпляров AdminSite и добавьте его к различным URL-ам.

В этом примере, URL-ы /basic-admin/ и /advanced-admin/ ведут к различным экземплярам AdminSitemyproject.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. А точнее добавьте эти четыре URL-шаблона:

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

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

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

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

Объекты LogEntry

class models.LogEntry

Класс LogEntry следит за добавлением, изменение и удалением объектов, которые выполняются через админку.

Атрибуты LogEntry

LogEntry.action_time

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

LogEntry.user

Пользователь (объект AUTH_USER_MODEL), который выполнил действие.

LogEntry.content_type

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

LogEntry.object_id

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

LogEntry.object_repr

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

LogEntry.action_flag

Тип действия: ADDITION, CHANGE, DELETION.

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

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

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

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

Методы LogEntry

LogEntry.get_edited_object()

Возвращает связанный объект.

LogEntry.get_change_message()

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

Поиск URL-ов интерфейса администратора

После установки AdminSite можно указывать ссылки к представлениям интерфейса администратора используя систему поиска URL-ов.

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

Страница

Название URL-а

Параметры

Главная

index

Авторизоваться

logout

Выхода

logout

Смена пароля

password_change

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

password_change_done

i18n JavaScript

jsi18n

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

app_list

app_label

Редирект на страницу объекта

view_on_site

content_type_id, object_id

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

Страница

Название URL-а

Параметры

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

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

Добавления объекта

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

Истории

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

object_id

Удаления объекта

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

object_id

Изменения объекта

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

object_id

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

Страница

Название URL-а

Параметры

Смена пароля

auth_user_password_change

user_id

Эти именованные URL-шаблоны зарегистрированы с названием экземпляра приложения admin и названием экземпляра приложения, указанным при создании AdminSite.

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

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

Этот код найдет первый зарегистрированный экземпляр приложения admin (не зависимо от определенного названия экземпляра) и найдет ссылку на представление для редактирования объекта 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)

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

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

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

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

Декоратор staff_member_required

staff_member_required(redirect_field_name='next', login_url='admin:login')

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

  • Если пользователь авторизирован, и он администратор (User.is_staff=True), и активен (User.is_active=True), выполнить представление.

  • Иначе запросе будет перенаправлен на URL, указанный в параметре login_url, который по умолчанию равен значению аргумента с названием из redirect_field_name. Например: /admin/login/?next=/admin/polls/question/3/.

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

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


@staff_member_required
def my_view(request): ...
Back to Top