Сайт администрирования 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/, по умолчанию). Если вам нужно создать пользователя для входа в систему, вы можете использовать команду createsuperuser.
Другие темы
- Действия администрирования
- Генератор документации Django admin
- Настройка JavaScript в администрировании
См. также
Дополнительную информацию о предоставлении статических файлов (изображения, 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
-
Декоратор
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в каждом установленных приложении. Такие модули должны регистрировать модели в администрировании.Как правило, вам не нужно вызывать эту функцию напрямую, так как
AdminConfigвызывает её при запуске Django.
Если вы используете пользовательский AdminSite, обычно импортируются все подклассы ModelAdmin в ваш код и регистрируются в пользовательском AdminSite. В этом случае, чтобы отключить автоматическое обнаружение, вы должны поместить 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в ваш параметр INSTALLED_APPS.
Параметры ModelAdmin
Класс ModelAdmin очень гибкий. У него есть несколько параметров для настройки интерфейса. Все параметры определены в подклассе ModelAdmin:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = 'pub_date'
-
Параметр
ModelAdmin.actions -
Список действий, которые нужно сделать доступными на странице списка изменений. Подробности см. в Действия администрирования.
-
ModelAdmin.actions_on_top
-
Параметр
ModelAdmin.actions_on_bottom -
Управляет, где на странице отображается панель действий. По умолчанию в списке изменений администрирования действия отображаются вверху страницы (
actions_on_top = True; actions_on_bottom = False).
-
ModelAdmin.actions_selection_counter -
Управляет отображением счетчика выделения рядом со списком действий. По умолчанию админ-список изменений будет отображать его (
actions_selection_counter = True).
-
ModelAdmin.date_hierarchy -
Установите
date_hierarchyв имя поляDateFieldилиDateTimeFieldв вашей модели, и страница списка изменений будет содержать навигацию по древовидной структуре по датам по этому полю.Пример:
date_hierarchy = 'pub_date'
Это будет интеллектуально заполняться на основе доступных данных, например, если все даты находятся в одном месяце, будет показана только навигация по дням.
Примечание
date_hierarchyиспользуетQuerySet.datetimes()внутри. Обратитесь к документации для некоторых оговорок, когда включена поддержка часовых поясов (USE_TZ = True).
-
ModelAdmin.empty_value_display -
Этот атрибут переопределяет значение по умолчанию для полей записей, которые пусты (
None, пустая строка и т. д.). Значение по умолчанию —-(тире). Например:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): empty_value_display = '-empty-'Вы также можете переопределить
empty_value_displayдля всех страниц администрирования с помощьюAdminSite.empty_value_displayили для определённых полей, как показано ниже:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): fields = ('name', 'title', 'view_birth_date') def view_birth_date(self, obj): return obj.birth_date view_birth_date.empty_value_display = '???'
-
ModelAdmin.exclude -
Этот атрибут, если задан, должен быть списком имён полей, которые нужно исключить из формы.
Например, рассмотрим следующую модель:
from django.db import models class Author(models.Model): name = models.CharField(max_length=100) title = models.CharField(max_length=3) birth_date = models.DateField(blank=True, null=True)Если вы хотите форму для модели
Author, которая включает только поляnameиtitle, вы бы указалиfieldsилиexcludeследующим образом:from django.contrib import admin class AuthorAdmin(admin.ModelAdmin): fields = ('name', 'title') class AuthorAdmin(admin.ModelAdmin): exclude = ('birth_date',)Поскольку модель Author имеет только три поля,
name,title, иbirth_date, формы, полученные из вышеприведенных объявлений, будут содержать ровно те же поля.
-
ModelAdmin.fields -
Используйте опцию
fieldsдля внесения простых изменений в макет форм на страницах «добавить» и «изменить», таких как отображение только подмножества доступных полей, изменение их порядка или группировка в строки. Например, вы можете определить упрощённую версию формы администрирования для моделиdjango.contrib.flatpages.models.FlatPageследующим образом:class FlatPageAdmin(admin.ModelAdmin): fields = ('url', 'title', 'content')В приведённом примере будут отображаться только поля
url,titleиcontent, последовательно, в форме.fieldsможет содержать значения, определённые вModelAdmin.readonly_fields, для отображения в режиме только для чтения.Для более сложных требований к макету см. опцию
fieldsets.Опция
fields, в отличие отlist_display, может содержать только имена полей в модели или в форме, указанной в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>в форме администрирования. (<fieldset>— это «раздел» формы.)Кортежи имеют формат
(name, field_options), гдеname— строка, представляющая заголовок набора полей, аfield_options— словарь информации о наборе полей, включая список полей, которые нужно отобразить в нём.Полный пример, взятый из модели
django.contrib.flatpages.models.FlatPage:from django.contrib import admin class FlatPageAdmin(admin.ModelAdmin): fieldsets = ( (None, { 'fields': ('url', 'title', 'content', 'sites') }), ('Advanced options', { 'classes': ('collapse',), 'fields': ('registration_required', 'template_name'), }), )Это приводит к странице администрирования, которая выглядит так:
Если ни опция
fieldsetsниfieldsне указаны, Django по умолчанию будет отображать каждое поле, которое не являетсяAutoFieldи имеетeditable=True, в отдельном наборе, в том же порядке, в котором поля определены в модели.Словарь
field_optionsможет содержать следующие ключи:-
-
fields -
Кортеж имён полей, которые нужно отобразить в этом наборе. Этот ключ обязателен.
Пример:
{ 'fields': ('first_name', 'last_name', 'address', 'city', 'state'), }Как и с опцией
fields, чтобы отобразить несколько полей в одной строке, оберните эти поля в свой кортеж. В этом примере поляfirst_nameиlast_nameбудут отображаться в одной строке:{ 'fields': (('first_name', 'last_name'), 'address', 'city', 'state'), }fieldsможет содержать значения, определённые вreadonly_fields, для отображения в режиме только для чтения.Если вы добавите имя вызываемого объекта в
fields, то применяется то же правило, что и с опциейfields: вызываемый объект должен быть перечислен вreadonly_fields.
-
-
-
classes -
Список или кортеж, содержащий дополнительные CSS-классы, которые необходимо применить к набору полей.
Пример:
{ 'classes': ('wide', 'extrapretty'), }Два полезных класса, определённых в стиле по умолчанию для сайта администрирования, —
collapseиwide. Наборы полей со стилемcollapseбудут изначально свёрнуты в админпанели и заменены небольшой ссылкой «нажать, чтобы развернуть». Наборы полей со стилем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,) -
Строка, представляющая атрибут в экземпляре модели. Это ведет себя также как вызываемый объект. Например:
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 по умолчанию экранирует вывод с помощью HTML. Чтобы экранировать пользовательский ввод и разрешить свои собственные неэкранированные теги, используйте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, ) class PersonAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'colored_name')Устаревшее с версии 1.9: В более старых версиях вы могли добавить атрибут
allow_tagsк методу, чтобы предотвратить автоматическое экранирование. Этот атрибут устарел, так как безопаснее использоватьformat_html(),format_html_join()илиmark_safe(). -
Если значение поля равно
None, пустой строке или итерируемому объекту без элементов, Django отобразит-(тире). Вы можете переопределить это с помощьюAdminSite.empty_value_display:from django.contrib import admin admin.site.empty_value_display = '(None)'
Вы также можете использовать
ModelAdmin.empty_value_display:class PersonAdmin(admin.ModelAdmin): empty_value_display = 'unknown'Или на уровне поля:
class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'birth_date_view') def birth_date_view(self, obj): return obj.birth_date birth_date_view.empty_value_display = 'unknown'Добавлена возможность настройки
empty_value_display. -
Если указанная строка является методом модели,
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.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 = None - Установите его в значение
-
ModelAdmin.list_editable -
Установите
list_editableв список имён полей модели, которые позволят редактировать их на странице списка изменений. То есть, поля, указанные вlist_editable, будут отображаться как виджеты форм на странице списка изменений, позволяя пользователям редактировать и сохранять несколько строк одновременно.Примечание
list_editableвзаимодействует с несколькими другими параметрами особым образом; вы должны учесть следующие правила:- Любое поле в
list_editableтакже должно быть вlist_display. Вы не можете редактировать поле, которое не отображается! - Одно и то же поле не может быть указано как в
list_editable, так и вlist_display_links— поле не может быть одновременно формой и ссылкой.
В случае нарушения этих правил будет выдано сообщение об ошибке валидации.
- Любое поле в
-
ModelAdmin.list_filter -
Установите
list_filterдля активации фильтров в правой боковой панели страницы списка изменений админки, как показано на следующем снимке экрана:
list_filterдолжен быть списком или кортежем элементов, где каждый элемент должен быть одного из следующих типов:-
имя поля, где указанное поле должно быть либо
BooleanField,CharField,DateField,DateTimeField,IntegerField,ForeignKeyилиManyToManyField, например:class PersonAdmin(admin.ModelAdmin): list_filter = ('is_staff', 'company')Имена полей в
list_filterтакже могут охватывать связи, используя__поиск, например:class PersonAdmin(admin.UserAdmin): list_filter = ('company__name',) -
класс, унаследованный от
django.contrib.admin.SimpleListFilter, которому вы должны предоставить атрибутыtitleиparameter_nameи переопределить методыlookupsиqueryset, например:from datetime import date from django.contrib import admin from django.utils.translation import 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').Если вам нужно указать динамическое значение, основанное на запросе, вы можете реализовать метод
get_list_select_related().
-
ModelAdmin.ordering -
Установите
orderingдля указания того, как списки объектов должны упорядочиваться в представлениях админки Django. Это должен быть список или кортеж в том же формате, что и параметрorderingмодели.Если этот параметр не указан, админка Django будет использовать порядок по умолчанию модели.
Если вам нужно указать динамический порядок (например, в зависимости от пользователя или языка), вы можете реализовать метод
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полей из одного или нескольких других полей. Сгенерированное значение получается путём конкатенации значений исходных полей, а затем преобразованием этого результата в корректный «сlag» (например, замены пробелов дефисами).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 mark_safe("<span class='errors'>I can't determine this address.</span>") # short_description functions like a model field's verbose_name address_report.short_description = "Address"
-
ModelAdmin.save_as -
Установите
save_asдля включения функции «сохранить как новый» в формах изменения администратора.Обычно объекты имеют три варианта сохранения: «Сохранить», «Сохранить и продолжить редактирование» и «Сохранить и добавить другой». Если
save_asимеет значениеTrue, «Сохранить и добавить другой» будет заменено кнопкой «Сохранить как новый», которая создает новый объект (с новым идентификатором) вместо обновления существующего объекта.По умолчанию
save_asимеет значениеFalse.
-
ModelAdmin.save_on_top -
Установите
save_on_topдля добавления кнопок сохранения в верхней части форм изменения администратора.Обычно кнопки сохранения отображаются только внизу форм. Если вы установите
save_on_top, кнопки будут отображаться как вверху, так и внизу.По умолчанию
save_on_topимеет значениеFalse.
-
ModelAdmin.search_fields -
Установите
search_fieldsдля включения поля поиска на странице списка изменений администратора. Это должно быть установлено в список имён полей, которые будут проиндексированы при вводе пользователем запроса в это поле.Эти поля должны быть какими-то текстовыми полями, например
CharFieldилиTextField. Вы также можете выполнить связанный поиск поForeignKeyилиManyToManyFieldс помощью нотации API поиска «follow»: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): url = reverse('person-detail', kwargs={'slug': obj.slug}) return 'https://example.com' + url
Дополнительные параметры шаблонов
В разделе Замена шаблонов административной панели описано, как переопределять или расширять стандартные шаблоны администратора. Используйте следующие параметры для переопределения стандартных шаблонов, используемых представлениями ModelAdmin:
-
ModelAdmin.add_form_template -
Путь к пользовательскому шаблону, используемому
add_view().
-
ModelAdmin.change_form_template -
Путь к пользовательскому шаблону, используемому
change_view().
-
ModelAdmin.change_list_template -
Путь к пользовательскому шаблону, используемому
changelist_view().
-
ModelAdmin.delete_confirmation_template -
Путь к пользовательскому шаблону, используемому
delete_view()для отображения страницы подтверждения при удалении одного или нескольких объектов.
-
ModelAdmin.delete_selected_confirmation_template -
Путь к пользовательскому шаблону, используемому методом действия
delete_selectedдля отображения страницы подтверждения при удалении одного или нескольких объектов. См. документацию по действиям.
-
ModelAdmin.object_history_template -
Путь к пользовательскому шаблону, используемому
history_view().
Методы ModelAdmin
Предупреждение
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во втором элементе возвращаемого значения.Например, чтобы выполнить поиск по
nameиage, можно использовать:class PersonAdmin(admin.ModelAdmin): list_display = ('name', 'age') search_fields = ('name',) def get_search_results(self, request, queryset, search_term): queryset, use_distinct = super(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Эта реализация более эффективна, чем
search_fields = ('name', '=age'), которая приводит к сравниванию строк для числового поля, например... OR UPPER("polls_choice"."votes"::text) = UPPER('4')в PostgreSQL.
-
Метод
save_relatedполучаетHttpRequest, родительский экземплярModelForm, список inline formset и булево значение, указывающее на добавление или изменение родительского объекта. Здесь вы можете выполнять любые предоперации или послеоперации сохранения для объектов, связанных с родителем. Обратите внимание, что на этом этапе родительский объект и его форма уже сохранены.
-
ModelAdmin.get_readonly_fields(request, obj=None) -
Метод
get_readonly_fieldsполучаетHttpRequestиobjредактируемого объекта (илиNoneна форме добавления) и должен возвращатьlistилиtupleимён полей, которые будут отображаться как только для чтения, как описано выше в разделеModelAdmin.readonly_fields.
-
ModelAdmin.get_prepopulated_fields(request, obj=None) -
Метод
get_prepopulated_fieldsполучаетHttpRequestиobjредактируемого объекта (илиNoneна форме добавления) и должен возвращатьdictionary, как описано выше в разделеModelAdmin.prepopulated_fields.
-
ModelAdmin.get_list_display(request)[source] -
Метод
get_list_displayполучаетHttpRequestи должен возвращатьlistилиtupleимён полей, которые будут отображаться на странице списка изменений, как описано в разделеModelAdmin.list_display.
-
ModelAdmin.get_list_display_links(request, list_display)[source] -
Метод
get_list_display_linksполучаетHttpRequestиlistилиtuple, возвращённые методомModelAdmin.get_list_display(). Он должен вернуть либоNone, либоlistилиtupleимён полей на странице списка, которые будут связаны со страницей изменения, как описано в разделеModelAdmin.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на форме добавления) и должен вернуть список пар кортежей, где каждая пара кортежей представляет собой<fieldset>на странице администрирования формы, как описано выше в разделеModelAdmin.fieldsets.
-
ModelAdmin.get_list_filter(request)[source] -
Метод
get_list_filterполучаетHttpRequestи должен вернуть тот же тип последовательности, что и атрибутlist_filter.
-
Метод
get_list_select_relatedполучаетHttpRequestи должен вернуть булево значение или список, как и атрибутModelAdmin.list_select_related.
-
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. Например, следующее вернёт встраиваемые элементы без фильтрации по умолчанию, основанной на разрешениях добавления, изменения и удаления:class MyModelAdmin(admin.ModelAdmin): inlines = (MyInline,) def get_inline_instances(self, request, obj=None): return [inline(self.model, self.admin_site) for inline in self.inlines]Если вы переопределяете этот метод, убедитесь, что возвращаемые встраиваемые элементы являются экземплярами классов, определённых в
inlines, иначе при добавлении связанных объектов может возникнуть ошибка «Bad Request».
-
ModelAdmin.get_urls()[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имеют атрибутmodel_admin. Другие представленияAdminSiteимеют атрибутadmin_site.
-
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_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, если редактирование obj разрешено,Falseв противном случае. Если obj являетсяNone, должно возвращатьTrueилиFalseдля указания разрешения на редактирование объектов данного типа в целом (например,Falseбудет интерпретироваться как означающее, что текущему пользователю не разрешено редактировать ни один объект данного типа).
-
ModelAdmin.has_delete_permission(request, obj=None) -
Должно возвращать
Trueесли удаление obj разрешено,Falseв противном случае. Если obj являетсяNone, должно возвращатьTrueилиFalseдля указания разрешения на удаление объектов данного типа в целом (например,Falseбудет интерпретироваться как означающее, что текущему пользователю не разрешено удалять ни один объект данного типа).
-
ModelAdmin.has_module_permission(request) -
Должно возвращать
Trueесли отображение модуля на странице индекса администрирования и доступ к странице индекса модуля разрешены,Falseв противном случае. ИспользуетUser.has_module_perms()по умолчанию. Переопределение не ограничивает доступ к страницам добавления, изменения или удаления,has_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. См. пример custom 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().response_addвызывается после отправки формы администрирования и сразу после создания и сохранения объекта и всех связанных экземпляров. Вы можете переопределить его, чтобы изменить стандартное поведение после создания объекта.
-
ModelAdmin.response_change(request, obj)[source] -
Определяет
HttpResponseдля стадииchange_view().response_changeвызывается после отправки формы администрирования и сразу после сохранения объекта и всех связанных экземпляров. Вы можете переопределить его, чтобы изменить стандартное поведение после изменения объекта.
-
ModelAdmin.response_delete(request, obj_display, obj_id)[source] -
Определяет
HttpResponseдля стадииdelete_view().response_deleteвызывается после удаления объекта. Вы можете переопределить его, чтобы изменить стандартное поведение после удаления объекта.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-адресов приложения администрирования для отображения страниц, связанных с операциями CRUD над экземплярами моделей. В результате полное переопределение этих методов существенно изменит поведение приложения администрирования.
Одной из распространённых причин переопределения этих методов является добавление данных контекста, предоставляемых шаблону, который отображает представление. В следующем примере представление изменения переопределяется, чтобы предоставленный рендеринг шаблона содержал некоторые дополнительные данные сопоставления, которые в противном случае недоступны:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
# ...
pass
def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['osm_data'] = self.get_osm_info()
return super(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 использует библиотеку jQuery.
Чтобы избежать конфликтов с пользовательскими скриптами или библиотеками, jQuery Django (версия 2.1.4) имеет пространство имён django.jQuery. Если вы хотите использовать jQuery в собственном JavaScript админки без включения второй копии, можете использовать объект django.jQuery в представлениях списка изменений и добавления/редактирования.
Встроенная библиотека jQuery была обновлена с 1.9.1 до 1.11.2.
Встроенная библиотека jQuery была обновлена с 1.11.2 до 2.1.4. Это означает потерю поддержки Internet Explorer 8 и ниже. Вы можете восстановить поддержку, включив собственную версию jQuery 1.X.
Класс ModelAdmin по умолчанию требует jQuery, поэтому нет необходимости добавлять jQuery в список ресурсов медиа вашего ModelAdmin, если нет особой необходимости. Например, если требуется, чтобы библиотека jQuery находилась в глобальном пространстве имён (например, при использовании сторонних плагинов jQuery) или если вам нужна более новая версия jQuery, придётся включить собственную копию.
Django предоставляет как нескомпрессированные, так и «скомпрессированные» версии jQuery, как jquery.js и jquery.min.js соответственно.
ModelAdmin и InlineModelAdmin имеют свойство media, которое возвращает список объектов Media, хранящих пути к файлам JavaScript для форм и/или наборов форм. Если DEBUG имеет значение True, будет возвращена нескомпрессированная версия различных файлов JavaScript, включая jquery.js; в противном случае — «скомпрессированная» версия.
Добавление кастомной валидации в админку
Добавление кастомной валидации данных в админке очень просто. Автоматический интерфейс админки использует django.forms, а класс ModelAdmin позволяет определить собственную форму:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
MyArticleAdminForm можно определить где угодно, при условии импорта по мере необходимости. Теперь внутри вашей формы вы можете добавить собственную кастомную валидацию для любого поля:
class MyArticleAdminForm(forms.ModelForm):
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]
Важно использовать здесь метод ModelForm, в противном случае могут возникнуть ошибки. См. документацию по формам форм по кастомной валидации и, более конкретно, примечания к валидации форм моделей для получения дополнительной информации.
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, on_delete=models.CASCADE) title = models.CharField(max_length=100)
Вы можете редактировать книги, написанные автором, на странице автора. Вы добавляете встраиваемые объекты в модель, указав их в
ModelAdmin.inlines:from django.contrib import admin class BookInline(admin.TabularInline): model = Book class AuthorAdmin(admin.ModelAdmin): inlines = [ BookInline, ]Django предоставляет два подкласса
InlineModelAdmin:Разница между ними заключается только в шаблоне, используемом для их отображения.
InlineModelAdmin опции
InlineModelAdmin разделяет многие функции с ModelAdmin, и добавляет свои собственные (общие функции фактически определены в суперклассе BaseModelAdmin). Общие функции:
formfieldsetsfieldsformfield_overridesexcludefilter_horizontalfilter_verticalorderingprepopulated_fieldsget_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 -
Это управляет количеством дополнительных форм, которые будет отображать formset помимо начальных форм. Для получения дополнительной информации см. документацию по formsets.
Для пользователей с браузерами, поддерживающими 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, on_delete=models.CASCADE, related_name="friends")
from_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="from_friends")
Если вы хотите отобразить строку на страницах добавления/изменения админки Person, вам необходимо явно определить внешний ключ, так как это невозможно сделать автоматически:
from django.contrib import admin
from myapp.models import Friendship
class FriendshipInline(admin.TabularInline):
model = Friendship
fk_name = "to_person"
class PersonAdmin(admin.ModelAdmin):
inlines = [
FriendshipInline,
]
Работа с моделями многие-ко-многим
По умолчанию админ-виджеты для отношений многие-ко-многим будут отображаться на той модели, которая содержит фактическую ссылку на ManyToManyField. В зависимости от определения вашей ModelAdmin, каждое поле многие-ко-многим в вашей модели будет представлено стандартным HTML-<select multiple>, горизонтальным или вертикальным фильтром, или виджетом raw_id_admin. Однако также возможно заменить эти виджеты строками.
Предположим, что у нас есть следующие модели:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, related_name='groups')
Если вы хотите отобразить отношения многие-ко-многим с помощью строки, вы можете сделать это, определив объект InlineModelAdmin для отношения:
from django.contrib import admin
class MembershipInline(admin.TabularInline):
model = Group.members.through
class PersonAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
class GroupAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
exclude = ('members',)
В этом примере есть две особенности, которые стоит отметить.
Во-первых, класс MembershipInline ссылается на Group.members.through. Атрибут through — это ссылка на модель, которая управляет отношением многие-ко-многим. Эта модель автоматически создается Django при определении поля многие-ко-многим.
Во-вторых, необходимо вручную исключить поле members. Django отображает админ-виджет для поля многие-ко-многим на модели, которая определяет отношение (в данном случае, Group). Если вы хотите использовать строку модели для представления отношения многие-ко-многим, вы должны сообщить админке Django, чтобы не отображать этот виджет — в противном случае у вас будет два виджета на странице админки для управления отношением.
Обратите внимание, что при использовании этого метода сигналы m2m_changed не срабатывают. Это потому, что, насколько это касается админки, through — это просто модель с двумя внешними ключами, а не отношением многие-ко-многим.
Во всех остальных отношениях InlineModelAdmin точно такая же, как любая другая. Вы можете настроить ее внешний вид с помощью любого из обычных свойств ModelAdmin.
Работа с промежуточными моделями многие-ко-многим
При указании промежуточной модели с помощью аргумента through к ManyToManyField, админка не будет отображать виджет по умолчанию. Это потому, что каждый экземпляр такой промежуточной модели требует большей информации, чем можно отобразить в одном виджете, а макет, необходимый для нескольких виджетов, будет различаться в зависимости от промежуточной модели.
Однако мы все равно хотим иметь возможность редактировать эту информацию в строке. К счастью, это легко сделать с помощью строчных моделей админки. Предположим, что у нас есть следующие модели:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Первым шагом в отображении этой промежуточной модели в админке является определение класса строки для модели Membership:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
Этот простой пример использует значения InlineModelAdmin по умолчанию для модели Membership и ограничивает дополнительные формы добавления одной. Это можно настроить с помощью любого из вариантов, доступных для классов InlineModelAdmin.
Теперь создайте админ-виджеты для моделей Person и Group:
class PersonAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
Наконец, зарегистрируйте ваши модели Person и Group в сайте админки:
admin.site.register(Person, PersonAdmin) admin.site.register(Group, GroupAdmin)
Теперь ваш сайт админки настроен для редактирования объектов Membership в строке с любой страницы добавления/изменения Person или страницы подробностей Group.
Использование универсальных отношений в качестве строки
Возможно использование строки с универсально связанными объектами. Предположим, что у вас есть следующие модели:
from django.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, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
class Product(models.Model):
name = models.CharField(max_length=100)
Если вы хотите разрешить редактирование и создание экземпляра Image на Product, добавлять/изменять представления, вы можете использовать GenericTabularInline или GenericStackedInline (оба являются подклассами GenericInlineModelAdmin), предоставленными admin. Они реализуют табличный и сточный визуальные макеты для форм, представляющих встроенные объекты, соответственно, так же, как и их не-обобщенные аналоги. Они ведут себя как любые другие встроенные объекты. В вашем admin.py для этого примера приложения:
from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline
from myproject.myapp.models import Image, Product
class ImageInline(GenericTabularInline):
model = Image
class ProductAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Product, ProductAdmin)
См. документацию по contenttypes для более подробной информации.
Переопределение шаблонов администрирования
Относительно легко переопределить многие шаблоны, которые модуль администрирования использует для генерации различных страниц сайта администрирования. Вы даже можете переопределить некоторые из этих шаблонов для определенного приложения или определенной модели.
Настройка каталогов шаблонов администрирования проекта
Файлы шаблонов администрирования находятся в каталоге 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конструктору. Это имя экземпляра используется для идентификации экземпляра, особенно при обращении к URL-адресам администрирования. Если имя экземпляра не указано, используется имя экземпляра по умолчаниюadmin. См. Настройка класса AdminSite для примера настройки классаAdminSite.
AdminSite атрибуты
Шаблоны могут переопределить или расширить базовые шаблоны администрирования, как описано в Переопределении шаблонов администрирования.
-
AdminSite.site_header -
Текст, отображаемый вверху каждой страницы администрирования, как
<h1>(строка). По умолчанию это «Django администрирование».
-
AdminSite.site_title -
Текст, отображаемый в конце
<title>каждой страницы администрирования (строка). По умолчанию это «Django сайт администрирования».
-
AdminSite.site_url -
URL для ссылки «Просмотреть сайт» в верхней части каждой страницы администрирования. По умолчанию
site_urlэто/. Установите его вNoneдля удаления ссылки.
-
AdminSite.index_title -
Текст, отображаемый вверху страницы индекса администрирования (строка). По умолчанию это «Администрирование сайта».
-
AdminSite.index_template -
Путь к пользовательскому шаблону, который будет использоваться основным представлением индекса сайта администрирования.
-
AdminSite.app_index_template -
Путь к пользовательскому шаблону, который будет использоваться представлением индекса приложения сайта администрирования.
-
AdminSite.empty_value_display -
Строка, используемая для отображения пустых значений в списке изменений сайта администрирования. По умолчанию тире. Значение также может быть переопределено для каждой
ModelAdminи для пользовательского поля вModelAdminпутем установки атрибутаempty_value_displayдля поля. См.ModelAdmin.empty_value_displayдля примеров.
-
AdminSite.login_template -
Путь к пользовательскому шаблону, который будет использоваться представлением входа сайта администрирования.
-
AdminSite.login_form -
Подкласс
AuthenticationForm, который будет использоваться представлением входа сайта администрирования.
-
AdminSite.logout_template -
Путь к пользовательскому шаблону, который будет использоваться представлением выхода сайта администрирования.
-
AdminSite.password_change_template -
Путь к пользовательскому шаблону, который будет использоваться представлением изменения пароля сайта администрирования.
-
AdminSite.password_change_done_template -
Путь к пользовательскому шаблону, который будет использоваться представлением завершения изменения пароля сайта администрирования.
AdminSite методы
-
AdminSite.each_context(request)[source] -
Возвращает словарь переменных для контекста шаблона каждой страницы в админской панели.
По умолчанию включает следующие переменные и значения:
-
site_header:AdminSite.site_header -
site_title:AdminSite.site_title -
site_url:AdminSite.site_url -
has_permission:AdminSite.has_permission() -
available_apps: список приложений из реестра приложений, доступных текущему пользователю. Каждый элемент списка — словарь, представляющий приложение со следующими ключами:-
app_label: метка приложения -
app_url: URL страницы индекса приложения в админке -
has_module_perms: логическое значение, указывающее, разрешено ли отображение и доступ к странице индекса модуля для текущего пользователя -
models: список моделей, доступных в приложении
Каждая модель — словарь со следующими ключами:
-
object_name: имя класса модели -
name: множественное число имени модели -
perms: отслеживаниеdict,add, иchangeразрешений -
admin_url: URL админского списка изменений для модели -
add_url: админский URL для добавления новой записи модели
-
Были добавлены аргумент
requestи переменнаяhas_permission.Была добавлена переменная
available_apps. -
-
AdminSite.has_permission(request)[source] -
Возвращает
True, если у пользователя для данногоHttpRequestесть разрешение на просмотр хотя бы одной страницы в админской панели. По умолчанию требуется, чтобы какUser.is_active, так иUser.is_staffбылиTrue.
Подключение экземпляров AdminSite в ваш URLconf
Последний шаг настройки Django админки — подключение вашего экземпляра AdminSite в ваш URLconf. Для этого укажите данный URL на метод AdminSite.urls. Использование include() не обязательно.
В этом примере, мы регистрируем стандартный экземпляр AdminSite django.contrib.admin.site по URL /admin/
# urls.py
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
В предыдущих версиях вы передавали admin.site.urls в include().
Настройка класса 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 url
from myapp.admin import admin_site
urlpatterns = [
url(r'^myadmin/', 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 url
from myproject.admin import basic_site, advanced_site
urlpatterns = [
url(r'^basic-admin/', basic_site.urls),
url(r'^advanced-admin/', 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() -
Сокращение, возвращающее ссылку на объект.
Обращение к админским URL
При развертывании AdminSite, представленные им представления доступны с помощью системы обратной ссылки на URL 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 (из приложения polls) в стандартном администрировании, вы должны вызвать:
>>> 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, обычно предоставляемые представлениями администрирования для текущей модели.
Декоратор staff_member_required
-
staff_member_required(redirect_field_name='next', login_url='admin:login')[source] -
Этот декоратор используется для представлений администрирования, требующих авторизации. Представление, декорированное этой функцией, будет работать следующим образом:
- Если пользователь авторизован, является сотрудником (
User.is_staff=True) и активен (User.is_active=True), представление выполняется нормально. - В противном случае запрос перенаправляется на URL, указанный параметром
login_url, с исходным запрошенным путем в переменной строки запроса, указанной вredirect_field_name. Например:/admin/login/?next=/admin/polls/question/3/.
Пример использования:
from django.contrib.admin.views.decorators import staff_member_required @staff_member_required def my_view(request): ... - Если пользователь авторизован, является сотрудником (
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.9/ref/contrib/admin/index/