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

Интерфейс администратора 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.

    Changed in Django 3.1:

    django.template.context_processors.request was added as a requirement in the 'context_processors' option to support the new AdminSite.enable_nav_sidebar.

  3. If you’ve customized the MIDDLEWARE setting, django.contrib.auth.middleware.AuthenticationMiddleware and django.contrib.messages.middleware.MessageMiddleware must be included.

  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):
    fields = ('name', 'title', 'view_birth_date')

    @admin.display(empty_value='???')
    def view_birth_date(self, obj):
        return obj.birth_date
Changed in Django 3.2:

The empty_value argument to the display() decorator is equivalent to setting the empty_value_display attribute on the display function directly in previous versions. Setting the attribute directly is still supported for backward compatibility.

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.

The fields option accepts the same types of values as list_display, except that callables aren’t accepted. Names of model and model admin methods will only be used if they’re listed in readonly_fields.

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

class FlatPageAdmin(admin.ModelAdmin):
    fields = (('url', 'title'), 'content')

Note

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

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

ModelAdmin.fieldsets

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

fieldsets is a list of two-tuples, in which each two-tuple represents a <fieldset> on the admin form page. (A <fieldset> is a «section» of the form.)

The two-tuples are in the format (name, field_options), where name is a string representing the title of the fieldset and field_options is a dictionary of information about the fieldset, including a list of fields to be displayed in it.

Полный пример для модели 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

    A tuple of field names to display in this fieldset. This key is required.

    Например:

    {
    '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

    A list or tuple containing extra CSS classes to apply to the fieldset.

    Например:

    {
    'classes': ('wide', 'extrapretty'),
    }
    

    Two useful classes defined by the default admin site stylesheet are collapse and wide. Fieldsets with the collapse style will be initially collapsed in the admin and replaced with a small «click to expand» link. Fieldsets with the wide style will be given extra horizontal space.

  • description

    A string of optional extra text to be displayed at the top of each fieldset, under the heading of the fieldset. This string is not rendered for TabularInline due to its layout.

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

ModelAdmin.filter_horizontal

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

ModelAdmin.filter_vertical

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

ModelAdmin.form

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

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

Note

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

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

Note

Если и 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) объекта.

There are four types of values that can be used in list_display. All but the simplest may use the display() decorator is used to customize how the field is presented:

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

    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'last_name')
    
  • Функция, которая принимает один аргумент - объект модели. Например:

    @admin.display(description='Name')
    def upper_case_name(obj):
        return ("%s %s" % (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 ("%s %s" % (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):
            return '%d’s' % (self.birthday.year // 10 * 10)
    
    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.

    Changed in Django 3.2:

    The description argument to the display() decorator is equivalent to setting the short_description attribute on the display function directly in previous versions. Setting the attribute directly is still supported for backward compatibility.

  • Если значение поля 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
    
    Changed in Django 3.2:

    The empty_value argument to the display() decorator is equivalent to setting the empty_value_display attribute on the display function directly in previous versions. Setting the attribute directly is still supported for backward compatibility.

  • Если заданная строка является методом модели 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')
    
    Changed in Django 3.2:

    The boolean argument to the display() decorator is equivalent to setting the boolean attribute on the display function directly in previous versions. Setting the attribute directly is still supported for backward compatibility.

  • Метод __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')
    

    Аргумент 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
    
    Changed in Django 3.2:

    The ordering argument to the display() decorator is equivalent to setting the admin_order_field attribute on the display function directly in previous versions. Setting the attribute directly is still supported for backward compatibility.

  • Elements of list_display can also be properties:

    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',
        )
        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'
    
    full_name = property(my_property)
    
  • Названия полей из list_display будут использованы в CSS классах, форма будет содержать класс column-<field_name> для каждого элемента <th>. Так можно определить ширину полей через CSS стили.

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

    • A field of the model.

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

    • Строка, представляющая атрибут 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

Set list_filter to activate filters in the right sidebar of the change list page of the admin, as illustrated in the following screenshot:

../../../_images/list_filter.png

list_filter should be a list or tuple of elements, where each element should be of one of the following types:

  • a field name, where the specified field should be either a BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey or ManyToManyField, for example:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = ('is_staff', 'company')
    

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

    class PersonAdmin(admin.UserAdmin):
        list_filter = ('company__name',)
    
  • a class inheriting from django.contrib.admin.SimpleListFilter, which you need to provide the title and parameter_name attributes to and override the lookups and queryset methods, e.g.:

    from datetime import date
    
    from django.contrib import admin
    from django.utils.translation import gettext_lazy as _
    
    class DecadeBornListFilter(admin.SimpleListFilter):
        # Human-readable title which will be displayed in the
        # right admin sidebar just above the filter options.
        title = _('decade born')
    
        # Parameter for the filter that will be used in the URL query.
        parameter_name = 'decade'
    
        def lookups(self, request, model_admin):
            """
            Returns a list of tuples. The first element in each
            tuple is the coded value for the option that will
            appear in the URL query. The second element is the
            human-readable name for the option that will appear
            in the right sidebar.
            """
            return (
                ('80s', _('in the eighties')),
                ('90s', _('in the nineties')),
            )
    
        def queryset(self, request, queryset):
            """
            Returns the filtered queryset based on the value
            provided in the query string and retrievable via
            `self.value()`.
            """
            # Compare the requested value (either '80s' or '90s')
            # to decide how to filter the queryset.
            if self.value() == '80s':
                return queryset.filter(birthday__gte=date(1980, 1, 1),
                                        birthday__lte=date(1989, 12, 31))
            if self.value() == '90s':
                return queryset.filter(birthday__gte=date(1990, 1, 1),
                                        birthday__lte=date(1999, 12, 31))
    
    class PersonAdmin(admin.ModelAdmin):
        list_filter = (DecadeBornListFilter,)
    

    Примечание

    Для удобства объект HttpRequest передается в методы lookups и queryset, например:

    class AuthDecadeBornListFilter(DecadeBornListFilter):
    
        def lookups(self, request, model_admin):
            if request.user.is_superuser:
                return super().lookups(request, model_admin)
    
        def queryset(self, request, queryset):
            if request.user.is_superuser:
                return super().queryset(request, queryset)
    

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

    class AdvancedDecadeBornListFilter(DecadeBornListFilter):
    
        def lookups(self, request, model_admin):
            """
            Only show the lookups if there actually is
            anyone born in the corresponding decades.
            """
            qs = model_admin.get_queryset(request)
            if qs.filter(birthday__gte=date(1980, 1, 1),
                          birthday__lte=date(1989, 12, 31)).exists():
                yield ('80s', _('in the eighties'))
            if qs.filter(birthday__gte=date(1990, 1, 1),
                          birthday__lte=date(1999, 12, 31)).exists():
                yield ('90s', _('in the nineties'))
    
  • a tuple, where the first element is a field name and the second element is a class inheriting from django.contrib.admin.FieldListFilter, for example:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = (
            ('is_staff', admin.BooleanFieldListFilter),
        )
    

    Теперь вы можете ограничить фильтр значениями, которые встречаются в связи, используя RelatedOnlyFieldListFilter:

    class BookAdmin(admin.ModelAdmin):
        list_filter = (
            ('author', admin.RelatedOnlyFieldListFilter),
        )
    

    Assuming author is a ForeignKey to a User model, this will limit the list_filter choices to the users who have written a book instead of listing all users.

    Вы можете фильтровать пустые значения, используя EmptyFieldListFilter, который может фильтровать как пустые строки, так и значения NULL, в зависимости от того, что поле позволяет хранить:

    class BookAdmin(admin.ModelAdmin):
        list_filter = (
            ('title', admin.EmptyFieldListFilter),
        )
    

    Примечание

    The FieldListFilter API is considered internal and might be changed.

    Примечание

    Поле GenericForeignKey не поддерживается.

    New in Django 3.1:

    The EmptyFieldListFilter class was added.

List filter’s typically appear only if the filter has more than one choice. A filter’s has_output() method controls whether or not it appears.

Вы можете указать собственный шаблон для отображения фильтра:

class FilterWithCustomTemplate(admin.SimpleListFilter):
    template = "custom_template.html"

Конкретный пример можно найти в шаблоне приложения интерфейса администратора, который использует Django (admin/filter.html).

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.

Changed in Django 3.2:

In older versions, various English stop words are removed from generated values.

ModelAdmin.preserve_filters

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

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 будет содержать значение первичного ключа для ForeignKey или список ключей для ManyToManyField. Возле поля есть кнопка поиска и выбора связанных объектов:

../../../_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> к полю:

Префикс

Искать

^

startswith

=

iexact

@

поиск

Никто

icontains

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

Changed in Django 3.2:

Support for searching against quoted phrases with spaces was added.

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_model принимает объект HttpRequest и экземпляр модели, который удаляется. В этом методе вы может выполнить дополнительные операции до или после удаления.

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

This method may be overridden with your own custom search method. For example, you might wish to search by an integer field, or use an external tool such as Solr or Haystack. You must establish if the queryset changes implemented by your search method may introduce duplicates into the results, and return True in the second element of the return value.

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

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)

The get_fieldsets method is given the HttpRequest and the obj being edited (or None on an add form) and is expected to return a list of two-tuples, in which each two-tuple represents a <fieldset> on the admin form page, as described above in the ModelAdmin.fieldsets section.

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

The get_urls method on a ModelAdmin returns the URLs to be used for that ModelAdmin in the same way as a URLconf. Therefore you can extend them as documented in Менеджер URL-ов:

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.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 %}

Примечание

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

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

However, the self.my_view function registered above suffers from two problems:

  • It will not perform any permission checks, so it will be accessible to the general public.

  • It will not provide any header details to prevent caching. This means if the page retrieves data from the database, and caching middleware is active, the page could show outdated information.

Since this is usually not what you want, Django provides a convenience wrapper to check permissions and mark the view as non-cacheable. This wrapper is AdminSite.admin_view() (i.e. self.admin_site.admin_view inside a ModelAdmin instance); use it like so:

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

Notice the wrapped view in the fifth line above:

path('my_view/', self.admin_site.admin_view(self.my_view))

This wrapping will protect self.my_view from unauthorized access and will apply the django.views.decorators.cache.never_cache() decorator to make sure it is not cached if the cache middleware is active.

Если страницу необходимо кэшировать, но необходимо проверять авторизацию, вы можете использовать аргумент 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'] += (('ready', 'Ready for deployment'),)
        return super().formfield_for_choice_field(db_field, request, **kwargs)

Note

Атрибут 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

Note

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)

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

The lookup_allowed() method is given a lookup path from the query string (e.g. 'user__email') and the corresponding value (e.g. 'user@example.com'), and returns a boolean indicating whether filtering the changelist’s QuerySet using the parameters is permitted. If lookup_allowed() returns False, DisallowedModelAdminLookup (subclass of SuspiciousOperation) is raised.

По умолчанию 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_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() и «удалить выбранное» action.

Аргумент 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.

To avoid conflicts with user-supplied scripts or libraries, Django’s jQuery (version 3.5.1) is namespaced as django.jQuery. If you want to use jQuery in your own admin JavaScript without including a second copy, you can use the django.jQuery object on changelist and add/edit views. Also, your own admin forms or widgets depending on django.jQuery must specify js=['admin/js/jquery.init.js', …] when declaring form media assets.

Changed in Django 3.1:

jQuery was upgraded from 3.4.1 to 3.5.1.

Класс 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

class BookInline(admin.TabularInline):
    model = Book

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

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

A list or tuple containing extra CSS classes to apply to the fieldset that is rendered for the inlines. Defaults to None. As with classes configured in fieldsets, inlines with a collapse class will be initially collapsed and their header will have a small «show» link.

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

An override to the verbose_name found in the model’s inner Meta class.

InlineModelAdmin.verbose_name_plural

An override to the verbose_name_plural found in the model’s inner Meta class.

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

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

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

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

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

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

from django.db import models

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

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

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

from django.contrib import admin

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

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

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

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

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

Вторая – класс 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)

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

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

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

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

The admin template files are located in the contrib/admin/templates/admin directory.

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

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

To override an admin template for a specific app, copy and edit the template from the django/contrib/admin/templates/admin directory, and save it to one of the directories you just created.

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

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

New in Django 3.2.

The admin uses CSS variables to define colors. This allows changing colors without having to override many individual CSS rules. For example, if you preferred purple instead of blue you could add a admin/base.html template override to your project:

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

{% block extrastyle %}{{ block.super }}
<style>
:root {
  --primary: #9774d5;
  --secondary: #785cab;
  --link-fg: #7c449b;
  --link-selected-fg: #8f5bb2;
}
</style>
{% endblock %}

A dark theme is defined, and applied respecting the prefers-color-scheme media query.

The list of CSS variables are defined at django/contrib/admin/static/admin/css/base.css.

Объект AdminSite

class AdminSite(name='admin')

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

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

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

Атрибуты AdminSite

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

AdminSite.site_header

The text to put at the top of each admin page, as an <h1> (a string). By default, this is «Django administration».

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
New in Django 3.1.

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

AdminSite.final_catch_all_view
New in Django 3.2.

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

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

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

Методы AdminSite

AdminSite.each_context(request)

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

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

  • 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 к странице добавления объекта модели в админке

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 — они будут применены как опции к классу администратора.

Raises ImproperlyConfigured if a model is abstract. and django.contrib.admin.sites.AlreadyRegistered if a model is already registered.

AdminSite.unregister(model_or_iterable)

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

Raises django.contrib.admin.sites.NotRegistered if a model isn’t already registered.

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

Последний шаг это добавить ваш экземпляр AdminSite в URLconf. Выполните это добавив в URLconf метод 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.admin import AdminSite

from .models import MyModel

class MyAdminSite(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() и добавьте URL-шаблоны с вашими представлениями.

Примечание

Каждое представление, которое использует шаблоны интерфейса администратора или унаследованные шаблоны, должно указать request.current_app перед рендерингом шаблона. Он должен быть равен self.name, если представление определенно в AdminSite, или self.admin_site.name, если определено в ModelAdmin.

Добавление возможности сброса пароля

Вы можете определить возможность сбросить пароль добавив несколько строк в URLconf. А точнее добавьте эти четыре URL-шаблона:

from django.contrib.auth import views as auth_views

path(
    'admin/password_reset/',
    auth_views.PasswordResetView.as_view(),
    name='admin_password_reset',
),
path(
    'admin/password_reset/done/',
    auth_views.PasswordResetDoneView.as_view(),
    name='password_reset_done',
),
path(
    'reset/<uidb64>/<token>/',
    auth_views.PasswordResetConfirmView.as_view(),
    name='password_reset_confirm',
),
path(
    'reset/done/',
    auth_views.PasswordResetCompleteView.as_view(),
    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.

So - if you wanted to get a reference to the Change view for a particular Choice object (from the polls application) in the default admin, you would call:

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

Этот код найдет первый зарегистрированный экземпляр приложения admin (не зависимо от определенного названия экземпляра) и найдет ссылку на представление для редактирования объекта poll.Choice.

If you want to find a URL in a specific admin instance, provide the name of that instance as a current_app hint to the reverse call. For example, if you specifically wanted the admin view from the admin instance named custom, you would need to call:

>>> 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)
New in Django 3.2.

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