Сайт администратора Django¶
Одна из самых мощных частей Django - это автоматический интерфейс администратора. Он считывает метаданные из ваших моделей, чтобы обеспечить быстрый, ориентированный на модели интерфейс, в котором доверенные пользователи могут управлять содержимым вашего сайта. Рекомендуемое использование администратора ограничено внутренним инструментом управления организации. Он не предназначен для создания всего фронт-энда.
В админке есть множество крючков для настройки, но остерегайтесь попыток использовать исключительно эти крючки. Если вам нужно предоставить более ориентированный на процесс интерфейс, который абстрагируется от деталей реализации таблиц и полей базы данных, то, вероятно, пришло время написать собственные представления.
В этом документе мы обсудим, как активировать, использовать и настраивать интерфейс администратора Django.
Обзор¶
Администратор включен в шаблон проекта по умолчанию, используемый startproject
.
Если вы не используете шаблон проекта по умолчанию, вот требования:
Добавьте
'django.contrib.admin'
и его зависимости -django.contrib.auth
,django.contrib.contenttypes
,django.contrib.messages
иdjango.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.request
был добавлен в качестве требования в опцию'context_processors'
для поддержки новойAdminSite.enable_nav_sidebar
.Если вы настроили параметр
MIDDLEWARE
,django.contrib.auth.middleware.AuthenticationMiddleware
иdjango.contrib.messages.middleware.MessageMiddleware
должны быть включены.
После выполнения этих действий вы сможете воспользоваться сайтом администратора, посетив URL, к которому вы его подключили (/admin/
, по умолчанию).
Если вам нужно создать пользователя для входа в систему, используйте команду createsuperuser
. По умолчанию для входа в систему администратора требуется, чтобы у пользователя атрибут is_staff
был установлен на True
.
Наконец, определите, какие из моделей вашего приложения должны быть доступны для редактирования в интерфейсе администратора. Для каждой из этих моделей зарегистрируйте их в админке, как описано в ModelAdmin
.
Другие темы¶
См.также
Информацию об обслуживании статических файлов (изображений, JavaScript и CSS), связанных с администратором в продакшене, смотрите в разделе Служебные файлы.
Возникли проблемы? Попробуйте ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ: Администратор.
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
¶
-
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
. Если вы используете пользовательскийAdminSite
, передайте его с помощью аргументаsite
ключевого слова:from django.contrib import admin from .models import Author, Editor, Reader from myproject.admin_site import custom_admin_site @admin.register(Author, Reader, Editor, site=custom_admin_site) class PersonAdmin(admin.ModelAdmin): pass
Вы не можете использовать этот декоратор, если вам нужно ссылаться на класс администратора модели в его методе
__init__()
, например,super(PersonAdmin, self).__init__(*args, **kwargs)
. Вы можете использоватьsuper().__init__(*args, **kwargs)
.
Обнаружение файлов администратора¶
Когда вы ставите 'django.contrib.admin'
в настройках INSTALLED_APPS
, Django автоматически ищет admin
модуль в каждом приложении и импортирует его.
-
class
apps.
AdminConfig
¶ Это класс по умолчанию
AppConfig
для администратора. Он вызываетautodiscover()
при запуске Django.
-
class
apps.
SimpleAdminConfig
¶ Этот класс работает как
AdminConfig
, за исключением того, что он не вызываетautodiscover()
.-
default_site
¶ Точечный путь импорта к классу сайта администратора по умолчанию или к вызываемому объекту, который возвращает экземпляр сайта. По умолчанию имеет значение
'django.contrib.admin.sites.AdminSite'
. Использование см. в Переопределение сайта администратора по умолчанию.
-
-
autodiscover
()[исходный код]¶ Эта функция пытается импортировать модуль
admin
в каждое установленное приложение. Ожидается, что такие модули будут регистрировать модели в админке.Обычно вам не нужно вызывать эту функцию напрямую, так как
AdminConfig
вызывает ее при запуске Django.
Если вы используете пользовательский AdminSite
, то обычно импортируете все подклассы ModelAdmin
в свой код и регистрируете их в пользовательском AdminSite
. В этом случае, чтобы отключить автоматическое обнаружение, в настройках 'django.contrib.admin.apps.SimpleAdminConfig'
вместо 'django.contrib.admin'
нужно поставить INSTALLED_APPS
.
ModelAdmin
опции¶
ModelAdmin
является очень гибким. Он имеет несколько опций для настройки интерфейса. Все опции определены в подклассе ModelAdmin
:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = 'pub_date'
-
ModelAdmin.
actions
¶ Список действий, которые необходимо сделать доступными на странице списка изменений. Подробнее см. в Действия администратора.
-
ModelAdmin.
actions_on_top
¶
-
ModelAdmin.
actions_on_bottom
¶ Управляет тем, где на странице отображается панель действий. По умолчанию в списке изменений администратора действия отображаются в верхней части страницы (
actions_on_top = True; actions_on_bottom = False
).
-
ModelAdmin.
actions_selection_counter
¶ Управляет тем, будет ли отображаться счетчик выбора рядом с выпадающим списком действий. По умолчанию он отображается в списке изменений администратора (
actions_selection_counter = True
).
-
ModelAdmin.
date_hierarchy
¶ Установите
date_hierarchy
на имяDateField
илиDateTimeField
в вашей модели, и страница списка изменений будет содержать навигацию по дате по этому полю.Пример:
date_hierarchy = 'pub_date'
Вы также можете указать поле в связанной модели с помощью поиска
__
, например:date_hierarchy = 'author__pub_date'
Он будет интеллектуально заполняться на основе имеющихся данных, например, если все даты относятся к одному месяцу, он будет показывать только детализацию на уровне дня.
Примечание
date_hierarchy
используетQuerySet.datetimes()
внутренне. Если включена поддержка часовых поясов (USE_TZ = True
), обратитесь к документации к нему, чтобы узнать некоторые предостережения.
-
ModelAdmin.
empty_value_display
¶ Этот атрибут переопределяет значение отображения по умолчанию для полей записи, которые пусты (
None
, пустая строка и т.д.). Значением по умолчанию является-
(тире). Например:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): empty_value_display = '-empty-'
Вы также можете переопределить
empty_value_display
для всех страниц администратора наAdminSite.empty_value_display
, или для определенных полей, например, так:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): 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',)
Поскольку модель Author имеет только три поля,
name
,title
иbirth_date
, формы, полученные в результате вышеприведенных деклараций, будут содержать точно такие же поля.
-
ModelAdmin.
fields
¶ Используйте опцию
fields
, чтобы внести простые изменения в макет форм на страницах «добавить» и «изменить», например, показать только часть доступных полей, изменить их порядок или сгруппировать их в строки. Например, вы можете определить более простую версию формы администратора для моделиdjango.contrib.flatpages.models.FlatPage
следующим образом:class FlatPageAdmin(admin.ModelAdmin): fields = ('url', 'title', 'content')
В приведенном выше примере в форме будут последовательно отображаться только поля
url
,title
иcontent
.fields
может содержать значения, определенные вModelAdmin.readonly_fields
, которые будут отображаться только для чтения.Для более сложной компоновки см. опцию
fieldsets
.Опция
fields
принимает те же типы значений, что иlist_display
, за исключением того, что callables не принимаются. Имена методов model и model admin будут использоваться, только если они перечислены вreadonly_fields
.Чтобы отобразить несколько полей на одной строке, оберните эти поля в собственный кортеж. В этом примере поля
url
иtitle
будут отображаться на одной строке, а полеcontent
будет отображаться под ними на своей собственной строке:class FlatPageAdmin(admin.ModelAdmin): fields = (('url', 'title'), 'content')
Примечание
Эту опцию
fields
не следует путать с ключом словаряfields
, который находится внутри опцииfieldsets
, как описано в следующем разделе.Если нет ни
fields
, ниfieldsets
, Django будет по умолчанию отображать каждое поле, которое не являетсяAutoField
и имеетeditable=True
, в одном наборе полей, в том же порядке, в котором поля определены в модели.
-
ModelAdmin.
fieldsets
¶ Установите
fieldsets
для управления макетом страниц администратора «добавить» и «изменить».fieldsets
- это список из двух кортежей, в котором каждый кортеж представляет<fieldset>
на странице формы администратора. (<fieldset>
- это «раздел» формы).Два кортежа имеют формат
(name, field_options)
, гдеname
- строка, представляющая заголовок набора полей, аfield_options
- словарь информации о наборе полей, включая список полей, которые будут в нем отображаться.Полный пример, взятый из модели
django.contrib.flatpages.models.FlatPage
:from django.contrib import admin class FlatPageAdmin(admin.ModelAdmin): fieldsets = ( (None, { 'fields': ('url', 'title', 'content', 'sites') }), ('Advanced options', { 'classes': ('collapse',), 'fields': ('registration_required', 'template_name'), }), )
В результате откроется страница администратора, которая будет выглядеть следующим образом:
Если нет ни
fieldsets
, ниfields
, Django будет по умолчанию отображать каждое поле, которое не являетсяAutoField
и имеетeditable=True
, в одном наборе полей, в том же порядке, в котором поля определены в модели.Словарь
field_options
может иметь следующие ключи:fields
Кортеж имен полей для отображения в этом наборе полей. Этот ключ является обязательным.
Пример:
{ 'fields': ('first_name', 'last_name', 'address', 'city', 'state'), }
Как и в случае с опцией
fields
, чтобы отобразить несколько полей на одной строке, оберните эти поля в собственный кортеж. В этом примере поляfirst_name
иlast_name
будут отображаться на одной строке:{ 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'), }
fields
может содержать значения, определенные вreadonly_fields
, которые будут отображаться только для чтения.Если вы добавляете имя вызываемого объекта в
fields
, действует то же правило, что и с опциейfields
: вызываемый объект должен быть указан вreadonly_fields
.
classes
Список или кортеж, содержащий дополнительные классы CSS для применения к набору полей.
Пример:
{ 'classes': ('wide', 'extrapretty'), }
Два полезных класса, определяемых таблицей стилей сайта администратора по умолчанию, это
collapse
иwide
. Наборы полей со стилемcollapse
будут изначально свернуты в админке и заменены маленькой ссылкой «click to expand». Наборы полей со стилемwide
будут иметь дополнительное горизонтальное пространство.
description
Строка необязательного дополнительного текста, который будет отображаться в верхней части каждого набора полей под заголовком набора полей. Эта строка не отображается для
TabularInline
из-за его расположения.Обратите внимание, что это значение не имеет HTML-выражения при отображении в интерфейсе администратора. Это позволит вам включить HTML, если вы того пожелаете. В качестве альтернативы вы можете использовать обычный текст и
django.utils.html.escape()
для экранирования любых специальных символов HTML.
-
ModelAdmin.
filter_horizontal
¶ По умолчанию
ManyToManyField
отображается на сайте администратора вместе с<select multiple>
. Однако поля множественного выбора могут быть сложны в использовании при выборе большого количества элементов. ДобавлениеManyToManyField
к этому списку вместо этого будет использовать удобный ненавязчивый интерфейс JavaScript «фильтр», который позволяет осуществлять поиск внутри опций. Невыбранные и выбранные варианты отображаются в двух ячейках рядом друг с другом. Для использования вертикального интерфейса смотритеfilter_vertical
.
-
ModelAdmin.
filter_vertical
¶ Аналогично
filter_horizontal
, но использует вертикальное отображение интерфейса фильтра, при этом поле невыбранных опций отображается над полем выбранных опций.
-
ModelAdmin.
form
¶ По умолчанию для вашей модели динамически создается
ModelForm
. Он используется для создания формы, представленной на обеих страницах добавления/изменения. Вы можете легко предоставить свою собственнуюModelForm
, чтобы отменить любое поведение формы по умолчанию на страницах добавления/изменения. Кроме того, вы можете настроить форму по умолчанию вместо того, чтобы задавать совершенно новую, используя методModelAdmin.get_form()
.Пример см. в разделе Добавление пользовательской валидации в админку.
Примечание
Если вы определяете атрибут
Meta.model
наModelForm
, вы также должны определить атрибутMeta.fields
(или атрибутMeta.exclude
). Однако, поскольку администратор имеет свой собственный способ определения полей, атрибутMeta.fields
будет проигнорирован.Если
ModelForm
будет использоваться только для администратора, самым простым решением будет опустить атрибутMeta.model
, так какModelAdmin
предоставит правильную модель для использования. В качестве альтернативы вы можете установитьfields = []
в классеMeta
, чтобы удовлетворить проверку наModelForm
.Примечание
Если ваши
ModelForm
иModelAdmin
оба определяют опциюexclude
, то приоритет имеетModelAdmin
:from django import forms from django.contrib import admin from myapp.models import Person class PersonForm(forms.ModelForm): class Meta: model = Person exclude = ['name'] class PersonAdmin(admin.ModelAdmin): exclude = ['age'] form = PersonForm
В приведенном выше примере поле «возраст» будет исключено, но поле «имя» будет включено в созданную форму.
-
ModelAdmin.
formfield_overrides
¶ Это обеспечивает быстрый и грязный способ переопределения некоторых опций
Field
для использования в админке.formfield_overrides
- это словарь, отображающий класс поля на дикту аргументов, которые нужно передать полю во время конструирования.Поскольку это немного абстрактно, давайте рассмотрим конкретный пример. Наиболее распространенное использование
formfield_overrides
- это добавление пользовательского виджета для определенного типа поля. Итак, представьте, что мы написалиRichTextEditorWidget
, который мы хотели бы использовать для больших текстовых полей вместо стандартного<textarea>
. Вот как мы это сделаем:from django.contrib import admin from django.db import models # Import our custom widget and our model from where they're defined from myapp.models import MyModel from myapp.widgets import RichTextEditorWidget class MyModelAdmin(admin.ModelAdmin): formfield_overrides = { models.TextField: {'widget': RichTextEditorWidget}, }
Обратите внимание, что ключом в словаре является сам класс поля, не строка. Значением является другой словарь; эти аргументы будут переданы в метод
__init__()
поля формы. Подробности см. в разделе API форм.Предупреждение
Если вы хотите использовать пользовательский виджет с полем отношения (т.е.
ForeignKey
илиManyToManyField
), убедитесь, что вы не включили имя этого поля вraw_id_fields
,radio_fields
илиautocomplete_fields
.formfield_overrides
не позволит вам изменить виджет для полей отношения, для которых установленыraw_id_fields
,radio_fields
илиautocomplete_fields
. Это потому, чтоraw_id_fields
,radio_fields
иautocomplete_fields
подразумевают собственные виджеты.
-
ModelAdmin.
inlines
¶ См. объекты
InlineModelAdmin
ниже, а такжеModelAdmin.get_formsets_with_inlines()
.
-
ModelAdmin.
list_display
¶ Установите
list_display
, чтобы контролировать, какие поля отображаются на странице списка изменений администратора.Пример:
list_display = ('first_name', 'last_name')
Если вы не установите
list_display
, на сайте администратора будет отображаться один столбец, в котором будет показано__str__()
представление каждого объекта.Существует четыре типа значений, которые могут быть использованы в
list_display
:Имя поля модели. Например:
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,)
Строка, представляющая метод
ModelAdmin
, который принимает один аргумент - экземпляр модели. Например: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'
Строка, представляющая атрибут или метод модели (без обязательных аргументов). Например:
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__()
связанного объекта.Поля
ManyToManyField
не поддерживаются, поскольку это повлечет за собой выполнение отдельного SQL-запроса для каждой строки таблицы. Если вы все же хотите сделать это, создайте для своей модели пользовательский метод и добавьте имя этого метода вlist_display
. (Подробнее о пользовательских методах вlist_display
см. ниже).Если поле имеет значение
BooleanField
, Django отобразит красивый значок «да», «нет» или «неизвестно» вместоTrue
,False
илиNone
.Если указанная строка является методом модели,
ModelAdmin
или вызываемым методом, Django по умолчанию будет HTML-скриптовать вывод. Чтобы экранировать пользовательский ввод и разрешить собственные теги без экранирования, используйтеformat_html()
.Вот полный пример модели:
from django.contrib import admin from django.db import models from django.utils.html import format_html class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) color_code = models.CharField(max_length=6) def colored_name(self): return format_html( '<span style="color: #{};">{} {}</span>', self.color_code, self.first_name, self.last_name, ) class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'colored_name')
Как уже показали некоторые примеры, при использовании вызываемого объекта, метода модели или метода
ModelAdmin
, вы можете настроить заголовок колонки, добавив атрибутshort_description
к вызываемому объекту.Если значение поля
None
, пустая строка или итерабельность без элементов, Django отобразит-
(тире). Вы можете переопределить это значение с помощьюAdminSite.empty_value_display
:from django.contrib import admin admin.site.empty_value_display = '(None)'
Вы также можете использовать
ModelAdmin.empty_value_display
:class PersonAdmin(admin.ModelAdmin): empty_value_display = 'unknown'
Или на полевом уровне:
class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'birth_date_view') def birth_date_view(self, obj): return obj.birth_date birth_date_view.empty_value_display = 'unknown'
Если заданная строка является методом модели,
ModelAdmin
или вызываемым методом, который возвращаетTrue
,False
илиNone
, Django отобразит красивую иконку «yes», «no» или «unknown», если вы зададите методу атрибутboolean
, значение которогоTrue
.Вот полный пример модели:
from django.contrib import admin from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) birthday = models.DateField() 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__()
так же действителен вlist_display
, как и любой другой метод моделирования, так что это совершенно нормально:list_display = ('__str__', 'some_other_field')
Обычно элементы
list_display
, которые не являются фактическими полями базы данных, не могут быть использованы в сортировке (потому что Django делает всю сортировку на уровне базы данных).Однако, если элемент
list_display
представляет определенное поле базы данных, вы можете указать на этот факт, установив атрибут элементаadmin_order_field
.Например:
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
в админке.Чтобы указать порядок убывания с помощью
admin_order_field
, можно использовать префикс дефиса в имени поля. Используя приведенный выше пример, это будет выглядеть так:colored_first_name.admin_order_field = '-first_name'
admin_order_field
поддерживает поиск запросов для сортировки по значениям в связанных моделях. Этот пример включает столбец «имя автора» в отображение списка и позволяет сортировать его по имени: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 может использоваться в
admin_order_field
. Например: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')
Элементы
list_display
также могут быть свойствами. Однако обратите внимание, что из-за особенностей работы свойств в Python, установкаshort_description
илиadmin_order_field
на свойство возможна только при использовании функцииproperty()
и не при использовании декоратора@property
.Например:
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 в HTML-выводе в видеcolumn-<field_name>
на каждом элементе<th>
. Это можно использовать, например, для задания ширины колонок в CSS-файле.Django попытается интерпретировать каждый элемент
list_display
в таком порядке:- Поле модели.
- Вызываемый.
- Строка, представляющая атрибут
ModelAdmin
. - Строка, представляющая атрибут модели.
Например, если у вас есть
first_name
как поле модели и как атрибутModelAdmin
, будет использоваться поле модели.
-
ModelAdmin.
list_display_links
¶ Используйте
list_display_links
для управления тем, должны ли и какие поля вlist_display
быть связаны со страницей «изменения» для объекта.По умолчанию страница списка изменений будет связывать первый столбец - первое поле, указанное в
list_display
- со страницей изменений для каждого элемента. Ноlist_display_links
позволяет вам изменить это:Установите значение
None
, чтобы вообще не получать ссылок.Установите его в список или кортеж полей (в том же формате, что и
list_display
), столбцы которых вы хотите преобразовать в ссылки.Вы можете указать одно или много полей. До тех пор, пока поля отображаются в
list_display
, Django неважно, сколько (или сколько мало) полей связано. Единственное требование - если вы хотите использоватьlist_display_links
таким образом, вы должны определитьlist_display
.
В этом примере поля
first_name
иlast_name
будут связаны на странице списка изменений:class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'birthday') list_display_links = ('first_name', 'last_name')
В этом примере сетка страницы списка изменений не будет иметь ссылок:
class AuditEntryAdmin(admin.ModelAdmin): list_display = ('timestamp', 'message') list_display_links = None
-
ModelAdmin.
list_editable
¶ Установите
list_editable
в список имен полей в модели, которые позволят редактировать на странице списка изменений. То есть поля, перечисленные вlist_editable
, будут отображаться в виде виджетов формы на странице списка изменений, позволяя пользователям редактировать и сохранять несколько строк одновременно.Примечание
list_editable
взаимодействует с парой других опций особым образом; вам следует обратить внимание на следующие правила:- Любое поле в
list_editable
должно быть также вlist_display
. Вы не можете редактировать поле, которое не отображается! - Одно и то же поле не может быть указано в
list_editable
иlist_display_links
- поле не может быть одновременно формой и ссылкой.
Если одно из этих правил нарушено, вы получите ошибку валидации.
- Любое поле в
-
ModelAdmin.
list_filter
¶ Установите
list_filter
для активации фильтров в правой боковой панели страницы списка изменений в админке, как показано на следующем снимке экрана:list_filter
должен быть списком или кортежем элементов, где каждый элемент должен быть одного из следующих типов:имя поля, где указанное поле должно быть либо
BooleanField
,CharField
,DateField
,DateTimeField
,IntegerField
,ForeignKey
илиManyToManyField
, например:class PersonAdmin(admin.ModelAdmin): list_filter = ('is_staff', 'company')
Имена полей в
list_filter
также могут охватывать отношения с помощью поиска__
, например:class PersonAdmin(admin.UserAdmin): list_filter = ('company__name',)
класс, наследующий от
django.contrib.admin.SimpleListFilter
, которому нужно предоставить атрибутыtitle
иparameter_name
и переопределить методыlookups
иqueryset
, например: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'))
кортеж, где первый элемент - имя поля, а второй - класс, наследующийся от
django.contrib.admin.FieldListFilter
, например:class PersonAdmin(admin.ModelAdmin): list_filter = ( ('is_staff', admin.BooleanFieldListFilter), )
Вы можете ограничить выбор связанной модели объектами, участвующими в этой связи, используя
RelatedOnlyFieldListFilter
:class BookAdmin(admin.ModelAdmin): list_filter = ( ('author', admin.RelatedOnlyFieldListFilter), )
Если предположить, что
author
являетсяForeignKey
кUser
модели, это ограничитlist_filter
выбор пользователями, которые написали книгу, вместо того, чтобы перечислять всех пользователей.Вы можете фильтровать пустые значения с помощью
EmptyFieldListFilter
, который может фильтровать как пустые строки, так и нули, в зависимости от того, что поле позволяет хранить:class BookAdmin(admin.ModelAdmin): list_filter = ( ('title', admin.EmptyFieldListFilter), )
Примечание
API
FieldListFilter
считается внутренним и может быть изменен.Примечание
Поле
GenericForeignKey
не поддерживается.New in Django 3.1:Был добавлен класс
EmptyFieldListFilter
.
Фильтр списка обычно появляется только в том случае, если фильтр имеет более одного выбора. Метод
has_output()
фильтра управляет тем, появляется он или нет.Можно задать собственный шаблон для отображения фильтра списка:
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
и вызыватьselect_related()
, если присутствуетForeignKey
.Если вам нужен более тонкий контроль, используйте кортеж (или список) в качестве значения для
list_select_related
. Пустой кортеж не позволит Django вызватьselect_related
вообще. Любой другой кортеж будет передан непосредственно вselect_related
в качестве параметров. Например:class ArticleAdmin(admin.ModelAdmin): list_select_related = ('author', 'category')
вызовет
select_related('author', 'category')
.Если вам нужно указать динамическое значение, основанное на запросе, вы можете реализовать метод
get_list_select_related()
.Примечание
ModelAdmin
игнорирует этот атрибут, еслиselect_related()
уже был вызван наQuerySet
списка изменений.
-
ModelAdmin.
ordering
¶ Задайте
ordering
, чтобы указать, как должны быть упорядочены списки объектов в представлениях администратора Django. Это должен быть список или кортеж в том же формате, что и параметр моделиordering
.Если это не указано, администратор Django будет использовать упорядочивание модели по умолчанию.
Если вам необходимо задать динамический порядок (например, в зависимости от пользователя или языка), вы можете реализовать метод
get_ordering()
.Соображения производительности при упорядочивании и сортировке
Чтобы обеспечить детерминированное упорядочивание результатов, список изменений добавляет
pk
к упорядочиванию, если не может найти единственный или уникальный набор полей, обеспечивающий общее упорядочивание.Например, если по умолчанию используется упорядочивание по неуникальному полю
name
, то список изменений сортируется поname
иpk
. Это может плохо работать, если у вас много строк и нет индекса дляname
иpk
.
-
ModelAdmin.
paginator
¶ Класс пагинатора, который будет использоваться для пагинации. По умолчанию используется
django.core.paginator.Paginator
. Если пользовательский класс пагинатора не имеет такого же интерфейса конструктора, какdjango.core.paginator.Paginator
, вам также необходимо предоставить реализацию дляModelAdmin.get_paginator()
.
-
ModelAdmin.
prepopulated_fields
¶ Установите
prepopulated_fields
в словарь, отображающий имена полей на поля, которые он должен предварительно заполнить:class ArticleAdmin(admin.ModelAdmin): prepopulated_fields = {"slug": ("title",)}
Если установлено, то данные поля будут использовать JavaScript для заполнения из назначенных полей. Основное использование этой функциональности - автоматическая генерация значения для полей
SlugField
из одного или нескольких других полей. Генерируемое значение получается путем конкатенации значений исходных полей, а затем путем преобразования этого результата в правильный slug (например, замена тире на пробелы; строчные буквы ASCII; удаление различных английских стоп-слов, таких как „a“, „an“, „as“ и подобных).Предварительно заполненные поля не изменяются JavaScript после сохранения значения. Обычно нежелательно, чтобы slug изменялись (что привело бы к изменению URL объекта, если в нем используется slug).
prepopulated_fields
не принимает поляDateTimeField
,ForeignKey
,OneToOneField
иManyToManyField
.
-
ModelAdmin.
preserve_filters
¶ По умолчанию примененные фильтры сохраняются в представлении списка после создания, редактирования или удаления объекта. Вы можете очистить фильтры, установив этот атрибут в значение
False
.
-
ModelAdmin.
radio_fields
¶ По умолчанию админка Django использует интерфейс select-box (<select>) для полей, которые имеют значение
ForeignKey
или установленыchoices
. Если поле присутствует вradio_fields
, Django будет использовать вместо него интерфейс радио-кнопки. Предполагая, чтоgroup
являетсяForeignKey
на моделиPerson
:class PersonAdmin(admin.ModelAdmin): radio_fields = {"group": admin.VERTICAL}
У вас есть выбор: использовать
HORIZONTAL
илиVERTICAL
из модуляdjango.contrib.admin
.Не включайте поле в
radio_fields
, если оно не являетсяForeignKey
или не установленоchoices
.
-
ModelAdmin.
autocomplete_fields
¶ autocomplete_fields
- это списокForeignKey
и/илиManyToManyField
полей, которые вы хотите изменить на Select2 автозаполняемые входы.По умолчанию администратор использует для этих полей интерфейс выборочного поля (
<select>
). Иногда вы не хотите тратить время на выбор всех связанных экземпляров для отображения в выпадающем списке.Вход Select2 похож на вход по умолчанию, но имеет функцию поиска, которая загружает варианты асинхронно. Это быстрее и удобнее для пользователя, если связанная модель имеет много экземпляров.
Вы должны определить
search_fields
наModelAdmin
связанного объекта, потому что автозаполняющий поиск использует его.Чтобы избежать несанкционированного раскрытия данных, пользователи должны иметь разрешение
view
илиchange
на связанный объект, чтобы использовать автозаполнение.Упорядочивание и пагинация результатов контролируются связанными методами
ModelAdmin
“get_ordering()
иget_paginator()
.В следующем примере
ChoiceAdmin
имеет поле автозаполнения отForeignKey
доQuestion
. Результаты фильтруются по полюquestion_text
и упорядочиваются по полюdate_created
:class QuestionAdmin(admin.ModelAdmin): ordering = ['date_created'] search_fields = ['question_text'] class ChoiceAdmin(admin.ModelAdmin): autocomplete_fields = ['question']
Соображения по производительности для больших наборов данных
Упорядочивание с использованием
ModelAdmin.ordering
может вызвать проблемы с производительностью, так как сортировка на большом наборе запросов будет медленной.Кроме того, если ваши поля поиска включают поля, которые не индексируются базой данных, вы можете столкнуться с низкой производительностью на очень больших таблицах.
Для таких случаев хорошей идеей будет написать собственную реализацию
ModelAdmin.get_search_results()
с использованием полнотекстового индексированного поиска.Вы также можете захотеть изменить
Paginator
на очень больших таблицах, поскольку пагинатор по умолчанию всегда выполняет запросcount()
. Например, вы можете переопределить реализацию свойстваPaginator.count
по умолчанию.
-
ModelAdmin.
raw_id_fields
¶ По умолчанию в админке Django используется интерфейс выбора (<select>) для полей, которые имеют значение
ForeignKey
. Иногда вы не хотите тратить время на выбор всех связанных экземпляров для отображения в выпадающем списке.raw_id_fields
- это список полей, которые вы хотите изменить в виджетеInput
дляForeignKey
илиManyToManyField
:class ArticleAdmin(admin.ModelAdmin): raw_id_fields = ("newspaper",)
Виджет
raw_id_fields
Input
должен содержать первичный ключ, если поле являетсяForeignKey
, или список значений, разделенных запятыми, если поле являетсяManyToManyField
. Виджетraw_id_fields
показывает кнопку увеличительного стекла рядом с полем, которая позволяет пользователям искать и выбирать значение:
-
ModelAdmin.
readonly_fields
¶ По умолчанию администратор показывает все поля как редактируемые. Любые поля в этом параметре (которые должны быть
list
илиtuple
) будут отображать свои данные как есть и не редактируемые; они также исключаются изModelForm
, используемых для создания и редактирования. Обратите внимание, что при указанииModelAdmin.fields
илиModelAdmin.fieldsets
поля только для чтения должны присутствовать, чтобы отображаться (в противном случае они игнорируются).Если
readonly_fields
используется без определения явного порядка черезModelAdmin.fields
илиModelAdmin.fieldsets
, то они будут добавлены последними после всех редактируемых полей.Поле только для чтения может не только отображать данные из поля модели, но и выводить результат метода модели или метода самого класса
ModelAdmin
. Это очень похоже на то, как ведет себяModelAdmin.list_display
. Это дает возможность использовать интерфейс администратора для предоставления обратной связи о состоянии редактируемых объектов, например:from django.contrib import admin from django.utils.html import format_html_join from django.utils.safestring import mark_safe class PersonAdmin(admin.ModelAdmin): readonly_fields = ('address_report',) 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
, «Сохранить и добавить другой» будет заменено кнопкой «Сохранить как новый», которая создает новый объект (с новым ID), а не обновляет существующий объект.По умолчанию
save_as
устанавливается вFalse
.
-
ModelAdmin.
save_as_continue
¶ При значении
save_as=True
перенаправление по умолчанию после сохранения нового объекта происходит на представление изменений для этого объекта. Если задатьsave_as_continue=False
, то перенаправление будет осуществляться на представление списка изменений.По умолчанию
save_as_continue
устанавливается вTrue
.
-
ModelAdmin.
save_on_top
¶ Установите
save_on_top
, чтобы добавить кнопки сохранения в верхней части форм изменения администратора.Обычно кнопки сохранения появляются только в нижней части форм. Если установить значение
save_on_top
, кнопки будут отображаться и сверху, и снизу.По умолчанию
save_on_top
устанавливается вFalse
.
-
ModelAdmin.
search_fields
¶ Установите
search_fields
, чтобы включить поле поиска на странице списка изменений администратора. Оно должно быть установлено на список имен полей, которые будут искаться всякий раз, когда кто-то вводит поисковый запрос в это текстовое поле.Эти поля должны быть какими-либо текстовыми полями, например
CharField
илиTextField
. Вы также можете выполнить связанный поиск поForeignKey
илиManyToManyField
с помощью нотации «follow» API поиска:search_fields = ['foreign_key__related_fieldname']
Например, если у вас есть запись в блоге с автором, следующее определение позволит искать записи в блоге по адресу электронной почты автора:
search_fields = ['user__email']
Когда кто-то выполняет поиск в окне поиска администратора, Django разбивает поисковый запрос на слова и возвращает все объекты, которые содержат каждое из слов, без учета регистра (используя поиск
icontains
), где каждое слово должно быть хотя бы в одном изsearch_fields
. Например, еслиsearch_fields
задано['first_name', 'last_name']
и пользователь ищетjohn lennon
, Django выполнит эквивалент этого предложения SQLWHERE
: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']
.Обратите внимание, что поскольку термины запроса разделяются и AND, как описано ранее, поиск с помощью
exact
работает только с одним поисковым словом, поскольку два или более слов не могут быть точным совпадением, если только все слова не одинаковые.Также доступны некоторые (старые) сочетания клавиш для указания поиска поля. Вы можете задать префикс поля в
search_fields
с помощью следующих символов, и это будет эквивалентно добавлению__<lookup>
к полю:Префикс Поиск ^ startswith
= iexact
@ search
Нет icontains
Если вам нужно настроить поиск, вы можете использовать
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
¶ По умолчанию страница списка изменений позволяет сортировать по всем полям модели (и callables, которые имеют свойство
admin_order_field
), указанным вlist_display
.Если вы хотите отключить сортировку для некоторых столбцов, установите
sortable_by
в коллекцию (например,list
,tuple
, илиset
) подмножестваlist_display
, которые вы хотите, чтобы были сортируемыми. Пустая коллекция отключает сортировку для всех столбцов.Если вам нужно задать этот список динамически, реализуйте вместо него метод
get_sortable_by()
.
-
ModelAdmin.
view_on_site
¶ Установите
view_on_site
, чтобы контролировать, отображать или нет ссылку «Посмотреть на сайте». Эта ссылка должна привести вас на URL, где вы можете отобразить сохраненный объект.Это значение может быть либо булевым флагом, либо вызываемым объектом. Если
True
(по умолчанию), то для генерации url будет использоваться метод объектаget_absolute_url()
.Если ваша модель имеет метод
get_absolute_url()
, но вы не хотите, чтобы появлялась кнопка «Просмотр на сайте», вам достаточно установитьview_on_site
вFalse
:from django.contrib import admin class PersonAdmin(admin.ModelAdmin): view_on_site = False
Если это вызываемый объект, то он принимает экземпляр модели в качестве параметра. Например:
from django.contrib import admin from django.urls import reverse class PersonAdmin(admin.ModelAdmin): def view_on_site(self, obj): url = reverse('person-detail', kwargs={'slug': obj.slug}) return 'https://example.com' + url
Пользовательские параметры шаблона¶
В разделе Переопределение шаблонов администратора описано, как переопределить или расширить шаблоны администратора по умолчанию. Используйте следующие параметры для переопределения шаблонов по умолчанию, используемых представлениями ModelAdmin
:
-
ModelAdmin.
add_form_template
¶ Путь к пользовательскому шаблону, используемому
add_view()
.
-
ModelAdmin.
change_form_template
¶ Путь к пользовательскому шаблону, используемому
change_view()
.
-
ModelAdmin.
change_list_template
¶ Путь к пользовательскому шаблону, используемому
changelist_view()
.
-
ModelAdmin.
delete_confirmation_template
¶ Путь к пользовательскому шаблону, используемому
delete_view()
для отображения страницы подтверждения при удалении одного или нескольких объектов.
-
ModelAdmin.
delete_selected_confirmation_template
¶ Путь к пользовательскому шаблону, используемому методом действия
delete_selected
для отображения страницы подтверждения при удалении одного или нескольких объектов. См. actions documentation.
-
ModelAdmin.
object_history_template
¶ Путь к пользовательскому шаблону, используемому
history_view()
.
-
ModelAdmin.
popup_response_template
¶ Путь к пользовательскому шаблону, используемому
response_add()
,response_change()
иresponse_delete()
.
ModelAdmin
методы¶
Предупреждение
При переопределении ModelAdmin.save_model()
и ModelAdmin.delete_model()
ваш код должен сохранить/удалить объект. Они не предназначены для целей вето, скорее они позволяют вам выполнять дополнительные операции.
-
ModelAdmin.
save_model
(request, obj, form, change)[исходный код]¶ Методу
save_model
передаетсяHttpRequest
, экземпляр модели, экземплярModelForm
и булево значение, основанное на том, добавляет или изменяет он объект. Переопределение этого метода позволяет выполнять операции до или после сохранения. Вызовитеsuper().save_model()
, чтобы сохранить объект с помощьюModel.save()
.Например, чтобы прикрепить
request.user
к объекту перед сохранением:from django.contrib import admin class ArticleAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): obj.user = request.user super().save_model(request, obj, form, change)
-
ModelAdmin.
delete_model
(request, obj)[исходный код]¶ Методу
delete_model
передаетсяHttpRequest
и экземпляр модели. Переопределение этого метода позволяет выполнять операции до или после удаления. Вызовитеsuper().delete_model()
для удаления объекта с помощьюModel.delete()
.
-
ModelAdmin.
delete_queryset
(request, queryset)[исходный код]¶ Методу
delete_queryset()
передаетсяHttpRequest
иQuerySet
объектов для удаления. Переопределите этот метод, чтобы настроить процесс удаления для «удаления выбранных объектов» action.
-
ModelAdmin.
save_formset
(request, form, formset, change)[исходный код]¶ Методу
save_formset
передаетсяHttpRequest
, родительский экземплярModelForm
и булево значение, основанное на том, добавляет ли он или изменяет родительский объект.Например, чтобы прикрепить
request.user
к каждому измененному экземпляру модели набора форм:class ArticleAdmin(admin.ModelAdmin): def save_formset(self, request, form, formset, change): instances = formset.save(commit=False) for obj in formset.deleted_objects: obj.delete() for instance in instances: instance.user = request.user instance.save() formset.save_m2m()
См. также Сохранение объектов в наборе форм.
-
ModelAdmin.
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, который применяет текущие фильтры, и заданный пользователем поисковый запрос. Он возвращает кортеж, содержащий кверисет, модифицированный для реализации поиска, и булево значение, указывающее, могут ли результаты содержать дубликаты.Реализация по умолчанию выполняет поиск по полям, названным в
ModelAdmin.search_fields
.Этот метод может быть переопределен вашим собственным методом поиска. Например, вы можете искать по целочисленному полю или использовать внешний инструмент, такой как Solr или Haystack. Вы должны установить, могут ли изменения queryset, осуществляемые вашим методом поиска, внести дубликаты в результаты, и вернуть
True
во втором элементе возвращаемого значения.Например, для поиска по
name
иage
можно использовать: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
, список наборов инлайн-форм и булево значение, основанное на том, добавляется или изменяется родитель. Здесь вы можете выполнять любые операции до или после сохранения для объектов, связанных с родителем. Обратите внимание, что в этот момент родительский объект и его форма уже сохранены.
-
ModelAdmin.
get_autocomplete_fields
(request)¶ Методу
get_autocomplete_fields()
задаетсяHttpRequest
и ожидается, что он вернетlist
илиtuple
имен полей, которые будут отображаться с помощью виджета автозаполнения, как описано выше в разделеModelAdmin.autocomplete_fields
.
-
ModelAdmin.
get_readonly_fields
(request, obj=None)¶ Методу
get_readonly_fields
даетсяHttpRequest
и редактируемоеobj
(илиNone
на форме добавления) и ожидается, что он вернетlist
илиtuple
имен полей, которые будут отображаться только для чтения, как описано выше в разделеModelAdmin.readonly_fields
.
-
ModelAdmin.
get_prepopulated_fields
(request, obj=None)¶ Методу
get_prepopulated_fields
передаетсяHttpRequest
и редактируемоеobj
(илиNone
на форме добавления) и ожидается, что он вернетdictionary
, как описано выше в разделеModelAdmin.prepopulated_fields
.
-
ModelAdmin.
get_list_display
(request)[исходный код]¶ Методу
get_list_display
задаетсяHttpRequest
и ожидается, что он вернет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_exclude
даетсяHttpRequest
и редактируемаяobj
(илиNone
на форме добавления) и ожидается, что он вернет список полей, как описано вModelAdmin.exclude
.
-
ModelAdmin.
get_fields
(request, obj=None)¶ Методу
get_fields
передаетсяHttpRequest
и редактируемаяobj
(илиNone
на форме добавления) и ожидается, что он вернет список полей, как описано выше в разделеModelAdmin.fields
.
-
ModelAdmin.
get_fieldsets
(request, obj=None)¶ Метод
get_fieldsets
получаетHttpRequest
и редактируемуюobj
(илиNone
на форме добавления) и должен вернуть список из двух кортежей, в котором каждый кортеж представляет<fieldset>
на странице формы администратора, как описано выше в разделеModelAdmin.fieldsets
.
-
ModelAdmin.
get_list_filter
(request)[исходный код]¶ Методу
get_list_filter
присваиваетсяHttpRequest
и ожидается, что он вернет тот же тип последовательности, что и для атрибутаlist_filter
.
Метод
get_list_select_related
передается методуHttpRequest
и должен возвращать булево значение или список, как это делаетModelAdmin.list_select_related
.
-
ModelAdmin.
get_search_fields
(request)[исходный код]¶ Методу
get_search_fields
присваиваетсяHttpRequest
и ожидается, что он вернет тот же тип последовательности, что и для атрибутаsearch_fields
.
-
ModelAdmin.
get_sortable_by
(request)¶ Методу
get_sortable_by()
передаетсяHttpRequest
и ожидается, что он вернет коллекцию (например,list
,tuple
илиset
) имен полей, которые можно будет сортировать на странице списка изменений.Его реализация по умолчанию возвращает
sortable_by
, если он установлен, в противном случае он переходит кget_list_display()
.Например, чтобы запретить сортировку одного или нескольких столбцов:
class PersonAdmin(admin.ModelAdmin): def get_sortable_by(self, request): return {*self.get_list_display(request)} - {'rank'}
-
ModelAdmin.
get_inline_instances
(request, obj=None)[исходный код]¶ Методу
get_inline_instances
даетсяHttpRequest
и редактируемыйobj
(илиNone
на форме добавления) и ожидается, что он вернетlist
илиtuple
изInlineModelAdmin
объектов, как описано ниже в разделеInlineModelAdmin
. Например, следующее возвращает строки без фильтрации по умолчанию на основе разрешений на добавление, изменение, удаление и просмотр:class MyModelAdmin(admin.ModelAdmin): inlines = (MyInline,) def get_inline_instances(self, request, obj=None): return [inline(self.model, self.admin_site) for inline in self.inlines]
Если вы переопределите этот метод, убедитесь, что возвращаемые инлайны являются экземплярами классов, определенных в
inlines
, иначе вы можете столкнуться с ошибкой «Bad Request» при добавлении связанных объектов.
-
ModelAdmin.
get_inlines
(request, obj)¶ - New in Django 3.0.
Методу
get_inlines
передаетсяHttpRequest
и редактируемыйobj
(илиNone
на форме добавления), и ожидается, что он вернет итерабельную последовательность инлайнов. Вы можете переопределить этот метод для динамического добавления строк на основе запроса или экземпляра модели вместо того, чтобы указывать их вModelAdmin.inlines
.
-
ModelAdmin.
get_urls
()[исходный код]¶ Метод
get_urls
наModelAdmin
возвращает URL, которые будут использоваться для данного ModelAdmin, таким же образом, как и URLconf. Поэтому вы можете расширить их, как описано в Диспетчер 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-адреса к встроенным.
В этом примере доступ к
my_view
будет осуществляться по адресу/admin/myapp/mymodel/my_view/
(при условии, что URL-адреса администраторов включены в/admin/
).Однако функция
self.my_view
, зарегистрированная выше, страдает от двух проблем:- Он не будет выполнять никаких проверок разрешений, поэтому он будет доступен для широкой публики.
- Он не предоставляет никаких сведений о заголовках для предотвращения кэширования. Это означает, что если страница получает данные из базы данных, а промежуточное ПО кэширования активно, страница может показать устаревшую информацию.
Поскольку это обычно не то, что вам нужно, Django предоставляет удобную обертку для проверки разрешений и пометки представления как некэшируемого. Эта обертка
AdminSite.admin_view()
(т.е.self.admin_site.admin_view
внутри экземпляраModelAdmin
); используйте ее так: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
Обратите внимание на обернутый вид в пятой строке сверху:
path('my_view/', self.admin_site.admin_view(self.my_view))
Эта обертка защитит
self.my_view
от несанкционированного доступа и применит декораторdjango.views.decorators.cache.never_cache()
, чтобы убедиться, что он не кэшируется, если активна промежуточная программа кэширования.Если страница кэшируема, но вы все равно хотите, чтобы проверка разрешения была выполнена, вы можете передать аргумент
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)[исходный код]¶ Создает пары (
FormSet
,InlineModelAdmin
) для использования в представлениях добавления и изменения администратора.Например, если вы хотите отображать определенную строку только в представлении изменений, вы можете переопределить
get_formsets_with_inlines
следующим образом:class MyModelAdmin(admin.ModelAdmin): inlines = [MyInline, SomeOtherInline] def get_formsets_with_inlines(self, request, obj=None): for inline in self.get_inline_instances(request, obj): # hide MyInline in the add view if not isinstance(inline, MyInline) or obj is not None: yield inline.get_formset(request, obj), inline
-
ModelAdmin.
formfield_for_foreignkey
(db_field, request, **kwargs)¶ Метод
formfield_for_foreignkey
наModelAdmin
позволяет переопределить поле формы по умолчанию для поля внешнего ключа. Например, чтобы вернуть подмножество объектов для этого поля внешнего ключа на основе данных пользователя:class MyModelAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == "car": kwargs["queryset"] = Car.objects.filter(owner=request.user) return super().formfield_for_foreignkey(db_field, request, **kwargs)
Здесь используется экземпляр
HttpRequest
для фильтрации поля внешнего ключаCar
, чтобы отобразить только автомобили, принадлежащие экземпляруUser
.Для более сложных фильтров вы можете использовать метод
ModelForm.__init__()
для фильтрации на основеinstance
вашей модели (см. Поля, которые обрабатывают отношения). Например:class CountryAdminForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['capital'].queryset = self.instance.cities.all() class CountryAdmin(admin.ModelAdmin): form = CountryAdminForm
-
ModelAdmin.
formfield_for_manytomany
(db_field, request, **kwargs)¶ Как и метод
formfield_for_foreignkey
, методformfield_for_manytomany
может быть переопределен для изменения поля формы по умолчанию для поля «многие ко многим». Например, если владелец может владеть несколькими автомобилями, а автомобили могут принадлежать нескольким владельцам - отношение «многие ко многим» - вы можете отфильтровать поле внешнего ключаCar
, чтобы отобразить только автомобили, принадлежащие владельцуUser
:class MyModelAdmin(admin.ModelAdmin): def formfield_for_manytomany(self, db_field, request, **kwargs): if db_field.name == "cars": kwargs["queryset"] = Car.objects.filter(owner=request.user) return super().formfield_for_manytomany(db_field, request, **kwargs)
-
ModelAdmin.
formfield_for_choice_field
(db_field, request, **kwargs)¶ Как и методы
formfield_for_foreignkey
иformfield_for_manytomany
, методformfield_for_choice_field
может быть переопределен для изменения поля формы по умолчанию для поля, в котором объявлены варианты выбора. Например, если выбор, доступный суперпользователю, должен отличаться от выбора, доступного обычному персоналу, вы можете поступить следующим образом:class MyModelAdmin(admin.ModelAdmin): def formfield_for_choice_field(self, db_field, request, **kwargs): if db_field.name == "status": kwargs['choices'] = ( ('accepted', 'Accepted'), ('denied', 'Denied'), ) if request.user.is_superuser: kwargs['choices'] += (('ready', 'Ready for deployment'),) return super().formfield_for_choice_field(db_field, request, **kwargs)
Примечание
Любой атрибут
choices
, установленный на поле формы, будет ограничен только полем формы. Если в соответствующем поле модели установлены варианты выбора, то варианты выбора, предоставляемые форме, должны быть допустимым подмножеством этих вариантов, иначе отправка формы завершится ошибкойValidationError
при проверке самой модели перед сохранением.
-
ModelAdmin.
get_changelist
(request, **kwargs)[исходный код]¶ Возвращает класс
Changelist
, который будет использоваться для листинга. По умолчанию используетсяdjango.contrib.admin.views.main.ChangeList
. Наследуя этот класс, вы можете изменить поведение листинга.
-
ModelAdmin.
get_changelist_form
(request, **kwargs)[исходный код]¶ Возвращает класс
ModelForm
для использования вFormset
на странице списка изменений. Чтобы использовать пользовательскую форму, например:from django import forms class MyForm(forms.ModelForm): pass class MyModelAdmin(admin.ModelAdmin): def get_changelist_form(self, request, **kwargs): return MyForm
Примечание
Если вы определяете атрибут
Meta.model
наModelForm
, вы также должны определить атрибутMeta.fields
(или атрибутMeta.exclude
). ОднакоModelAdmin
игнорирует это значение, переопределяя его атрибутомModelAdmin.list_editable
. Самое простое решение - опустить атрибутMeta.model
, посколькуModelAdmin
предоставит правильную модель для использования.
-
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
). Поскольку поиск в строке запроса может быть манипулирован пользователем, он должен быть санирован для предотвращения несанкционированного раскрытия данных.Методу
lookup_allowed()
передается путь поиска из строки запроса (например,'user__email'
) и соответствующее значение (например,'user@example.com'
), и возвращается булево число, указывающее, разрешена ли фильтрацияQuerySet
списка изменений с использованием параметров. Еслиlookup_allowed()
возвращаетFalse
, то вызываетсяDisallowedModelAdminLookup
(подклассSuspiciousOperation
).По умолчанию
lookup_allowed()
разрешает доступ к локальным полям модели, путям к полям, используемым вlist_filter
(но не к путям изget_list_filter()
), и поискам, необходимым для того, чтобыlimit_choices_to
правильно функционировал вraw_id_fields
.Переопределите этот метод, чтобы настроить поиск, разрешенный для вашего подкласса
ModelAdmin
.
-
ModelAdmin.
has_view_permission
(request, obj=None)¶ Должно возвращать
True
, если просмотрobj
разрешен,False
в противном случае. Если obj равенNone
, должно возвращатьсяTrue
илиFalse
, чтобы указать, разрешен ли просмотр объектов этого типа вообще (например,False
будет интерпретировано как означающее, что текущему пользователю не разрешено просматривать ни один объект этого типа).Реализация по умолчанию возвращает
True
, если пользователь имеет разрешение «изменить» или «просмотреть».
-
ModelAdmin.
has_add_permission
(request)¶ Должен возвращать
True
, если добавление объекта разрешено,False
в противном случае.
-
ModelAdmin.
has_change_permission
(request, obj=None)¶ Должно возвращать
True
, если редактированиеobj
разрешено,False
в противном случае. Еслиobj
равноNone
, должно возвращатьTrue
илиFalse
, чтобы указать, разрешено ли редактирование объектов данного типа вообще (например,False
будет интерпретировано как означающее, что текущему пользователю не разрешено редактировать ни один объект данного типа).
-
ModelAdmin.
has_delete_permission
(request, obj=None)¶ Должно возвращать
True
, если удалениеobj
разрешено,False
в противном случае. Еслиobj
равноNone
, должно возвращатьTrue
илиFalse
, чтобы указать, разрешено ли удаление объектов данного типа вообще (например,False
будет интерпретировано как означающее, что текущему пользователю запрещено удалять любой объект данного типа).
-
ModelAdmin.
has_module_permission
(request)¶ Должен возвращать
True
, если отображение модуля на индексной странице администратора и доступ к индексной странице модуля разрешены,False
в противном случае. По умолчанию используетсяUser.has_module_perms()
. Его переопределение не ограничивает доступ к просмотру, добавлению, изменению или удалению представлений, для этого следует использоватьhas_view_permission()
,has_add_permission()
,has_change_permission()
иhas_delete_permission()
.
-
ModelAdmin.
get_queryset
(request)¶ Метод
get_queryset
наModelAdmin
возвращаетQuerySet
всех экземпляров модели, которые могут быть отредактированы администратором сайта. Одним из вариантов использования переопределения этого метода является показ объектов, принадлежащих вошедшему пользователю:class MyModelAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super().get_queryset(request) if request.user.is_superuser: return qs return qs.filter(author=request.user)
-
ModelAdmin.
message_user
(request, message, level=messages.INFO, extra_tags='', fail_silently=False)[исходный код]¶ Отправляет сообщение пользователю, используя бэкенд
django.contrib.messages
. См. custom ModelAdmin example.Аргументы с ключевыми словами позволяют изменить уровень сообщения, добавить дополнительные 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
.Этот метод должен возвращать 4-кортеж
(deleted_objects, model_count, perms_needed, protected)
.deleted_objects
- это список строк, представляющих все объекты, которые будут удалены. Если есть связанные объекты, подлежащие удалению, список является вложенным и включает эти связанные объекты. Список форматируется в шаблоне с помощью фильтраunordered_list
.model_count
- это словарь, отображающийverbose_name_plural
каждой модели на количество объектов, которые будут удалены.perms_needed
- это наборverbose_name
моделей, которые пользователь не имеет права удалять.protected
- это список строк, представляющих все защищенные связанные объекты, которые не могут быть удалены. Список отображается в шаблоне.
Другие методы¶
-
ModelAdmin.
add_view
(request, form_url='', extra_context=None)[исходный код]¶ 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 представление для страницы, которая показывает историю модификаций для данного экземпляра модели.
В отличие от методов типа hook ModelAdmin
, подробно описанных в предыдущем разделе, эти пять методов на самом деле предназначены для вызова в виде представлений Django из обработчика URL-диспетчеризации приложения администратора для отображения страниц, которые работают с CRUD-операциями над экземплярами моделей. В результате, полное переопределение этих методов значительно изменит поведение приложения администратора.
Одна из распространенных причин переопределения этих методов заключается в дополнении контекстных данных, которые предоставляются шаблону, отображающему представление. В следующем примере представление изменения переопределяется таким образом, что шаблону рендеринга предоставляются некоторые дополнительные данные отображения, которые иначе не были бы доступны:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
# ...
pass
def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['osm_data'] = self.get_osm_info()
return super().change_view(
request, object_id, form_url, extra_context=extra_context,
)
Эти представления возвращают экземпляры TemplateResponse
, которые позволяют легко настраивать данные ответа перед рендерингом. Для более подробной информации смотрите TemplateResponse documentation.
ModelAdmin
определения активов¶
Бывают случаи, когда вы хотите добавить немного CSS и/или JavaScript в представления добавления/изменения. Этого можно добиться, используя внутренний класс Media
на вашем ModelAdmin
:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
staticfiles app добавляет STATIC_URL
(или MEDIA_URL
, если STATIC_URL
равно None
) к любым путям активов. Применяются те же правила, что и для regular asset definitions on forms.
jQuery¶
JavaScript администратора Django использует библиотеку jQuery.
Чтобы избежать конфликтов с пользовательскими скриптами или библиотеками, jQuery в Django (версия 3.5.1) размещается в пространстве имен как django.jQuery
. Если вы хотите использовать jQuery в своем собственном админском JavaScript без включения второй копии, вы можете использовать объект django.jQuery
в списке изменений и представлениях добавления/редактирования. Кроме того, ваши собственные административные формы или виджеты, зависящие от django.jQuery
, должны указывать js=['admin/js/jquery.init.js', …]
, когда declaring form media assets.
jQuery был обновлен с версии 3.3.1 до 3.4.1.
jQuery был обновлен с версии 3.4.1 до 3.5.1.
Класс ModelAdmin
требует jQuery по умолчанию, поэтому нет необходимости добавлять jQuery в список медиаресурсов вашего ModelAdmin
, если у вас нет особой необходимости. Например, если вам требуется, чтобы библиотека jQuery находилась в глобальном пространстве имен (например, при использовании сторонних плагинов jQuery) или если вам нужна более новая версия jQuery, вам придется включить свою собственную копию.
Django предоставляет несжатую и «минифицированную» версии jQuery, как jquery.js
и jquery.min.js
соответственно.
ModelAdmin
и InlineModelAdmin
имеют свойство media
, которое возвращает список Media
объектов, хранящих пути к JavaScript файлам для форм и/или наборов форм. Если DEBUG
является True
, то возвращаются несжатые версии различных JavaScript файлов, включая jquery.js
; если нет, то возвращаются «минифицированные» версии.
Добавление пользовательской валидации в админку¶
Вы также можете добавить пользовательскую валидацию данных в админке. Автоматический интерфейс администратора повторно использует django.forms
, а класс ModelAdmin
дает вам возможность определить свою собственную форму:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
MyArticleAdminForm
может быть определено в любом месте, если вы импортируете там, где это необходимо. Теперь внутри вашей формы вы можете добавить свою собственную пользовательскую валидацию для любого поля:
class MyArticleAdminForm(forms.ModelForm):
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]
Здесь важно использовать ModelForm
, иначе все может сломаться. См. документацию forms по custom validation и, более конкретно, model form validation notes для получения дополнительной информации.
InlineModelAdmin
объекты¶
-
class
InlineModelAdmin
¶
-
class
TabularInline
[исходный код]¶
-
class
StackedInline
[исходный код]¶ В интерфейсе администратора есть возможность редактировать модели на той же странице, что и родительская модель. Такие модели называются вставками. Предположим, у вас есть две модели:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) title = models.CharField(max_length=100)
Вы можете редактировать книги, автором которых является автор, на странице автора. Вы добавляете вставки в модель, указывая их в строке
ModelAdmin.inlines
:from django.contrib import admin class BookInline(admin.TabularInline): model = Book class AuthorAdmin(admin.ModelAdmin): inlines = [ BookInline, ]
Django предоставляет два подкласса
InlineModelAdmin
и это:Разница между ними заключается лишь в шаблоне, используемом для их визуализации.
InlineModelAdmin
опции¶
InlineModelAdmin
имеет много общих функций с ModelAdmin
и добавляет некоторые собственные (общие функции определены в суперклассе BaseModelAdmin
). К общим функциям относятся:
form
fieldsets
fields
formfield_overrides
exclude
filter_horizontal
filter_vertical
ordering
prepopulated_fields
get_fieldsets()
get_queryset()
radio_fields
readonly_fields
raw_id_fields
formfield_for_choice_field()
formfield_for_foreignkey()
formfield_for_manytomany()
has_module_permission()
Класс InlineModelAdmin
добавляет или настраивает:
-
InlineModelAdmin.
model
¶ Модель, которую использует инлайн. Требуется.
-
InlineModelAdmin.
fk_name
¶ Имя внешнего ключа модели. В большинстве случаев это будет сделано автоматически, но
fk_name
должно быть указано явно, если существует более одного внешнего ключа к одной и той же родительской модели.
-
InlineModelAdmin.
formset
¶ По умолчанию это значение равно
BaseInlineFormSet
. Использование собственного набора форм может дать вам много возможностей для настройки. Строки строятся вокруг model formsets.
-
InlineModelAdmin.
form
¶ Значение для
form
по умолчанию равноModelForm
. Именно это значение передается вinlineformset_factory()
при создании набора форм для данного инлайна.
Предупреждение
При написании пользовательской валидации для форм InlineModelAdmin
будьте осторожны с написанием валидации, которая полагается на особенности родительской модели. Если родительская модель не пройдет валидацию, она может оказаться в противоречивом состоянии, как описано в предупреждении в Валидация на ModelForm.
-
InlineModelAdmin.
classes
¶ Список или кортеж, содержащий дополнительные классы CSS для применения к набору полей, отображаемому для инлайнов. По умолчанию имеет значение
None
. Как и в случае с классами, настроенными вfieldsets
, инлайны с классомcollapse
будут изначально свернуты, а их заголовок будет содержать небольшую ссылку «показать».
-
InlineModelAdmin.
extra
¶ Этот параметр определяет количество дополнительных форм, которые набор форм будет отображать в дополнение к начальным формам. По умолчанию установлено значение 3. Дополнительную информацию см. в formsets documentation.
Для пользователей браузеров с поддержкой JavaScript предусмотрена ссылка «Добавить еще», позволяющая добавить любое количество дополнительных строк в дополнение к тем, которые были получены в результате аргумента
extra
.Динамическая ссылка не появится, если количество отображаемых в данный момент форм превышает
max_num
, или если у пользователя не включен JavaScript.InlineModelAdmin.get_extra()
также позволяет настроить количество дополнительных форм.
-
InlineModelAdmin.
max_num
¶ Управляет максимальным количеством форм, которые будут показаны во вставке. Это не связано напрямую с количеством объектов, но может быть связано, если значение достаточно мало. Смотрите Ограничение количества редактируемых объектов для получения дополнительной информации.
InlineModelAdmin.get_max_num()
также позволяет настроить максимальное количество дополнительных форм.
-
InlineModelAdmin.
min_num
¶ Этот параметр определяет минимальное количество форм, которые будут показаны в строке. Для получения дополнительной информации смотрите
modelformset_factory()
.InlineModelAdmin.get_min_num()
также позволяет настроить минимальное количество отображаемых форм.
-
InlineModelAdmin.
raw_id_fields
¶ По умолчанию в админке Django используется интерфейс выбора (<select>) для полей, которые имеют значение
ForeignKey
. Иногда вы не хотите тратить время на выбор всех связанных экземпляров для отображения в выпадающем списке.raw_id_fields
- это список полей, которые вы хотите изменить в виджетеInput
дляForeignKey
илиManyToManyField
:class BookInline(admin.TabularInline): model = Book raw_id_fields = ("pages",)
-
InlineModelAdmin.
template
¶ Шаблон, используемый для отображения инлайна на странице.
-
InlineModelAdmin.
verbose_name
¶ Переопределение
verbose_name
, находящегося во внутреннем классе моделиMeta
.
-
InlineModelAdmin.
verbose_name_plural
¶ Переопределение
verbose_name_plural
, находящегося во внутреннем классе моделиMeta
.
-
InlineModelAdmin.
can_delete
¶ Определяет, можно ли удалять инлайн-объекты в инлайне. По умолчанию имеет значение
True
.
-
InlineModelAdmin.
show_change_link
¶ Определяет, будет ли у инлайн-объектов, которые можно изменить в админке, ссылка на форму изменения. По умолчанию имеет значение
False
.
-
InlineModelAdmin.
get_formset
(request, obj=None, **kwargs)¶ Возвращает класс
BaseInlineFormSet
для использования в представлениях добавления/изменения администратора.obj
- редактируемый родительский объект илиNone
при добавлении нового родителя. См. пример дляModelAdmin.get_formsets_with_inlines
.
-
InlineModelAdmin.
get_extra
(request, obj=None, **kwargs)¶ Возвращает количество дополнительных встроенных форм для использования. По умолчанию возвращает атрибут
InlineModelAdmin.extra
.Переопределите этот метод, чтобы программно определить количество дополнительных встроенных форм. Например, это может быть основано на экземпляре модели (переданном в качестве аргумента ключевого слова
obj
):class BinaryTreeAdmin(admin.TabularInline): model = BinaryTree def get_extra(self, request, obj=None, **kwargs): extra = 2 if obj: return extra - obj.binarytree_set.count() return extra
-
InlineModelAdmin.
get_max_num
(request, obj=None, **kwargs)¶ Возвращает максимальное количество дополнительных встроенных форм для использования. По умолчанию возвращает атрибут
InlineModelAdmin.max_num
.Переопределите этот метод, чтобы программно определить максимальное количество встроенных форм. Например, это может быть основано на экземпляре модели (переданном в качестве аргумента ключевого слова
obj
):class BinaryTreeAdmin(admin.TabularInline): model = BinaryTree def get_max_num(self, request, obj=None, **kwargs): max_num = 10 if obj and obj.parent: return max_num - 5 return max_num
-
InlineModelAdmin.
get_min_num
(request, obj=None, **kwargs)¶ Возвращает минимальное количество инлайн-форм для использования. По умолчанию возвращает атрибут
InlineModelAdmin.min_num
.Переопределите этот метод, чтобы программно определить минимальное количество встроенных форм. Например, это может быть основано на экземпляре модели (переданном в качестве аргумента ключевого слова
obj
).
-
InlineModelAdmin.
has_add_permission
(request, obj)¶ Должен возвращать
True
, если добавление инлайн-объекта разрешено,False
в противном случае.obj
- редактируемый родительский объект илиNone
при добавлении нового родителя.
-
InlineModelAdmin.
has_change_permission
(request, obj=None)¶ Должен возвращать
True
, если редактирование инлайн-объекта разрешено,False
в противном случае.obj
- это редактируемый родительский объект.
-
InlineModelAdmin.
has_delete_permission
(request, obj=None)¶ Должен возвращать
True
, если удаление инлайн-объекта разрешено,False
в противном случае.obj
- это редактируемый родительский объект.
Примечание
Аргументом obj
, передаваемым методам InlineModelAdmin
, является редактируемый родительский объект или None
при добавлении нового родителя.
Работа с моделью с двумя или более внешними ключами к одной родительской модели¶
Иногда возможно иметь более одного внешнего ключа к одной и той же модели. Возьмем, к примеру, такую модель:
from django.db import models
class Friendship(models.Model):
to_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="friends")
from_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="from_friends")
Если вы хотите отобразить инлайн на страницах добавления/изменения администратора Person
, вам необходимо явно определить внешний ключ, поскольку он не может сделать это автоматически:
from django.contrib import admin
from myapp.models import Friendship
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
Работа с моделями «многие-ко-многим¶
По умолчанию виджеты администратора для отношений «многие-ко-многим» будут отображаться на той модели, которая содержит фактическую ссылку на ManyToManyField
. В зависимости от вашего определения ModelAdmin
, каждое поле «многие-ко-многим» в вашей модели будет представлено стандартным HTML <select multiple>
, горизонтальным или вертикальным фильтром, или виджетом raw_id_admin
. Однако можно также заменить эти виджеты вставками.
Предположим, что у нас есть следующие модели:
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
). Если вы хотите использовать инлайн-модель для представления отношения «многие-ко-многим», вы должны указать администратору Django не отображать этот виджет - в противном случае вы получите два виджета на странице администратора для управления отношением.
Обратите внимание, что при использовании этой техники сигналы m2m_changed
не срабатывают. Это происходит потому, что для администратора through
- это просто модель с двумя полями внешнего ключа, а не отношение «многие ко многим».
Во всех остальных отношениях InlineModelAdmin
точно такой же, как и любой другой. Вы можете настроить внешний вид, используя любое из обычных свойств ModelAdmin
.
Работа с моделями посредников «многие-ко-многим¶
Когда вы указываете промежуточную модель с помощью аргумента through
к аргументу ManyToManyField
, администратор не будет отображать виджет по умолчанию. Это происходит потому, что каждый экземпляр этой промежуточной модели требует больше информации, чем может быть отображено в одном виджете, а компоновка, необходимая для нескольких виджетов, будет отличаться в зависимости от промежуточной модели.
Однако мы все еще хотим иметь возможность редактировать эту информацию в строке. К счастью, мы можем сделать это с помощью встроенных моделей администратора. Предположим, у нас есть следующие модели:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Первым шагом в отображении этой промежуточной модели в админке является определение встроенного класса для модели Membership
:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
В этом примере используются значения по умолчанию InlineModelAdmin
для модели Membership
, а дополнительные формы добавления ограничены одной. Это можно настроить, используя любые опции, доступные для классов InlineModelAdmin
.
Теперь создайте представления администратора для моделей Person
и Group
:
class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
Наконец, зарегистрируйте свои модели Person
и Group
на сайте администратора:
admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)
Теперь ваш администраторский сайт настроен на редактирование Membership
объектов в строке со страниц деталей Person
или Group
.
Использование родовых отношений в качестве инлайна¶
Можно использовать инлайн с общими связанными объектами. Допустим, у вас есть следующие модели:
from django.contrib.contenttypes.fields import GenericForeignKey
from django.db import models
class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
Если вы хотите разрешить редактирование и создание экземпляра Image
на Product
, добавление/изменение представлений, вы можете использовать GenericTabularInline
или GenericStackedInline
(оба подкласса GenericInlineModelAdmin
), предоставляемые admin
. Они реализуют табличную и стековую визуальные компоновки для форм, представляющих инлайн-объекты, соответственно, как и их негенерические аналоги. Они ведут себя так же, как и любой другой инлайн. В вашем admin.py
для этого примера приложении:
from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline
from myproject.myapp.models import Image, Product
class ImageInline(GenericTabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Product, ProductAdmin)
Более подробную информацию см. в contenttypes documentation.
Переопределение шаблонов администратора¶
Вы можете переопределить многие шаблоны, которые модуль администратора использует для создания различных страниц сайта администратора. Вы даже можете переопределить некоторые из этих шаблонов для конкретного приложения или конкретной модели.
Настройте каталоги шаблонов администратора ваших проектов¶
Файлы шаблонов администратора находятся в директории contrib/admin/templates/admin
.
Для того чтобы переопределить один или несколько из них, сначала создайте каталог admin
в каталоге templates
вашего проекта. Это может быть любой из каталогов, которые вы указали в опции DIRS
бэкенда DjangoTemplates
в настройке TEMPLATES
. Если вы настроили опцию 'loaders'
, убедитесь, что 'django.template.loaders.filesystem.Loader'
появляется перед 'django.template.loaders.app_directories.Loader'
, чтобы ваши пользовательские шаблоны были найдены системой загрузки шаблонов раньше тех, которые включены в django.contrib.admin
.
В этом каталоге admin
создайте подкаталоги с именами ваших приложений. Внутри этих подкаталогов приложения создайте подкаталоги с именами ваших моделей. Обратите внимание, что приложение администратора при поиске каталога будет писать имя модели в нижнем регистре, поэтому убедитесь, что вы назвали каталог в нижнем регистре, если вы собираетесь запускать ваше приложение в файловой системе, чувствительной к регистру.
Чтобы переопределить шаблон администратора для конкретного приложения, скопируйте и отредактируйте шаблон из каталога django/contrib/admin/templates/admin
и сохраните его в одном из каталогов, которые вы только что создали.
Например, если мы хотим добавить инструмент в представление списка изменений для всех моделей в приложении с именем my_app
, мы скопируем contrib/admin/templates/admin/change_list.html
в каталог templates/admin/my_app/
нашего проекта и внесем все необходимые изменения.
Если бы мы хотели добавить инструмент в представление списка изменений только для определенной модели с именем „Page“, мы бы скопировали этот же файл в каталог templates/admin/my_app/page
нашего проекта.
Переопределение и замена шаблона администратора¶
Из-за модульной конструкции шаблонов администраторов обычно не требуется и не рекомендуется заменять весь шаблон. Почти всегда лучше переопределить только ту часть шаблона, которую необходимо изменить.
Продолжая приведенный выше пример, мы хотим добавить новую ссылку рядом с инструментом History
для модели Page
. Посмотрев на change_form.html
, мы определили, что нам нужно переопределить только блок object-tools-items
. Поэтому вот наш новый блок change_form.html
:
{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
<li>
<a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% translate "History" %}</a>
</li>
<li>
<a href="mylink/" class="historylink">My Link</a>
</li>
{% if has_absolute_url %}
<li>
<a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% translate "View on site" %}</a>
</li>
{% endif %}
{% endblock %}
И все! Если бы мы поместили этот файл в каталог templates/admin/my_app
, то наша ссылка появилась бы в форме изменения для всех моделей внутри my_app.
Шаблоны, которые могут быть переопределены для каждого приложения или модели¶
Не все шаблоны в contrib/admin/templates/admin
могут быть переопределены для каждого приложения или модели. Следующие могут:
actions.html
app_index.html
change_form.html
change_form_object_tools.html
change_list.html
change_list_object_tools.html
change_list_results.html
date_hierarchy.html
delete_confirmation.html
object_history.html
pagination.html
popup_response.html
prepopulated_fields_js.html
search_form.html
submit_line.html
Для тех шаблонов, которые нельзя переопределить таким образом, вы все равно можете переопределить их для всего проекта, поместив новую версию в каталог templates/admin
. Это особенно полезно для создания пользовательских страниц 404 и 500.
Примечание
Некоторые шаблоны администратора, такие как change_list_results.html
, используются для отображения пользовательских тегов включения. Они могут быть переопределены, но в таких случаях вам, вероятно, лучше создать свою собственную версию тега и дать ему другое имя. Таким образом, вы сможете использовать его выборочно.
Шаблоны корня и входа в систему¶
Если вы хотите изменить шаблоны index, login или logout, вам лучше создать свой собственный экземпляр 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
.Если вы хотите настроить сайт администратора по умолчанию, вы можете override it.
При конструировании экземпляра
AdminSite
можно задать уникальное имя экземпляра, используя аргументname
в конструкторе. Это имя экземпляра используется для идентификации экземпляра, особенно при reversing admin URLs. Если имя экземпляра не указано, будет использоваться имя экземпляра по умолчаниюadmin
. Пример настройки класса Настройка класса AdminSite см. в разделеAdminSite
.
AdminSite
атрибуты¶
Шаблоны могут переопределять или расширять базовые шаблоны администратора, как описано в Переопределение шаблонов администратора.
-
AdminSite.
site_header
¶ Текст для размещения в верхней части каждой страницы администратора, в виде
<h1>
(строка). По умолчанию это «Django administration».
-
AdminSite.
site_title
¶ Текст, который нужно поместить в конце
<title>
каждой страницы администратора (строка). По умолчанию это «Django site admin».
-
AdminSite.
site_url
¶ URL для ссылки «Просмотр сайта» в верхней части каждой страницы администратора. По умолчанию
site_url
имеет значение/
. Установите значениеNone
, чтобы убрать ссылку.Для сайтов, работающих на подпути, метод
each_context()
проверяет, установлен ли для текущего запросаrequest.META['SCRIPT_NAME']
, и использует это значение, еслиsite_url
не установлен на что-то другое, чем/
.
-
AdminSite.
index_title
¶ Текст для размещения в верхней части индексной страницы администратора (строка). По умолчанию это «Администрация сайта».
-
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_header
site_title
:AdminSite.site_title
site_url
:AdminSite.site_url
has_permission
:AdminSite.has_permission()
available_apps
: список приложений из application registry, доступных для текущего пользователя. Каждая запись в списке является диктой, представляющей приложение со следующими ключами:app_label
: ярлык приложенияapp_url
: URL-адрес индекса приложения в админкеhas_module_perms
: булево значение, указывающее, разрешено ли отображение и доступ к индексной странице модуля для текущего пользователяmodels
: список моделей, доступных в приложении
Каждая модель представляет собой диктант со следующими ключами:
object_name
: имя класса моделиname
: множественное имя моделиperms
: разрешениеdict
, отслеживающееadd
,change
,delete
иview
admin_url
: URL-адрес списка изменений администратора для моделиadd_url
: URL-адрес администратора для добавления нового экземпляра модели
-
AdminSite.
has_permission
(request)[исходный код]¶ Возвращает
True
, если пользователь для данногоHttpRequest
имеет разрешение на просмотр хотя бы одной страницы на сайте администратора. По умолчанию требует, чтобы иUser.is_active
, иUser.is_staff
былиTrue
.
-
AdminSite.
register
(model_or_iterable, admin_class=None, **options)[исходный код]¶ Регистрирует заданный класс модели (или итерабель классов) с заданным
admin_class
.admin_class
по умолчанию используетсяModelAdmin
(опции администратора по умолчанию). Если заданы аргументы в виде ключевых слов – например,list_display
– они будут применены как опции к классу администратора.Вызывает
ImproperlyConfigured
, если модель является абстрактной. иdjango.contrib.admin.sites.AlreadyRegistered
, если модель уже зарегистрирована.
-
AdminSite.
unregister
(model_or_iterable)[исходный код]¶ Снимает с регистрации заданный класс модели (или итерабель классов).
Вызывает
django.contrib.admin.sites.NotRegistered
, если модель еще не зарегистрирована.
Включение экземпляров AdminSite
в вашу URLconf¶
Последним шагом в настройке администратора Django является подключение вашего экземпляра AdminSite
к вашей URLconf. Сделайте это, указав заданный URL на метод AdminSite.urls
. Нет необходимости использовать include()
.
В этом примере мы регистрируем экземпляр по умолчанию AdminSite
django.contrib.admin.site
на URL /admin/
:
# urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
Настройка класса AdminSite
¶
Если вы хотите создать свой собственный сайт администратора с пользовательским поведением, вы можете подкласс AdminSite
и переопределить или добавить все, что вам нравится. Затем создайте экземпляр вашего подкласса AdminSite
(так же, как вы создаете любой другой класс Python) и зарегистрируйте свои модели и подклассы ModelAdmin
в нем, а не в сайте по умолчанию. Наконец, обновите myproject/urls.py
, чтобы он ссылался на ваш AdminSite
подкласс.
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),
]
Обратите внимание, что вам может не понадобиться автообнаружение модулей admin
при использовании собственного экземпляра AdminSite
, поскольку вы, вероятно, будете импортировать все модули admin
для каждого приложения в свой модуль myproject.admin
. Это означает, что вам нужно поставить 'django.contrib.admin.apps.SimpleAdminConfig'
вместо 'django.contrib.admin'
в настройках INSTALLED_APPS
.
Переопределение сайта администратора по умолчанию¶
Вы можете переопределить значение по умолчанию 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 для целей reversing them. Это необходимо только в том случае, если вы используете более одного AdminSite
.
Добавление представлений к сайтам администраторов¶
Как и ModelAdmin
, AdminSite
предоставляет метод get_urls()
, который может быть переопределен для определения дополнительных представлений для сайта. Чтобы добавить новое представление на ваш администраторский сайт, расширьте базовый метод get_urls()
, включив в него шаблон для вашего нового представления.
Примечание
Любое представление, которое использует шаблоны администратора или расширяет базовый шаблон администратора, должно установить request.current_app
перед отображением шаблона. Оно должно быть установлено либо в self.name
, если ваше представление находится на AdminSite
, либо в self.admin_site.name
, если ваше представление находится на ModelAdmin
.
Добавление функции сброса пароля¶
Вы можете добавить функцию сброса пароля на сайт администратора, добавив несколько строк в URLconf. В частности, добавьте эти четыре шаблона:
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 reversing system Django.
AdminSite
предоставляет следующие именованные шаблоны URL:
Страница | Имя URL | Параметры |
---|---|---|
Индекс | index |
|
Вход в систему | login |
|
Выход из системы | logout |
|
Смена пароля | password_change |
|
Смена пароля выполнена | password_change_done |
|
i18n JavaScript | jsi18n |
|
Индексная страница приложения | app_list |
app_label |
Перенаправление на страницу объекта | view_on_site |
content_type_id , object_id |
Каждый экземпляр ModelAdmin
предоставляет дополнительный набор именованных URL:
Страница | Имя URL | Параметры |
---|---|---|
Changelist | {{ app_label }}_{{ model_name }}_changelist |
|
Добавить | {{ app_label }}_{{ model_name }}_add |
|
История | {{ app_label }}_{{ model_name }}_history |
object_id |
Удалить | {{ app_label }}_{{ model_name }}_delete |
object_id |
Изменить | {{ app_label }}_{{ model_name }}_change |
object_id |
UserAdmin
предоставляет именованный URL:
Страница | Имя URL | Параметры |
---|---|---|
Смена пароля | auth_user_password_change |
user_id |
Эти именованные URL регистрируются в пространстве имен приложения admin
, а также в пространстве имен экземпляра, соответствующем имени экземпляра Site.
Итак - если вы хотите получить ссылку на представление Change для определенного объекта Choice
(из приложения polls) в администраторе по умолчанию, вы вызовете:
>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,))
Это позволит найти первый зарегистрированный экземпляр приложения администратора (независимо от имени экземпляра) и разрешить представление для изменения poll.Choice
экземпляров в этом экземпляре.
Если вы хотите найти URL в определенном экземпляре администратора, укажите имя этого экземпляра в качестве подсказки current_app
для обратного вызова. Например, если вам нужен вид администратора из экземпляра администратора с именем custom
, вам нужно вызвать:
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,), current_app='custom')
Для более подробной информации смотрите документацию по reversing namespaced URLs.
Для того чтобы упростить реверсирование урлов администратора в шаблонах, 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')[исходный код]¶ Этот декоратор используется в представлениях администратора, требующих авторизации. Представление, декорированное этой функцией, будет иметь следующее поведение:
- Если пользователь вошел в систему, является сотрудником (
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): ...
- Если пользователь вошел в систему, является сотрудником (