Сайт администратора Django
Одной из самых мощных частей Django является автоматический интерфейс администратора. Он считывает метаданные в вашей модели, чтобы предоставить мощный и готовый к использованию в производстве интерфейс, который производители контента могут немедленно использовать для начала добавления контента на сайт. В этом документе мы обсудим, как активировать, использовать и настраивать интерфейс администратора Django.
Обзор
Администратор включен в шаблон проекта по умолчанию, используемый startproject.
Для справки, вот требования:
- Добавьте
'django.contrib.admin'в настройкуINSTALLED_APPS. - Администратор имеет четыре зависимости —
django.contrib.auth,django.contrib.contenttypes,django.contrib.messagesиdjango.contrib.sessions. Если эти приложения отсутствуют в вашем спискеINSTALLED_APPS, добавьте их. - Добавьте
django.contrib.auth.context_processors.authиdjango.contrib.messages.context_processors.messagesк параметру'context_processors'бэкендаDjangoTemplates, определенного в вашей настройкеTEMPLATES, а такжеdjango.contrib.auth.middleware.AuthenticationMiddlewareиdjango.contrib.messages.middleware.MessageMiddlewareвMIDDLEWARE_CLASSES. (Все они активны по умолчанию, поэтому вам нужно это делать только в том случае, если вы вручную изменили настройки.) - Определите, какие модели ваших приложений должны быть доступны для редактирования в интерфейсе администратора.
- Для каждой из этих моделей, необязательно, создайте класс
ModelAdmin, который обобщает настраиваемые функциональные возможности и параметры для этой конкретной модели. - Создайте экземпляр
AdminSiteи сообщите ему о каждой из ваших моделей и классахModelAdmin. - Присоедините экземпляр
AdminSiteк вашей URLconf.
После выполнения этих шагов вы сможете использовать сайт администратора Django, перейдя по URL-адресу, к которому вы его подключили (/admin/, по умолчанию).
Другие темы
См. также
Дополнительная информация о предоставлении статических файлов (изображений, JavaScript и CSS), связанных с администратором в режиме производства, см. Обработка файлов.
Возникли проблемы? Попробуйте Вопросы и ответы: администратор.
ModelAdmin объекты
-
class ModelAdmin[source] -
Класс
ModelAdminпредставляет модель в интерфейсе администратора. Обычно они хранятся в файле с именемadmin.pyв вашем приложении. Давайте рассмотрим очень простой примерModelAdmin.from django.contrib import admin from myproject.myapp.models import Author class AuthorAdmin(admin.ModelAdmin): pass admin.site.register(Author, AuthorAdmin)Нужен ли вам объект
ModelAdminвообще?В приведенном выше примере класс
ModelAdminне определяет никаких пользовательских значений (еще). В результате будет предоставлен стандартный интерфейс администратора. Если вас устраивает интерфейс администратора по умолчанию, вам не нужно определять объектModelAdminвообще — вы можете зарегистрировать класс модели без предоставления описанияModelAdmin. Приведенный пример можно упростить до:from django.contrib import admin from myproject.myapp.models import Author admin.site.register(Author)
Декоратор регистрации
-
register(*models, site=django.admin.sites.site)[source] -
Также существует декоратор для регистрации ваших классов
ModelAdmin.from django.contrib import admin from .models import Author @admin.register(Author) class AuthorAdmin(admin.ModelAdmin): passЕму передаётся один или несколько классов модели для регистрации с администратором, и необязательный ключевой параметр
site, если вы не используете стандартныйAdminSite.from django.contrib import admin from .models import Author, Reader, Editor from myproject.admin_site import custom_admin_site @admin.register(Author, Reader, Editor, site=custom_admin_site) class PersonAdmin(admin.ModelAdmin): passВы не можете использовать этот декоратор, если вам необходимо сослаться на свой класс администрирования модели в его методе
__init__(), например,super(PersonAdmin, self).__init__(*args, **kwargs). Если вы используете Python 3 и не должны беспокоиться о поддержке Python 2, вы можете использоватьsuper().__init__(*args, **kwargs). В противном случае вам придется использоватьadmin.site.register()вместо этого декоратора.
Обнаружение файлов администратора
Когда вы помещаете 'django.contrib.admin' в настройку INSTALLED_APPS, Django автоматически ищет модуль admin в каждом приложении и импортирует его.
-
class apps.AdminConfig -
Это стандартный класс
AppConfigдля администратора. Он вызываетautodiscover(), когда Django запускается.
-
class apps.SimpleAdminConfig -
Этот класс работает так же, как
AdminConfig, за исключением того, что он не вызываетautodiscover().
-
autodiscover()[source] -
Эта функция пытается импортировать модуль
adminв каждом установленных приложении. Такие модули ожидают, что они будут регистрировать модели с администратором.Предыдущие версии Django рекомендовали вызывать эту функцию непосредственно в URLconf. Начиная с Django 1.7, это больше не нужно.
AdminConfigзаботится об автоматическом выполнении автообнаружения.
Если вы используете пользовательский AdminSite, обычно все подклассы ModelAdmin импортируются в ваш код и регистрируются в пользовательском AdminSite. В этом случае, чтобы отключить автообнаружение, вам следует поместить 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в настройку INSTALLED_APPS.
В предыдущих версиях администратору нужно было указать искать файлы admin.py с помощью autodiscover(). Начиная с Django 1.7, автообнаружение включено по умолчанию и должно быть явно отключено, когда это нежелательно.
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используетQuerySet.datetimes()внутри. Обратитесь к документации для некоторых замечаний, когда включена поддержка часовых поясов (USE_TZ = True).
-
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, может содержать только имена полей модели или формы, указанной вform. Она может содержать вызываемые объекты только в том случае, если они указаны в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>на странице формы администрирования. (Полесет — это «раздел» формы.)Парные кортежи имеют формат
(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': ('enable_comments', '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будут изначально свёрнуты в админ-панели и заменены небольшой ссылкой «нажать, чтобы развернуть». Полесеты со стилем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.db import models from django.contrib import admin # Import our custom widget and our model from where they're defined from myapp.widgets import RichTextEditorWidget from myapp.models import MyModel class MyModelAdmin(admin.ModelAdmin): formfield_overrides = { models.TextField: {'widget': RichTextEditorWidget}, }Обратите внимание, что ключ в словаре — это фактический класс поля, а не строка. Значение — ещё один словарь; эти аргументы будут переданы методу
__init__()поля формы. Подробнее см. API форм.Предупреждение
Если вы хотите использовать пользовательский виджет с полем связи (например,
ForeignKeyилиManyToManyField), убедитесь, что вы не включили имя этого поля вraw_id_fieldsилиradio_fields.formfield_overridesне позволит вам изменить виджет в полях связи, для которых заданыraw_id_fieldsилиradio_fields. Это потому, чтоraw_id_fieldsиradio_fieldsподразумевают свои собственные пользовательские виджеты.
-
ModelAdmin.inlines -
См. также объекты
InlineModelAdminниже иModelAdmin.get_formsets_with_inlines().
-
ModelAdmin.list_display -
Настройка
list_displayдля управления отображением полей на странице списка изменений админ-панели.Пример:
list_display = ('first_name', 'last_name')Если
list_displayне задано, админ-сайт отобразит единственный столбец, показывающий__str__()(__unicode__()в Python 2) представление каждого объекта.В
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' -
Строка, представляющая атрибут модели. Работает почти так же, как функция, но
selfв этом контексте — экземпляр модели. Вот полный пример модели:from django.db import models from django.contrib import admin 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__()(__unicode__()в Python 2) связанного объекта. -
ManyToManyFieldполя не поддерживаются, поскольку это потребует выполнения отдельного SQL-запроса для каждой строки в таблице. Если вам всё же нужно это сделать, добавьте в модель пользовательский метод и укажите имя этого метода вlist_display. (См. ниже дополнительную информацию о пользовательских методах вlist_display.) - Если поле является
BooleanFieldилиNullBooleanField, Django отобразит красивый значок «вкл» или «выкл» вместоTrueилиFalse. -
Если указанная строка является методом модели,
ModelAdminили функцией, Django по умолчанию экранирует вывод. Если вам не нужно экранировать вывод метода, задайте атрибутallow_tagsсо значениемTrue. Однако, чтобы избежать уязвимости XSS, используйтеformat_html()для экранирования данных, предоставленных пользователем.Вот полный пример модели:
from django.db import models from django.contrib import admin 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) colored_name.allow_tags = True class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'colored_name') -
Если указанная строка является методом модели,
ModelAdminили функцией, возвращающей True или False, Django отобразит красивый значок «вкл» или «выкл», если вы зададите атрибутbooleanсо значениемTrue.Вот полный пример модели:
from django.db import models from django.contrib import admin 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__()(__unicode__()в Python 2) также допустим вlist_display, как и любой другой метод модели, поэтому это вполне допустимо:list_display = ('__str__', 'some_other_field') -
Обычно элементы
list_display, которые не являются фактическими полями базы данных, не могут использоваться для сортировки (потому что Django выполняет всю сортировку на уровне базы данных).Однако, если элемент
list_displayпредставляет определённое поле базы данных, вы можете указать это, установив атрибутadmin_order_fieldэлемента.Например:
from django.db import models from django.contrib import admin 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.allow_tags = True 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' -
Элементы
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 = NoneNoneбыл добавлен в качестве допустимого значенияlist_display_links. - Установите его в
-
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 ugettext_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(AuthDecadeBornListFilter, self).lookups(request, model_admin) def queryset(self, request, queryset): if request.user.is_superuser: return super(AuthDecadeBornListFilter, self).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считается внутренним и может быть изменен.
Можно указать пользовательский шаблон для отображения фильтра списка:
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. Пустой кортеж предотвратит вызовselect_relatedDjango вообще. Любой другой кортеж будет передан напрямую вselect_relatedв качестве параметров. Например:class ArticleAdmin(admin.ModelAdmin): list_select_related = ('author', 'category')вызовет
select_related('author', 'category').
-
ModelAdmin.ordering -
Установите
orderingдля указания порядка сортировки списков объектов в представлениях Django admin. Это должен быть список или кортеж в том же формате, что и параметрorderingмодели.Если это не указано, Django admin будет использовать порядок сортировки по умолчанию для модели.
Если вам нужно указать динамический порядок (например, в зависимости от пользователя или языка), вы можете реализовать метод
get_ordering().
-
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полей из одного или нескольких других полей. Сгенерированное значение получается путем конкатенации значений исходных полей, а затем путем преобразования этого результата в допустимый слаг (например, замена пробелов тире).prepopulated_fieldsне принимает поляDateTimeField,ForeignKey, ниManyToManyField.
-
ModelAdmin.preserve_filters -
Админка теперь сохраняет фильтры на представлении списка после создания, редактирования или удаления объекта. Вы можете восстановить предыдущее поведение, очищающее фильтры, установив этот атрибут в
False.
-
ModelAdmin.radio_fields -
По умолчанию админка Django использует интерфейс выпадающего списка (<select>) для полей, которые
ForeignKeyили имеютchoicesустановленным. Если поле присутствует вradio_fields, Django будет использовать интерфейс радиокнопок вместо него. Предположим, чтоgroup— этоForeignKeyмоделиPerson:class PersonAdmin(admin.ModelAdmin): radio_fields = {"group": admin.VERTICAL}У вас есть выбор использования
HORIZONTALилиVERTICALиз модуляdjango.contrib.admin.Не включайте поле в
radio_fields, если оно не являетсяForeignKeyили у него не установленоchoices.
-
ModelAdmin.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 "<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" # in this example, we have used HTML tags in the output address_report.allow_tags = True
-
ModelAdmin.save_as -
Установите
save_asдля включения функции «сохранить как» в формах изменения админки.Обычно у объектов есть три варианта сохранения: «Сохранить», «Сохранить и продолжить редактирование» и «Сохранить и добавить другой». Если
save_asравноTrue, «Сохранить и добавить другой» будет заменено кнопкой «Сохранить как».«Сохранить как» означает, что объект будет сохранён как новый объект (с новым идентификатором), а не как старый.
По умолчанию
save_asустановлено вFalse.
-
ModelAdmin.save_on_top -
Установите
save_on_topдля добавления кнопок сохранения в верхней части форм изменения админки.Обычно кнопки сохранения отображаются только внизу форм. Если вы установите
save_on_top, кнопки будут отображаться как сверху, так и снизу.По умолчанию
save_on_topустановлено в значениеFalse.
-
ModelAdmin.search_fields -
Установите
search_fieldsдля включения поля поиска на странице списка изменений админки. Это должно быть список имён полей, которые будут проиндексированы при каждом запросе поиска.Эти поля должны быть каким-либо типом текстового поля, например
CharFieldилиTextField. Вы также можете выполнить связанный поиск поForeignKeyилиManyToManyFieldс использованием синтаксиса поиска «следовать»:search_fields = ['foreign_key__related_fieldname']
Например, если у вас есть запись блога с автором, следующее определение позволит искать записи блога по адресу электронной почты автора:
search_fields = ['user__email']
Когда пользователь выполняет поиск в поле поиска админки, Django разбивает запрос поиска на слова и возвращает все объекты, содержащие каждое из слов, без учёта регистра, где каждое слово должно присутствовать хотя бы в одном из
search_fields. Например, еслиsearch_fieldsустановлено в значение['first_name', 'last_name']и пользователь ищетjohn lennon, Django выполнит запрос, эквивалентный следующему SQL-операторWHERE:WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
Для более быстрого и/или более ограниченного поиска добавьте оператор к имени поля:
-
^ -
Используйте оператор ‘^’, чтобы соответствовать началу поля. Например, если
search_fieldsустановлено в значение['^first_name', '^last_name']и пользователь ищетjohn lennon, Django выполнит запрос, эквивалентный следующему SQL-операторWHERE:WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%') AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
Этот запрос более эффективен, чем обычный запрос
'%john%', потому что база данных проверяет только начало данных в столбце, а не ищет по всему столбцу. Кроме того, если в столбце есть индекс, некоторые базы данных могут использовать его для этого запроса, даже если этоLIKEзапрос. -
= -
Используйте оператор ‘=’, чтобы выполнить точное совпадение, не учитывая регистр. Например, если
search_fieldsустановлено в значение['=first_name', '=last_name']и пользователь ищетjohn lennon, Django выполнит запрос, эквивалентный следующему SQL-операторWHERE:WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john') AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
Обратите внимание, что ввод запроса разбивается по пробелам, поэтому, следуя этому примеру, в настоящее время невозможно искать все записи, в которых
first_nameточно равно'john winston'(содержащее пробел). -
@ - Используйте оператор ‘@’, чтобы выполнить полнотекстовый поиск. Это аналогично методу поиска по умолчанию, но использует индекс. В настоящее время это доступно только для MySQL.
Если вам нужно настроить поиск, вы можете использовать
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.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.core.urlresolvers import reverse class PersonAdmin(admin.ModelAdmin): def view_on_site(self, obj): return 'http://example.com' + reverse('person-detail', kwargs={'slug': obj.slug})
Дополнительные параметры шаблона
В разделе Замена шаблонов админки описано, как переопределять или расширять стандартные шаблоны админки. Используйте следующие параметры для переопределения стандартных шаблонов, используемых представлениями ModelAdmin:
-
ModelAdmin.add_form_template -
Путь к настраиваемому шаблону, используемому
add_view().
-
ModelAdmin.change_form_template -
Путь к настраиваемому шаблону, используемому
change_view().
-
ModelAdmin.change_list_template -
Путь к настраиваемому шаблону, используемому
changelist_view().
-
ModelAdmin.delete_confirmation_template -
Путь к настраиваемому шаблону, используемому
delete_view()для отображения страницы подтверждения при удалении одного или нескольких объектов.
-
ModelAdmin.delete_selected_confirmation_template -
Путь к настраиваемому шаблону, используемому методом действия
delete_selectedдля отображения страницы подтверждения при удалении одного или нескольких объектов. См. документацию по действиям.
-
ModelAdmin.object_history_template -
Путь к настраиваемому шаблону, используемому
history_view().
ModelAdmin методы
Предупреждение
ModelAdmin.save_model() и ModelAdmin.delete_model() должны сохранять/удалять объект, они не предназначены для отмены, а позволяют выполнять дополнительные операции.
-
ModelAdmin.save_model(request, obj, form, change)[source] -
Метод
save_modelполучаетHttpRequest, экземпляр модели, экземплярModelFormи булевое значение, указывающее, добавляется или изменяется объект. Здесь вы можете выполнять любые предварительные или последующие операции сохранения.Например, чтобы прикрепить
request.userк объекту перед сохранением:from django.contrib import admin class ArticleAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): obj.user = request.user obj.save()
-
ModelAdmin.delete_model(request, obj)[source] -
Метод
delete_modelполучаетHttpRequestи экземпляр модели. Используйте этот метод для выполнения предварительных или последующих операций удаления.
-
ModelAdmin.save_formset(request, form, formset, change)[source] -
Метод
save_formsetполучаетHttpRequest, родительский экземплярModelFormи булевое значение, указывающее, добавляется или изменяется родительский объект.Например, чтобы прикрепить
request.userк каждому изменённому экземпляру модели formset: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()См. также Сохранение объектов в formset.
-
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)[source] -
Метод
get_search_resultsизменяет список отображаемых объектов на те, которые соответствуют предоставленному поисковому запросу. Он принимает запрос, набор данных, к которому применяются текущие фильтры, и поисковый запрос пользователя. Он возвращает кортеж, содержащий измененный набор данных для реализации поиска и булево значение, указывающее, могут ли результаты содержать дубликаты.По умолчанию выполняется поиск по полям, указанным в
ModelAdmin.search_fields.Этот метод можно переопределить своей собственной пользовательской функцией поиска. Например, вы можете захотеть искать по целочисленному полю или использовать внешний инструмент, такой как Solr или Haystack. Вы должны установить, могут ли изменения набора данных, внесённые вашим методом поиска, ввести дубликаты в результаты и вернуть
Trueво втором элементе возвращаемого значения.Например, чтобы включить поиск по целочисленному полю, можно использовать:
class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'age') search_fields = ('name',) def get_search_results(self, request, queryset, search_term): queryset, use_distinct = super(PersonAdmin, self).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
-
Метод
save_relatedполучаетHttpRequest, родительскийModelFormэкземпляр, список форм inline и булево значение, указывающее, добавляется ли родитель или изменяется. Здесь можно выполнить любые операции до или после сохранения объектов, связанных с родителем. Обратите внимание, что на этом этапе родительский объект и его форма уже сохранены.
-
ModelAdmin.get_readonly_fields(request, obj=None) -
Метод
get_readonly_fieldsполучаетHttpRequestи редактируемыйobjобъект (илиNoneпри добавлении формы) и должен вернуть список или кортеж имён полей, которые будут отображаться как только для чтения, как описано выше в разделеModelAdmin.readonly_fields.
-
ModelAdmin.get_prepopulated_fields(request, obj=None) -
Метод
get_prepopulated_fieldsполучаетHttpRequestи редактируемыйobjобъект (илиNoneпри добавлении формы) и должен вернуть список, как описано выше в разделеModelAdmin.prepopulated_fields.
-
ModelAdmin.get_list_display(request)[source] -
Метод
get_list_displayполучаетHttpRequestи должен вернуть список или кортеж имён полей, которые будут отображаться на странице списка изменений, как описано выше в разделеModelAdmin.list_display.
-
ModelAdmin.get_list_display_links(request, list_display)[source] -
Метод
get_list_display_linksполучаетHttpRequestи список или кортеж, возвращённый методомModelAdmin.get_list_display(). Он должен вернуть список или кортеж имён полей на странице списка изменений, которые будут связаны со страницей изменения, как описано в разделеModelAdmin.list_display_links.Noneбыл добавлен как допустимое значение возвратаget_list_display_links().
-
ModelAdmin.get_fields(request, obj=None)[source] -
Метод
get_fieldsполучаетHttpRequestи редактируемыйobjобъект (илиNoneпри добавлении формы) и должен вернуть список полей, как описано выше в разделеModelAdmin.fields.
-
ModelAdmin.get_fieldsets(request, obj=None) -
Метод
get_fieldsetsполучаетHttpRequestи редактируемыйobjобъект (илиNoneпри добавлении формы) и должен вернуть список пар из двух элементов, в которых каждая пара представляет собой набор полей на странице формы администрирования, как описано в разделеModelAdmin.fieldsets.
-
ModelAdmin.get_list_filter(request)[source] -
Метод
get_list_filterполучаетHttpRequestи должен вернуть последовательность того же типа, что и для атрибутаlist_filter.
-
ModelAdmin.get_search_fields(request)[source] -
Метод
get_search_fieldsполучаетHttpRequestи должен вернуть последовательность того же типа, что и для атрибутаsearch_fields.
-
ModelAdmin.get_inline_instances(request, obj=None)[source] -
Метод
get_inline_instancesполучаетHttpRequestи редактируемыйobjобъект (илиNoneпри добавлении формы) и должен вернуть список или кортеж объектовInlineModelAdmin, как описано ниже в разделеInlineModelAdmin. Например, следующее вернёт inline без фильтрации по умолчанию в зависимости от прав на добавление, изменение и удаление: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]Если вы переопределяете этот метод, убедитесь, что возвращаемые inline являются экземплярами классов, определённых в
inlines, иначе при добавлении связанных объектов может появиться ошибка «Неверный запрос».
-
ModelAdmin.get_urls()[source] -
Метод
get_urlsна экземпляреModelAdminвозвращает URL-адреса, используемые для этого ModelAdmin, так же, как URLconf. Поэтому вы можете расширить их, как описано в Диспечере URL-адресов:class MyModelAdmin(admin.ModelAdmin): def get_urls(self): urls = super(MyModelAdmin, self).get_urls() my_urls = [ url(r'^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(MyModelAdmin, self).get_urls() my_urls = [ url(r'^my_view/$', self.admin_site.admin_view(self.my_view)) ] return my_urls + urlsОбратите внимание на обернутое представление в пятой строке выше:
url(r'^my_view/$', self.admin_site.admin_view(self.my_view))
Эта оболочка защитит
self.my_viewот несанкционированного доступа и применит декораторdjango.views.decorators.cache.never_cache, чтобы убедиться, что она не кэшируется, если активен промежуточный сервер кэширования.Если страница кэшируема, но вы всё ещё хотите, чтобы проверка разрешений выполнялась, вы можете передать параметр
cacheable=TrueфункцииAdminSite.admin_view():url(r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))
-
ModelAdmin.get_form(request, obj=None, **kwargs)[source] -
Возвращает класс
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(MyModelAdmin, self).get_form(request, obj, **kwargs)Вы также можете просто вернуть пользовательский класс
ModelFormнапрямую.
-
ModelAdmin.get_formsets(request, obj=None)[source] -
Устаревшее с версии 1.7: Используйте
get_formsets_with_inlines()вместо этого.Возвращает
InlineModelAdminдля использования в представлениях админского добавления и изменения.Например, если вы хотите отобразить определённый встроенный элемент только в представлении изменения, вы можете переопределить
get_formsetsследующим образом:class MyModelAdmin(admin.ModelAdmin): inlines = [MyInline, SomeOtherInline] def get_formsets(self, request, obj=None): for inline in self.get_inline_instances(request, obj): # hide MyInline in the add view if isinstance(inline, MyInline) and obj is None: continue yield inline.get_formset(request, obj)
-
ModelAdmin.get_formsets_with_inlines(request, obj=None)[source] -
Возвращает пары (
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 isinstance(inline, MyInline) and obj is None: continue 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(MyModelAdmin, self).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(MyModelAdmin, self).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(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs)Примечание
Любой атрибут
choices, установленный для поля формы, будет ограничен только этим полем формы. Если соответствующее поле в модели имеет установленные варианты, предоставляемые для формы варианты должны быть действительным подмножеством этих вариантов, в противном случае отправка формы завершится ошибкойValidationErrorпри валидации модели перед сохранением.
-
ModelAdmin.get_changelist(request, **kwargs)[source] -
Возвращает класс
Changelistдля использования в списке. По умолчанию используетсяdjango.contrib.admin.views.main.ChangeList. Наследуя этот класс, вы можете изменить поведение отображения.
-
ModelAdmin.get_changelist_form(request, **kwargs)[source] -
Возвращает класс
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)[source] -
Возвращает класс 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(MyModelAdmin, self).get_changelist_formset(request, **kwargs)
-
ModelAdmin.has_add_permission(request) -
Должен возвращать
Trueесли добавление объекта разрешено,Falseв противном случае.
-
ModelAdmin.has_change_permission(request, obj=None) -
Должен возвращать
Trueесли редактирование объекта разрешено,Falseв противном случае. Если obj —None, должен возвращатьTrueилиFalseдля указания, разрешено ли редактирование объектов этого типа в целом (например,Falseбудет интерпретироваться как запрет редактирования любых объектов этого типа для текущего пользователя).
-
ModelAdmin.has_delete_permission(request, obj=None) -
Должен возвращать
Trueесли удаление объекта разрешено,Falseв противном случае. Если obj —None, должен возвращатьTrueилиFalseдля указания, разрешено ли удаление объектов этого типа в целом (например,Falseбудет интерпретироваться как запрет удаления любых объектов этого типа для текущего пользователя).
-
ModelAdmin.has_module_permission(request) -
Должен возвращать
Trueесли отображение модуля на странице админского индекса и доступ к странице индекса модуля разрешены,Falseв противном случае. По умолчанию используетUser.has_module_perms(). Переопределение не ограничивает доступ к представлениям добавления, изменения или удаления, для этого следует использоватьhas_add_permission(),has_change_permission()иhas_delete_permission().
-
ModelAdmin.get_queryset(request) -
Метод
get_querysetвModelAdminвозвращаетQuerySetвсех экземпляров модели, которые могут быть отредактированы админским сайтом. Один из случаев использования переопределения этого метода — отображение объектов, принадлежащих вошедшему пользователю:class MyModelAdmin(admin.ModelAdmin): def get_queryset(self, request): qs = super(MyModelAdmin, self).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)[source] -
Отправляет сообщение пользователю, используя бэкенд
django.contrib.messages. См. пример настраиваемого ModelAdmin.Использование ключевых аргументов позволяет изменить уровень сообщения, добавить дополнительные теги CSS или молча проигнорировать ошибку, если
contrib.messagesфреймворк не установлен. Эти ключевые аргументы соответствуют аргументам функцииdjango.contrib.messages.add_message(); для получения дополнительной информации обратитесь к документации этой функции. Отличие заключается в том, что уровень может быть передан как строковое обозначение помимо целого числа/константы.
-
ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)[source] -
Возвращает экземпляр пагинатора, который необходимо использовать для данного представления. По умолчанию создаёт экземпляр
paginator.
-
ModelAdmin.response_add(request, obj, post_url_continue=None)[source] -
Определяет
HttpResponseдля стадииadd_view().Вызывается после отправки формы администратора и сразу после создания и сохранения объекта и всех связанных экземпляров. Вы можете переопределить его, чтобы изменить стандартное поведение после создания объекта.
-
ModelAdmin.response_change(request, obj)[source] -
Определяет
HttpResponseдля стадииchange_view().Вызывается после отправки формы администратора и сразу после сохранения объекта и всех связанных экземпляров. Вы можете переопределить его, чтобы изменить стандартное поведение после изменения объекта.
-
ModelAdmin.response_delete(request, obj_display, obj_id)[source] -
Определяет
HttpResponseдля стадииdelete_view().Вызывается после удаления объекта. Вы можете переопределить его, чтобы изменить стандартное поведение после удаления объекта.
obj_display— строка с именем удалённого объекта.obj_id— сериализованный идентификатор, используемый для извлечения объекта, который нужно удалить.Параметр
obj_idбыл добавлен.
-
ModelAdmin.get_changeform_initial_data(request)[source] -
Привязка к начальным данным в формах изменения администратора. По умолчанию поля получают начальные значения из параметров
GET. Например,?name=initial_valueзадаст начальное значение поляnameвinitial_value.Этот метод должен возвращать словарь в формате
{'fieldname': 'fieldval'}:def get_changeform_initial_data(self, request): return {'name': 'custom_initial_value'}
Другие методы
-
ModelAdmin.add_view(request, form_url='', extra_context=None)[source] -
Представление Django для страницы добавления экземпляра модели. См. примечание ниже.
-
ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)[source] -
Представление Django для страницы редактирования экземпляра модели. См. примечание ниже.
-
ModelAdmin.changelist_view(request, extra_context=None)[source] -
Представление Django для страницы списка экземпляров модели/страницы действий. См. примечание ниже.
-
ModelAdmin.delete_view(request, object_id, extra_context=None)[source] -
Представление Django для страницы подтверждения удаления экземпляра(ов) модели. См. примечание ниже.
-
ModelAdmin.history_view(request, object_id, extra_context=None)[source] -
Представление Django для страницы, отображающей историю изменений для данного экземпляра модели.
В отличие от методов типа ModelAdmin, описанных в предыдущем разделе, эти пять методов фактически предназначены для вызова как представлений Django из обработчика маршрутизации URL-адреса приложения admin для отображения страниц, связанных с операциями CRUD экземпляров моделей. Полное переопределение этих методов существенно изменит поведение приложения admin.
Одной из распространённых причин переопределения этих методов является расширение данных контекста, которые предоставляются шаблону, отображающему представление. В следующем примере представление изменения переопределено таким образом, что предоставленному шаблону для отображения доступны дополнительные данные сопоставления, которые иначе недоступны:
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(MyModelAdmin, self).change_view(request, object_id,
form_url, extra_context=extra_context)
Эти представления возвращают экземпляры TemplateResponse, что позволяет легко настроить данные ответа перед отображением. Для получения дополнительной информации см. документацию TemplateResponse.
ModelAdmin определения активов
Иногда требуется добавить CSS и/или JavaScript в представления добавления/редактирования. Это можно сделать, используя внутренний класс Media в вашем ModelAdmin:
class ArticleAdmin(admin.ModelAdmin):
class Media:
css = {
"all": ("my_styles.css",)
}
js = ("my_code.js",)
Приложение staticfiles добавляет STATIC_URL (или MEDIA_URL, если STATIC_URL является None) к любым путям активов. Применяются те же правила, что и в определении активов форм.
jQuery
В JavaScript Django admin используется библиотека jQuery.
Чтобы избежать конфликтов с пользовательскими скриптами или библиотеками, Django’s jQuery (версия 1.11.2) имеет пространство имён django.jQuery. Если вы хотите использовать jQuery в собственном JavaScript admin без включения дополнительной копии, вы можете использовать объект django.jQuery в представлении списка изменений и представлениях добавления/редактирования.
Встроенный jQuery был обновлён с версии 1.9.1 до 1.11.2.
Класс ModelAdmin по умолчанию требует jQuery, поэтому нет необходимости добавлять jQuery в список ресурсов медиа вашего ModelAdmin, если у вас нет особой необходимости. Например, если вам нужен jQuery в глобальном пространстве имён (например, при использовании сторонних плагинов jQuery) или вам нужна более новая версия jQuery, придётся включить свою собственную копию.
Django предоставляет как нескомпрессированные, так и «скомпрессированные» версии jQuery, соответственно jquery.js и jquery.min.js.
ModelAdmin и InlineModelAdmin имеют свойство media, возвращающее список объектов Media, которые хранят пути к файлам JavaScript для форм и/или наборов форм. Если DEBUG равно True, он вернёт нескомпрессированные версии различных файлов JavaScript, включая jquery.js; в противном случае вернёт «скомпрессированные» версии.
Добавление пользовательской валидации в admin
Добавление пользовательской валидации данных в админ-панели довольно просто. Автоматический интерфейс админки использует 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 , иначе могут возникнуть проблемы. Обратитесь к документации форм по пользовательской валидации и, более конкретно, к примечаниям по валидации форм моделей для получения дополнительной информации.
InlineModelAdmin объекты
-
class InlineModelAdmin
-
class TabularInline[source]
-
class StackedInline[source] -
Интерфейс админки имеет возможность редактировать модели на одной странице с родительской моделью. Они называются вложенными. Предположим, у вас есть эти две модели:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): author = models.ForeignKey(Author) 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_queryset()radio_fieldsreadonly_fieldsraw_id_fieldsformfield_for_choice_field()formfield_for_foreignkey()formfield_for_manytomany()has_add_permission()has_change_permission()has_delete_permission()has_module_permission()
Класс InlineModelAdmin добавляет:
-
InlineModelAdmin.model -
Модель, которую использует вложенный элемент. Это обязательно.
-
InlineModelAdmin.fk_name -
Имя внешнего ключа в модели. В большинстве случаев это обрабатывается автоматически, но
fk_nameнеобходимо указать явно, если существует более одного внешнего ключа к той же родительской модели.
-
InlineModelAdmin.formset -
По умолчанию это
BaseInlineFormSet. Использование собственного набора форм предоставляет множество возможностей для настройки. Вложенные элементы основаны на наборах форм моделей.
-
InlineModelAdmin.form -
Значение для
formпо умолчанию равноModelForm. Это то, что передаётся вinlineformset_factory()при создании набора форм для этого вложенного элемента.
Предупреждение
При написании пользовательской валидации для InlineModelAdmin форм, будьте осторожны при написании валидации, которая опирается на особенности родительской модели. Если родительская модель не проходит валидацию, она может остаться в несогласованном состоянии, как описано в предупреждении в Валидации на ModelForm.
-
InlineModelAdmin.extra -
Это управляет количеством дополнительных форм, которые отобразит набор форм дополнительно к исходным формам. Для получения дополнительной информации см. документацию по наборам форм.
Для пользователей с браузерами, поддерживающими 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для использования в админских представлениях добавления/редактирования. См. пример для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.parent: return max_num - 5 return max_num
-
InlineModelAdmin.get_min_num(request, obj=None, **kwargs) -
Возвращает минимальное количество форм вложенной модели. По умолчанию возвращает атрибут
InlineModelAdmin.min_num.Переопределите этот метод для программированного определения минимального количества форм. Например, это может зависеть от экземпляра модели (переданного в качестве ключевого аргумента
obj) :
Работа с моделью с двумя или более внешними ключами к одной и той же родительской модели
Иногда может быть более одного внешнего ключа к одной и той же модели. Рассмотрим эту модель:
from django.db import models
class Friendship(models.Model):
to_person = models.ForeignKey(Person, related_name="friends")
from_person = models.ForeignKey(Person, 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, чтобы не отображать этот виджет — в противном случае у вас на странице админки будут два виджета для управления отношением.
Во всех остальных аспектах 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)
group = models.ForeignKey(Group)
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.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
class Image(models.Model):
image = models.ImageField(upload_to="images")
content_type = models.ForeignKey(ContentType)
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 для более подробной информации.
Переопределение шаблонов админки
Относительно легко переопределить многие шаблоны, используемые модулем админки для генерации различных страниц админского сайта. Вы можете даже переопределить некоторые из этих шаблонов для конкретного приложения или конкретной модели.
Настройка каталогов шаблонов админки проекта
Файлы шаблонов админки находятся в каталоге 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 можно переопределить по приложению или модели. Переопределять можно:
app_index.htmlchange_form.htmlchange_list.htmldelete_confirmation.htmlobject_history.html
Для тех шаблонов, которые нельзя переопределить таким образом, вы всё ещё можете переопределить их для всего проекта. Просто поместите новую версию в каталог templates/admin. Это особенно полезно для создания пользовательских страниц 404 и 500.
Примечание
Некоторые шаблоны админки, такие как change_list_results.html используются для отрисовки пользовательских тегов включения. Их можно переопределить, но в таких случаях, скорее всего, лучше создать свою версию интересующего тега и дать ему другое имя. Таким образом, вы сможете использовать его выборочно.
Шаблоны корневой и логин-страниц
Если вы хотите изменить шаблоны индекса, входа или выхода, лучше создать свою собственную AdminSite экземпляр (см. ниже) и изменить свойства AdminSite.index_template, AdminSite.login_template или AdminSite.logout_template.
AdminSite экземпляры
-
class AdminSite(name='admin')[source] -
Сайт Django администрирования представлен экземпляром класса
django.contrib.admin.sites.AdminSite; по умолчанию создаётся экземпляр этого класса какdjango.contrib.admin.site, и вы можете регистрировать в нём свои модели и экземплярыModelAdmin.При создании экземпляра
AdminSite, вы можете указать уникальное имя экземпляра, используя аргументnameв конструкторе. Это имя экземпляра используется для идентификации экземпляра, особенно при обращении к адресам администрирования. Если имя экземпляра не указано, будет использоваться имя по умолчаниюadmin. См. Настройка класса AdminSite для примера настройки классаAdminSite.
AdminSite атрибуты
Шаблоны могут переопределять или расширять базовые шаблоны администрирования, как описано в Переопределение шаблонов админки.
-
AdminSite.site_header -
Текст в верхней части каждой страницы администрирования, как
<h1>(строка). По умолчанию это “Django администрирование”.
-
AdminSite.site_title -
Текст в конце каждой страницы администрирования
<title>(строка). По умолчанию это “Django сайт администрирования”.
-
AdminSite.site_url -
Адрес ссылки «Просмотр сайта» в верхней части каждой страницы администрирования. По умолчанию
site_urlэто/. Установите его вNoneчтобы удалить ссылку.
-
AdminSite.index_title -
Текст в верхней части главной страницы администрирования (строка). По умолчанию это “Администрирование сайта”.
-
AdminSite.index_template -
Путь к пользовательскому шаблону, который будет использоваться основным представлением индекса сайта администрирования.
-
AdminSite.app_index_template -
Путь к пользовательскому шаблону, который будет использоваться представлением индекса приложений сайта администрирования.
-
AdminSite.login_template -
Путь к пользовательскому шаблону, который будет использоваться представлением входа на сайт администрирования.
-
AdminSite.login_form -
Подкласс
AuthenticationForm, который будет использоваться представлением входа на сайт администрирования.
-
AdminSite.logout_template -
Путь к пользовательскому шаблону, который будет использоваться представлением выхода с сайта администрирования.
-
AdminSite.password_change_template -
Путь к пользовательскому шаблону, который будет использоваться представлением смены пароля на сайте администрирования.
-
AdminSite.password_change_done_template -
Путь к пользовательскому шаблону, который будет использоваться представлением смены пароля на сайте администрирования (после изменения).
AdminSite методы
-
AdminSite.each_context(request)[source] -
Возвращает словарь переменных, которые необходимо поместить в контекст шаблона для каждой страницы на сайте администрирования.
По умолчанию включает следующие переменные и значения:
-
site_header:AdminSite.site_header -
site_title:AdminSite.site_title -
site_url:AdminSite.site_url -
has_permission:AdminSite.has_permission()
Аргумент
requestи переменнаяhas_permissionбыли добавлены. -
-
AdminSite.has_permission(request)[source] -
Возвращает
True, если у пользователя для данногоHttpRequestесть разрешение на просмотр хотя бы одной страницы на сайте администрирования. По умолчанию требует, чтобы обаUser.is_activeиUser.is_staffбылиTrue.
Подключение экземпляров AdminSite в ваш URLconf
Последний шаг в настройке Django администрирования — подключение вашего экземпляра AdminSite к вашему URLconf. Сделайте это, указав определённый URL на метод AdminSite.urls.
В этом примере мы регистрируем экземпляр AdminSite django.contrib.admin.site по адресу /admin/
# urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(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.conf.urls import include, url
from myapp.admin import admin_site
urlpatterns = [
url(r'^myadmin/', include(admin_site.urls)),
]
Обратите внимание, что вы можете не захотеть автоматического обнаружения модулей admin при использовании вашего собственного экземпляра AdminSite, так как вы, скорее всего, импортируете все модули admin по приложению в свой модуль myproject.admin. Это означает, что вам нужно поместить 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в настройку INSTALLED_APPS.
Несколько сайтов администрирования в одном URLconf
Создать несколько экземпляров сайта администрирования на одном веб-сайте Django легко. Просто создайте несколько экземпляров AdminSite и настройте каждый из них по разному URL.
В этом примере URL /basic-admin/ и /advanced-admin/ содержат отдельные версии сайта администрирования — используя экземпляры AdminSite myproject.admin.basic_site и myproject.admin.advanced_site соответственно:
# urls.py
from django.conf.urls import include, url
from myproject.admin import basic_site, advanced_site
urlpatterns = [
url(r'^basic-admin/', include(basic_site.urls)),
url(r'^advanced-admin/', include(advanced_site.urls)),
]
AdminSite экземпляры принимают один аргумент в свой конструктор — имя, которое может быть любым. Этот аргумент становится префиксом для имён URL для целей обращения к ним. Это необходимо только в том случае, если вы используете более одного AdminSite.
Добавление представлений в административные сайты
Так же, как и ModelAdmin, AdminSite предоставляет метод get_urls(), который можно переопределить для определения дополнительных представлений для сайта. Чтобы добавить новое представление в ваш административный сайт, расширьте базовый метод get_urls(), включив в него шаблон для вашего нового представления.
Примечание
Любое представление, которое вы отображаете с использованием административных шаблонов или расширяете базовый административный шаблон, должно установить request.current_app перед отображением шаблона. Оно должно быть установлено в self.name если ваше представление находится на AdminSite, или в self.admin_site.name если ваше представление находится на ModelAdmin.
В предыдущих версиях Django вам приходилось передавать аргумент current_app в RequestContext или Context при отображении шаблона.
Добавление функции сброса пароля
Вы можете добавить функцию сброса пароля в административный сайт, добавив несколько строк в свой URLconf. В частности, добавьте эти четыре шаблона:
from django.contrib.auth import views as auth_views url(r'^admin/password_reset/$', auth_views.password_reset, name='admin_password_reset'), url(r'^admin/password_reset/done/$', auth_views.password_reset_done, name='password_reset_done'), url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$', auth_views.password_reset_confirm, name='password_reset_confirm'), url(r'^reset/done/$', auth_views.password_reset_complete, 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 LogEntry, ADDITION LogEntry.objects.filter(action_flag=ADDITION)
-
LogEntry.change_message -
Подробное описание изменения. В случае редактирования, сообщение содержит список изменённых полей.
Методы
LogEntry
-
LogEntry.get_edited_object()[source] -
Удобный метод, возвращающий сохранённый объект.
Обращение к URL-адресам администратора
При развертывании AdminSite, предоставляемые этим сайтом представления доступны с помощью системы обратной связи Django систему обратной связи URL.
AdminSite предоставляет следующие именованные URL-шаблоны:
| Страница | Имя URL | Параметры |
|---|---|---|
| Главная страница | index | |
| Выход | logout | |
| Изменение пароля | password_change | |
| Изменение пароля завершено | password_change_done | |
| i18n JavaScript | jsi18n | |
| Страница индекса приложения | app_list | app_label |
| Перенаправление на страницу объекта | view_on_site |
content_type_id, object_id
|
Каждый экземпляр ModelAdmin предоставляет дополнительный набор именованных URL:
| Страница | Имя URL | Параметры |
|---|---|---|
| Список изменений | {{ app_label }}_{{ model_name }}_changelist | |
| Добавить | {{ app_label }}_{{ model_name }}_add | |
| История | {{ app_label }}_{{ model_name }}_history | object_id |
| Удалить | {{ app_label }}_{{ model_name }}_delete | object_id |
| Изменить | {{ app_label }}_{{ model_name }}_change | object_id |
Экземпляр UserAdmin предоставляет именованный URL:
| Страница | Имя URL | Параметры |
|---|---|---|
| Изменение пароля | auth_user_password_change | user_id |
Эти именованные URL зарегистрированы в пространстве имён приложения admin, а также в пространстве имён экземпляра, соответствующем имени экземпляра сайта.
Таким образом, если вы хотите получить ссылку на представление «Изменить» для определённого объекта Choice (из приложения «опросы») в стандартной админ-панели, вы должны вызвать:
>>> from django.core import urlresolvers
>>> c = Choice.objects.get(...)
>>> change_url = urlresolvers.reverse('admin:polls_choice_change', args=(c.id,))
Это найдёт первый зарегистрированный экземпляр приложения администратора (каково бы ни было имя экземпляра) и перенаправит на представление для изменения экземпляров poll.Choice в этом экземпляре.
Если вы хотите найти URL в конкретном экземпляре администратора, передайте имя этого экземпляра как подсказку current_app вызову обратной связи. Например, если вам нужен именно административный вид из экземпляра администратора под названием custom, вам нужно вызвать:
>>> change_url = urlresolvers.reverse('admin:polls_choice_change',
... args=(c.id,), current_app='custom')
Дополнительную информацию см. в документации по обращению к именованным URL в пространствах имён.
Для упрощения обращения к административным URL-адресам в шаблонах Django предоставляет фильтр admin_urlname , который принимает действие в качестве аргумента:
{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>
Действие в примерах выше соответствует последней части имён URL для экземпляров ModelAdmin, описанных выше. Переменная opts может быть любым объектом, имеющим атрибуты app_label и model_name, и обычно предоставляется представлениями администратора для текущей модели.
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/ref/contrib/admin/index/