Сайт администратора Django¶
Одна из самых мощных частей Django - это автоматический интерфейс администратора. Он считывает метаданные из ваших моделей, чтобы обеспечить быстрый, ориентированный на модели интерфейс, в котором доверенные пользователи могут управлять содержимым вашего сайта. Рекомендуемое использование администратора ограничено внутренним инструментом управления организации. Он не предназначен для создания всего фронт-энда.
В админке есть множество крючков для настройки, но остерегайтесь попыток использовать исключительно эти крючки. Если вам нужно предоставить более ориентированный на процесс интерфейс, который абстрагируется от деталей реализации таблиц и полей базы данных, то, вероятно, пришло время написать собственные представления.
В этом документе мы обсудим, как активировать, использовать и настраивать интерфейс администратора Django.
Обзор¶
Администратор включен в шаблон проекта по умолчанию, используемый startproject.
Если вы не используете шаблон проекта по умолчанию, вот требования:
- Добавьте
'django.contrib.admin'и его зависимости -django.contrib.auth,django.contrib.contenttypes,django.contrib.messagesиdjango.contrib.sessions- в настройкуINSTALLED_APPS. - Настройте бэкенд
DjangoTemplatesв настройкахTEMPLATESсdjango.contrib.auth.context_processors.authиdjango.contrib.messages.context_processors.messagesв настройках'context_processors'сOPTIONS. - Если вы настроили параметр
MIDDLEWARE,django.contrib.auth.middleware.AuthenticationMiddlewareиdjango.contrib.messages.middleware.MessageMiddlewareдолжны быть включены.
После выполнения этих действий вы сможете воспользоваться сайтом администратора, посетив URL, к которому вы его подключили (/admin/, по умолчанию).
Если вам нужно создать пользователя для входа в систему, используйте команду createsuperuser. По умолчанию для входа в систему администратора требуется, чтобы у пользователя был установлен атрибут is_superuser или 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.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¶ - New in Django 2.1.
Точечный путь импорта к классу сайта администратора по умолчанию или к вызываемому объекту, который возвращает экземпляр сайта. По умолчанию имеет значение
'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 self.birthday.strftime('%Y')[:3] + "0's" 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.Если указанная строка является методом модели,
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, Django отобразит красивую иконку «включено» или «выключено», если вы зададите методу атрибут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 self.birthday.strftime('%Y')[:3] == '195' 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')
New in Django 2.1:Добавлена поддержка выражений в
admin_order_field.Элементы
list_displayтакже могут быть свойствами. Однако, обратите внимание, что из-за особенностей работы свойств в Python, установкаshort_descriptionна свойство возможна только при использовании функции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" 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выбор пользователями, которые написали книгу, вместо того, чтобы перечислять всех пользователей.Примечание
API
FieldListFilterсчитается внутренним и может быть изменен.
Фильтр списка обычно появляется только в том случае, если фильтр имеет более одного выбора. Метод
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_fieldsInputдолжен содержать первичный ключ, если поле является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работает только с одним поисковым словом, поскольку два или более слов не могут быть точным совпадением, если только все слова не одинаковые.New in Django 2.1:Добавлена возможность указать поиск по полю.
Также доступны некоторые (старые) сочетания клавиш для указания поиска поля. Вы можете задать префикс поля в
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¶ - New in Django 2.1.
По умолчанию страница списка изменений позволяет сортировать по всем полям модели (и 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)[исходный код]¶ - New in Django 2.1.
Методу
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)¶ - New in Django 2.1.
Методу
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_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.
-
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)¶ - New in Django 2.1.
Должно возвращать
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)[исходный код]¶ - New in Django 2.1.
Хук для настройки процесса удаления
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.3.1) размещается в пространстве имен как django.jQuery. Если вы хотите использовать jQuery в собственном JavaScript администратора без включения второй копии, вы можете использовать объект django.jQuery в списке изменений и представлениях добавления/редактирования.
jQuery был обновлен с версии 2.2.3 до версии 3.3.1.
jQuery был обновлен с версии 3.3.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). К общим функциям относятся:
formfieldsetsfieldsformfield_overridesexcludefilter_horizontalfilter_verticalorderingprepopulated_fieldsget_fieldsets()get_queryset()radio_fieldsreadonly_fieldsraw_id_fieldsformfield_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¶ Этот параметр определяет количество дополнительных форм, которые набор форм будет отображать в дополнение к начальным формам. Для получения дополнительной информации смотрите 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при добавлении нового родителя.Changed in Django 2.1:Был добавлен аргумент
obj. Во время периода устаревания он также может бытьNone, если сторонние вызовыhas_add_permission()не обеспечивают его.
-
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">{% trans "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">{% trans "View on site" %}</a>
</li>
{% endif %}
{% endblock %}
И все! Если бы мы поместили этот файл в каталог templates/admin/my_app, то наша ссылка появилась бы в форме изменения для всех моделей внутри my_app.
Шаблоны, которые могут быть переопределены для каждого приложения или модели¶
Не все шаблоны в contrib/admin/templates/admin могут быть переопределены для каждого приложения или модели. Следующие могут:
actions.htmlapp_index.htmlchange_form.htmlchange_form_object_tools.htmlchange_list.htmlchange_list_object_tools.htmlchange_list_results.htmldate_hierarchy.htmldelete_confirmation.htmlobject_history.htmlpagination.htmlpopup_response.htmlprepopulated_fields_js.htmlsearch_form.htmlsubmit_line.html
Добавлена возможность переопределения шаблонов actions.html, change_form_object_tools.html, change_list_object_tools.html, change_list_results.html, date_hierarchy.html, pagination.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.
-
AdminSite.login_template¶ Путь к пользовательскому шаблону, который будет использоваться представлением входа на сайт администратора.
-
AdminSite.login_form¶ Подкласс
AuthenticationForm, который будет использоваться представлением входа на сайт администратора.
-
AdminSite.logout_template¶ Путь к пользовательскому шаблону, который будет использоваться в представлении выхода из сайта администратора.
-
AdminSite.password_change_template¶ Путь к пользовательскому шаблону, который будет использоваться в представлении изменения пароля администратора сайта.
-
AdminSite.password_change_done_template¶ Путь к пользовательскому шаблону, который будет использоваться в представлении изменения пароля администратора сайта.
AdminSite методы¶
-
AdminSite.each_context(request)[исходный код]¶ Возвращает словарь переменных, которые нужно поместить в контекст шаблона для каждой страницы на сайте администратора.
По умолчанию включает следующие переменные и значения:
site_header:AdminSite.site_headersite_title:AdminSite.site_titlesite_url:AdminSite.site_urlhas_permission:AdminSite.has_permission()available_apps: список приложений из application registry, доступных для текущего пользователя. Каждая запись в списке является диктой, представляющей приложение со следующими ключами:app_label: ярлык приложенияapp_url: URL-адрес индекса приложения в админкеhas_module_perms: булево значение, указывающее, разрешено ли отображение и доступ к индексной странице модуля для текущего пользователяmodels: список моделей, доступных в приложении
Каждая модель представляет собой диктант со следующими ключами:
object_name: имя класса моделиname: множественное имя моделиperms: разрешениеdict, отслеживающееadd,change,deleteиviewadmin_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 в вашу 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): ...
- Если пользователь вошел в систему, является сотрудником (