Интерфейс администратора Django¶
Одна из сильных сторон Django – это автоматический интерфейс администратора. Он использует мета-данные модели чтобы предоставить многофункциональный, готовый к использованию интерфейс для работы с содержимым сайта. В этом разделе мы расскажем как установить, использовать и настроить интерфейс администратора Django.
У администратора есть множество возможностей для настройки, но остерегайтесь использовать исключительно эти приемы. Если вам необходимо предоставить более ориентированный на процессы интерфейс, который абстрагирует детали реализации таблиц и полей базы данных, то, вероятно, пришло время написать свои собственные представления.
В этом документе мы обсудим, как активировать, использовать и настраивать интерфейс администратора Django.
Обзор¶
Интерфейс администратора по умолчанию включен, если вы создавали проект командой startproject.
Если необходимо самостоятельно его включить, вот требования:
Интерфейс администратора имеет четыре зависимости -
django.contrib.auth,django.contrib.contenttypes,django.contrib.messagesanddjango.contrib.sessions. Если эти приложения не входят в списокINSTALLED_APPS, добавьте их.Настройте
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.requestwas added as a requirement in the'context_processors'option to support the newAdminSite.enable_nav_sidebar.If you’ve customized the
MIDDLEWAREsetting,django.contrib.auth.middleware.AuthenticationMiddlewareanddjango.contrib.messages.middleware.MessageMiddlewaremust be included.
После всего это вы можете использовать интерфейс администратора Django посетив соответствующий URL (/admin/ по умолчанию).
Если вам нужно создать пользователя для входа в систему, используйте команду createsuperuser. По умолчанию для входа в систему администратора требуется, чтобы у пользователя для атрибута is_staff было установлено значение True.
Определите, какие модели будут редактироваться через интерфейс администратора.
Другие разделы¶
См.также
Информацию о настройке статических файлов (изображений, JavaScript и CSS) для интерфейса администратора на «боевом» сервере можно найти в разделе Обслуживание файлов.
Вопросы? Обратитесь к FAQ: Админка.
Объект ModelAdmin¶
- class ModelAdmin¶
Класс
ModelAdmin– это отображение модели в интерфейсе администратора. Его код добавляют обычно в файлadmin.pyвашего приложения. Давайте рассмотрим простой примерModelAdmin:from django.contrib import admin from myproject.myapp.models import Author class AuthorAdmin(admin.ModelAdmin): pass admin.site.register(Author, AuthorAdmin)
Нужен ли вообще вам объект
ModelAdmin?В этом примере, класс
ModelAdminне определяет никаких настроек (пока).В результате мы получим интерфейс предоставляемый по умолчанию. Если он вас устраивает, вы можете не определятьModelAdminсовсем и зарегистрировать модель безModelAdmin. Пример выше может выглядеть таким образом:from django.contrib import admin from myproject.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') def view_birth_date(self, obj): return obj.birth_date view_birth_date.empty_value_display = '???'
- 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
fieldsoption accepts the same types of values aslist_display, except that callables aren’t accepted. Names of model and model admin methods will only be used if they’re listed inreadonly_fields.Чтобы поля отображались в одной строке, укажите их в кортеже вместе. В этом примере, поля
urlиtitleбудут отображаться в одном ряду, полеcontentбудет расположено ниже:class FlatPageAdmin(admin.ModelAdmin): fields = (('url', 'title'), 'content')
Note
Настройку
fieldsне следует путать с ключом словаряfieldsв настройкеfieldsets, описанной ниже.Если не определен ни атрибут
fields, ниfieldsets, Django покажет все поля сeditable=TrueкромеAutoField, в одном наборе полей в порядке, в котором они указанные в модели.
- ModelAdmin.fieldsets¶
Позволяет изменить макет страниц добавления и редактирования объекта.
fieldsetsis 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), wherenameis a string representing the title of the fieldset andfield_optionsis 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'), }), )
Этот пример будет выглядеть следующим образом:
Если не определен ни атрибут
fields, ниfieldsets, Django покажет все поля сeditable=TrueкромеAutoField, в одном наборе полей в порядке, в котором они указанные в модели.Словарь
field_optionsможет содержать следующие ключи:fieldsA 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.
classesA 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
collapseandwide. Fieldsets with thecollapsestyle will be initially collapsed in the admin and replaced with a small «click to expand» link. Fieldsets with thewidestyle will be given extra horizontal space.
descriptionA 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
TabularInlinedue 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:Поле модели. Например:
class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name')
Функция, которая принимает один аргумент - объект модели. Например:
def upper_case_name(obj): return ("%s %s" % (obj.first_name, obj.last_name)).upper() upper_case_name.short_description = 'Name' class PersonAdmin(admin.ModelAdmin): list_display = (upper_case_name,)
Функция, которая принимает один аргумент - объект модели. Например:
class PersonAdmin(admin.ModelAdmin): list_display = ('upper_case_name',) def upper_case_name(self, obj): return ("%s %s" % (obj.first_name, obj.last_name)).upper() upper_case_name.short_description = 'Name'
Название атрибута
ModelAdmin. Работает так же, как и функция. Например:from django.contrib import admin from django.db import models class Person(models.Model): name = models.CharField(max_length=50) birthday = models.DateField() def decade_born_in(self): return '%d’s' % (self.birthday.year // 10 * 10) decade_born_in.short_description = 'Birth decade' 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) 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')
As some examples have already demonstrated, when using a callable, a model method, or a
ModelAdminmethod, you can customize the column’s title by adding ashort_descriptionattribute to the callable.Если значение поля
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') def birth_date_view(self, obj): return obj.birth_date birth_date_view.empty_value_display = 'unknown'
If the string given is a method of the model,
ModelAdminor a callable that returnsTrue,False, orNone, Django will display a pretty «yes», «no», or «unknown» icon if you give the method abooleanattribute whose value isTrue.Пример:
from django.contrib import admin from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) birthday = models.DateField() def born_in_fifties(self): return 1950 <= self.birthday.year < 1960 born_in_fifties.boolean = True class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'born_in_fifties')
Метод
__str__()(__unicode__()в Python 2) можно использовать вlist_displayкак и любой другой метод модели:list_display = ('__str__', 'some_other_field')
Обычно элементы
list_display, которые не являются полями модели, не могу быть использованы при сортировке (так как Django выполняет сортировку на уровне базы данных).However, if an element of
list_displayrepresents a certain database field, you can indicate this fact by setting theadmin_order_fieldattribute of the item.Например:
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) def colored_first_name(self): return format_html( '<span style="color: #{};">{}</span>', self.color_code, self.first_name, ) colored_first_name.admin_order_field = 'first_name' class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'colored_first_name')
В этом примере Django будет использовать поле
first_nameпри сортировке поcolored_first_name.To indicate descending order with
admin_order_fieldyou can use a hyphen prefix on the field name. Using the above example, this would look like:colored_first_name.admin_order_field = '-first_name'
admin_order_fieldsupports query lookups to sort by values on related models. This example includes an «author first name» column in the list display and allows sorting it by first name: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') def author_first_name(self, obj): return obj.author.first_name author_first_name.admin_order_field = 'author__first_name'
Query expressions may be used in
admin_order_field. For example: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) def full_name(self): return self.first_name + ' ' + self.last_name full_name.admin_order_field = Concat('first_name', Value(' '), 'last_name')
Elements of
list_displaycan also be properties. Please note however, that due to the way properties work in Python, settingshort_descriptionoradmin_order_fieldon a property is only possible when using theproperty()function and not with the@propertydecorator.Например:
class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) 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) class PersonAdmin(admin.ModelAdmin): list_display = ('full_name',)
Названия полей из
list_displayбудут использованы в CSS классах, форма будет содержать классcolumn-<field_name>для каждого элемента<th>. Так можно определить ширину полей через CSS стили.Django попытается интерпретировать каждый элемент
list_displayв следующем порядке:A field of the model.
Метод или любой другой вызываемый объект.
Строка, представляющая атрибут
ModelAdmin.Строка, представляющая атрибут модели.
Например, если существует поле модели
first_nameи атрибутModelAdmin, будет использоваться поле модели.
- ModelAdmin.list_display_links¶
Используйте
list_display_links, чтобы указать какие поля вlist_displayбудут ссылками на страницу редактирования объекта.По умолчанию, на страницу редактирования объекта будет вести ссылка в первой колонке – первое поле в
list_display. Ноlist_display_linksпозволяет изменить это поведение:Можно указать
None, чтобы убрать ссылки.Укажите список или кортеж полей (так же как и в
list_display) чьи колонки должны быть ссылками на страницу редактирования.Вы можете указывать одно или несколько полей. Пока указанные поля входят в
list_display, Django безразлично сколько их. Единственное требование: для использованияlist_display_linksвы должны указатьlist_display.
В этом примере поля
first_nameиlast_nameбудут отображаться как ссылки на страницу редактирования объекта:class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'birthday') list_display_links = ('first_name', 'last_name')
В этом примере список объектов будет без ссылок:
class AuditEntryAdmin(admin.ModelAdmin): list_display = ('timestamp', 'message') list_display_links = None
- ModelAdmin.list_editable¶
Укажите в
list_editableсписок полей, которые можно будет редактировать на странице списка объектов. То есть, поля изlist_editableбудут отображаться как поля формы позволяя пользователям изменять значения и сохранять изменения для всех строк сразу.Примечание
list_editableвзаимодействует с другими настройками следующим образом:Поле из
list_editableдолжно входить вlist_display. Вы не можете редактировать поле, которое не отображается!Поле не может быть в
list_editableиlist_display_linksвместе – поле не может быть ссылкой и полем формы.
Вы получите ошибку проверки если нарушите эти правила.
- ModelAdmin.list_filter¶
Set
list_filterto activate filters in the right sidebar of the change list page of the admin, as illustrated in the following screenshot:
list_filtershould 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,ForeignKeyorManyToManyField, 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 thetitleandparameter_nameattributes to and override thelookupsandquerysetmethods, 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
authoris aForeignKeyto aUsermodel, this will limit thelist_filterchoices 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
FieldListFilterAPI is considered internal and might be changed.Примечание
Поле
GenericForeignKeyне поддерживается.New in Django 3.1:The
EmptyFieldListFilterclass 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",)}
When set, the given fields will use a bit of JavaScript to populate from the fields assigned. The main use for this functionality is to automatically generate the value for
SlugFieldfields from one or more other fields. The generated value is produced by concatenating the values of the source fields, and then by transforming that result into a valid slug (e.g. substituting dashes for spaces; lowercasing ASCII letters; and removing various English stop words such as „a“, „an“, „as“, and similar).Предварительно заполненные поля не изменяются с помощью JavaScript после сохранения значения. Обычно нежелательно, чтобы слаги менялись (это может привести к изменению URL-адреса объекта, если в нем используется слаг).
prepopulated_fieldsне принимает поляDateTimeField,ForeignKeyилиManyToManyField.
- 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. Возле поля есть кнопка поиска и выбора связанных объектов:
- 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',) 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>") # short_description functions like a model field's verbose_name address_report.short_description = "Address"
- 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%')
Если вы не хотите использовать «icontains» для поиска, вы можете использовать любой поиск, добавив его в поле. Например, вы можете использовать
exact, установив дляsearch_fieldsзначение['first_name__exact'].Beware that because query terms are split and ANDed as described earlier, searching with
exactonly works with a single search word since two or more words can’t all be an exact match unless all words are the same.Также доступны некоторые (более старые) сочетания клавиш для задания поиска по полю. Вы можете префикс поля в
search_fieldsследующими символами, и это эквивалентно добавлению__<lookup>к полю:Префикс
Искать
^
=
@
поискНикто
Вы можете переопределить метод
ModelAdmin.get_search_results(), чтобы указать дополнительные параметры при поиске, или переопределить механизм поиска.
- 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¶
By default, the change list page allows sorting by all model fields (and callables that have the
admin_order_fieldproperty) specified inlist_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
Truein 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, use_distinct = 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, use_distinct
Эта реализация более эффективна, чем
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.
- ModelAdmin.get_list_display_links(request, list_display)¶
Метод
get_list_display_linksпринимает объектHttpRequestиlistилиtupleуказанный вModelAdmin.get_list_display(). Должен вернутьNone,listилиtupleсодержащий список полей, который будут ссылками на странице списка объектов к странице редактирования. Смотрите описаниеModelAdmin.list_display_links.
- ModelAdmin.get_exclude(request, obj=None)¶
Метод
get_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_fieldsetsmethod is given theHttpRequestand theobjbeing edited (orNoneon 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 theModelAdmin.fieldsetssection.
- 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)¶
- New in Django 3.0.
Метод
get_fieldsпринимает объектHttpRequestи редактируемый объектobj(илиNoneдля формы создания нового объекта) и должен вернуть список полей аналогичныйModelAdmin.fields.
- ModelAdmin.get_urls()¶
The
get_urlsmethod on aModelAdminreturns 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_viewfunction 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_viewinside aModelAdmininstance); 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_viewfrom unauthorized access and will apply thedjango.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’sQuerySetusing the parameters is permitted. Iflookup_allowed()returnsFalse,DisallowedModelAdminLookup(subclass ofSuspiciousOperation) 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.
jQuery was upgraded from 3.3.1 to 3.4.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, иначе сжатая версия.
Дополнительная проверка данных в интерфейсе администратора¶
You can also add custom validation of data in the admin. The automatic admin
interface reuses django.forms, and the ModelAdmin class gives you
the ability define your own form:
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, вот они:
get_queryset()
Параметры класса 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 infieldsets, inlines with acollapseclass 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_namefound in the model’s innerMetaclass.
- InlineModelAdmin.verbose_name_plural¶
An override to the
verbose_name_pluralfound in the model’s innerMetaclass.
- InlineModelAdmin.can_delete¶
Определяет можно ли удалять связанные объекты. По умолчанию равно
True.
- InlineModelAdmin.show_change_link¶
Определяет показывать ли ссылку на форму изменения для связанных объектов, которые можно изменять. По умолчанию равно
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,
]
Работа со связями многие-ко-многим¶
By default, admin widgets for many-to-many relations will be displayed
on whichever model contains the actual reference to the
ManyToManyField. Depending on your ModelAdmin
definition, each many-to-many field in your model will be represented by a
standard HTML <select multiple>, a horizontal or vertical filter, or a
raw_id_admin widget. However, it is also possible to replace these
widgets with inlines.
Предположим у нас есть следующие модели:
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 myproject.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.htmlapp_index.htmlchange_form.htmlchange_form.htmlchange_list.htmlchange_list.htmlchange_list.htmlobject_history.htmldelete_confirmation.htmlobject_history.htmlchange_list.htmlapp_index.htmlapp_index.htmlchange_form.htmlapp_index.html
Остальные шаблоны вы можете все еще переопределить для всего проекта. Просто добавьте новую версию шаблона в каталог templates/admin. Это особенно полезно для переопределения страниц для 404 и 500 ошибки.
Примечание
Некоторые шаблоны, такие как change_list_request.html используются для отображения включаемых тегов(inclusion tags). Вы можете переопределить их, но лучше создать собственную версию тега, которая будет использовать новый шаблон. В этом случае вы сможете использовать оба шаблона.
Главный шаблон и шаблон страницы входа¶
Чтобы переопределить шаблоны главной страницы и страниц входа/выхода, лучше создать собственный экземпляр AdminSite (смотрите ниже), и изменить свойства AdminSite.index_template , AdminSite.login_template и AdminSite.logout_template.
Объект 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.
- New in Django 3.1.
Логическое значение, определяющее, отображать ли боковую панель навигации на больших экранах. По умолчанию установлено значение «True».
- 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_headersite_title:AdminSite.site_titlesite_url:AdminSite.site_urlhas_permission:AdminSite.has_permission()available_apps: список приложений из регистра приложений, которые доступны для текущего пользователя. Каждый элемент списка содержит словарь, который представляет приложение, со следующими ключами:app_label: название приложенияapp_url: URL главное страницы приложения в админкеhas_module_perms: булево, которые указывает есть ли у пользователя права к главной странице приложения в админкеmodels: список моделей прилоджения
Каждая модель представлена словарем со следующими ключами:
object_name: название класса моделиname: множественное название моделиperms:dictсо значениями правadd,changeиdeleteadmin_url: URL к странице списка объектов модели в админкеadd_url: URL к странице добавления объекта модели в админке
- AdminSite.has_permission(request)¶
Возвращает
True, если пользователь из переданногоHttpRequestимеет доступ хотя бы к одной странице админки. По умолчанию проверяется равны лиUser.is_activeиUser.is_staffTrue.
- AdminSite.register(model_or_iterable, admin_class=None, **options)¶
Регистрирует данный класс модели (или итерацию классов) с заданным
admin_class.admin_classпо умолчанию имеет значениеModelAdmin(параметры администратора по умолчанию). Если указаны аргументы ключевого слова, напримерlist_display— они будут применены как опции к классу администратора.Raises
ImproperlyConfiguredif a model is abstract. anddjango.contrib.admin.sites.AlreadyRegisteredif a model is already registered.
- AdminSite.unregister(model_or_iterable)¶
Отменяет регистрацию данного класса модели (или итерации классов).
Raises
django.contrib.admin.sites.NotRegisteredif 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.
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)
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, либо вызываемого объекта, который возвращает экземпляр сайта.
from django.contrib import admin
class MyAdminSite(admin.AdminSite):
...
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
INSTALLED_APPS = [
...
'myproject.apps.MyAdminConfig', # replaces 'django.contrib.admin'
...
]
Несколько интерфейсов администратора в одном URLconf¶
Django позволяет легко создать несколько интерфейсов администратора для одного сайта. Просто создайте несколько экземпляров AdminSite и добавьте его к различным URL-ам.
В этом примере, URL-ы /basic-admin/ и /advanced-admin/ ведут к различным экземплярам AdminSite – myproject.admin.basic_site и myproject.admin.advanced_site соответственно:
# urls.py
from django.urls import path
from myproject.admin import advanced_site, basic_site
urlpatterns = [
path('basic-admin/', basic_site.urls),
path('advanced-admin/', advanced_site.urls),
]
Конструктор AdminSite принимает единственный аргумент – название экземпляра, которое может быть любым. Это значение будет использоваться как префикс для названий URL при их поиске. Это необходимо если вы используете несколько экземпляров AdminSite.
Добавление представлений в интерфейс администратора¶
Как и ModelAdmin AdminSite содержит метод get_urls(), который можно переопределить и добавить собственные представления в интерфейс администратора. Переопределите метод get_urls() и добавьте URL-шаблоны с вашими представлениями.
Примечание
Каждое представление, которое использует шаблоны интерфейса администратора или унаследованные шаблоны, должно указать request.current_app перед рендерингом шаблона. Он должен быть равен self.name, если представление определенно в AdminSite, или self.admin_site.name, если определено в ModelAdmin.
Добавление возможности сброса пароля¶
Вы можете определить возможность сбросить пароль добавив несколько строк в URLconf. А точнее добавьте эти четыре 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-а |
Параметры |
|---|---|---|
Главная |
|
|
Авторизоваться |
|
|
Выхода |
|
|
Смена пароля |
|
|
Завершения смены пароля |
|
|
i18n JavaScript |
|
|
Главная страница приложения |
|
|
Редирект на страницу объекта |
|
|
Каждый экземпляр ModelAdmin предоставляет дополнительные именованные URL-шаблоны:
Страница |
Название URL-а |
Параметры |
|---|---|---|
Список объектов |
|
|
Добавления объекта |
|
|
Истории |
|
|
Удаления объекта |
|
|
Изменения объекта |
|
|
UserAdmin предоставляет следующие именованные URL-шаблоны:
Страница |
Название URL-а |
Параметры |
|---|---|---|
Смена пароля |
|
|
Эти именованные 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, эта переменная обычно указывается представлением в интерфейсе администратора для текущей модели.
Декоратор staff_member_required¶
- staff_member_required(redirect_field_name='next', login_url='admin:login')¶
This decorator is used on the admin views that require authorization. A view decorated with this function will having the following behavior:
Если пользователь авторизирован, и он администратор (
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): ...