Spec-Zone.ru › Django 4.1

Система администрирования Django

Одна из самых мощных частей Django — это автоматический интерфейс администрирования. Он считывает метаданные из ваших моделей, чтобы предоставить быстрый, ориентированный на модели интерфейс, где авторизованные пользователи могут управлять контентом на вашем сайте. Рекомендуемое использование админки ограничено внутренним инструментом управления организации. Она не предназначена для построения всего вашего фронтенда вокруг неё.

Админка имеет много возможностей для настройки, но будьте осторожны, пытаясь использовать эти возможности исключительно. Если вам нужно предоставить более ориентированный на процесс интерфейс, абстрагирующий детали реализации таблиц и полей базы данных, то, вероятно, пришло время написать свои собственные представления.

В этом документе мы обсудим, как активировать, использовать и настраивать интерфейс администрирования Django.

Обзор

Админка включена в шаблон проекта по умолчанию, используемый startproject.

Если вы не используете шаблон проекта по умолчанию, вот требования:

  1. Добавьте 'django.contrib.admin' и его зависимости — django.contrib.auth, django.contrib.contenttypes, django.contrib.messages и django.contrib.sessions — в ваше значение INSTALLED_APPS.
  2. Настройте DjangoTemplates бэкенд в вашем значении TEMPLATES с django.template.context_processors.request, django.contrib.auth.context_processors.auth, и django.contrib.messages.context_processors.messages в опции 'context_processors' OPTIONS.
  3. Если вы настроили значение MIDDLEWARE, django.contrib.auth.middleware.AuthenticationMiddleware и django.contrib.messages.middleware.MessageMiddleware должны быть включены.
  4. Подключите URL-адреса админки к вашему URLconf.

После выполнения этих шагов вы сможете использовать сайт администрирования, перейдя по URL-адресу, к которому вы его подключили (/admin/, по умолчанию).

Если вам нужно создать пользователя для входа, используйте команду createsuperuser. По умолчанию для входа в админку требуется, чтобы у пользователя было значение атрибута is_staff равным True.

Наконец, определите, модели каких приложений должны быть редактируемы в интерфейсе администрирования. Для каждой такой модели зарегистрируйте её в админке, как описано в ModelAdmin.

Другие темы

  • Действия в админке
  • ModelAdmin Фильтры списков
  • Генератор документации Django admin
  • Настройка JavaScript в админке

См. также

Для получения информации об обслуживании статических файлов (изображения, JavaScript и CSS), связанных с админкой в производственной среде, см. Обслуживание файлов.

Возникли проблемы? Обратитесь к FAQ: Админка.

ModelAdmin объекты

class ModelAdmin

Класс ModelAdmin представляет модель в интерфейсе администрирования. Обычно они хранятся в файле с именем admin.py в вашем приложении. Давайте рассмотрим пример ModelAdmin:

from django.contrib import admin
from myapp.models import Author

class AuthorAdmin(admin.ModelAdmin):
    pass
admin.site.register(Author, AuthorAdmin)

Нужен ли вам объект ModelAdmin?

В приведённом примере класс ModelAdmin не определяет никаких пользовательских значений (ещё). В результате, будет предоставлен интерфейс администрирования по умолчанию. Если вас устраивает интерфейс администрирования по умолчанию, вам не нужно определять объект ModelAdmin вообще — вы можете зарегистрировать класс модели без указания описания ModelAdmin. Предыдущий пример можно упростить до:

from django.contrib import admin
from myapp.models import Author

admin.site.register(Author)

Декоратор register

register(*models, site=django.contrib.admin.sites.site)

Также есть декоратор для регистрации ваших классов ModelAdmin:

from django.contrib import admin
from .models import Author

@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
    pass

Он принимает один или несколько классов моделей для регистрации в ModelAdmin. Если вы используете пользовательскую AdminSite, передайте её с помощью ключевого аргумента site:

from django.contrib import admin
from .models import Author, Editor, Reader
from myproject.admin_site import custom_admin_site

@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
    pass

Вы не можете использовать этот декоратор, если вам нужно сослаться на класс вашей модели администрирования в методе __init__() , например super(PersonAdmin, self).__init__(*args, **kwargs). Вы можете использовать super().__init__(*args, **kwargs).

Обнаружение файлов админки

Когда вы помещаете 'django.contrib.admin' в ваше значение INSTALLED_APPS, Django автоматически ищет модуль admin в каждом приложении и импортирует его.

class apps.AdminConfig

Это класс AppConfig по умолчанию для админки. Он вызывает autodiscover() при запуске Django.

class apps.SimpleAdminConfig

Этот класс работает как AdminConfig, за исключением того, что он не вызывает autodiscover().

default_site

Путь импорта к классу сайта администрирования по умолчанию или вызываемому объекту, который возвращает экземпляр сайта. По умолчанию 'django.contrib.admin.sites.AdminSite'. См. Переопределение сайта администрирования по умолчанию для использования.

autodiscover()

Эта функция пытается импортировать модуль admin в каждом установленным приложении. Такие модули ожидают регистрации моделей в админке.

Как правило, вам не нужно вызывать эту функцию напрямую, так как AdminConfig вызывает её при запуске Django.

Если вы используете пользовательский AdminSite, обычно импортируются все подклассы ModelAdmin в ваш код и регистрируются в пользовательском AdminSite. В этом случае, чтобы отключить автоматическое обнаружение, вы должны поместить 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в ваше значение INSTALLED_APPS.

ModelAdmin опции

Класс ModelAdmin очень гибкий. Он имеет несколько опций для настройки интерфейса. Все опции определяются в подклассе ModelAdmin:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
    date_hierarchy = 'pub_date'
ModelAdmin.actions

Список действий, которые должны быть доступны на странице списка изменений. См. Действия в админке для получения подробностей.

ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom

Управляет, где на странице отображается панель действий. По умолчанию, страница списка изменений админки отображает действия в верхней части страницы (actions_on_top = True; actions_on_bottom = False).

ModelAdmin.actions_selection_counter

Управляет отображением счётчика выделенных элементов рядом с раскрывающимся списком действий. По умолчанию, страница списка изменений админки отображает его (actions_selection_counter = True).

ModelAdmin.date_hierarchy

Установите date_hierarchy в имя DateField или DateTimeField в вашей модели, и страница списка изменений будет включать навигацию с древовидным просмотром по датам по этому полю.

Пример:

date_hierarchy = 'pub_date'

Вы также можете указать поле в связанной модели, используя поиск __, например:

date_hierarchy = 'author__pub_date'

Это будет интеллектуально заполняться на основе доступных данных, например, если все даты находятся в одном месяце, будет показан только древовидный просмотр по дням.

Примечание

date_hierarchy использует QuerySet.datetimes() в качестве внутренней функции. Обратитесь к документации по возможным нюансам, когда включена поддержка часовых поясов (USE_TZ = True).

ModelAdmin.empty_value_display

Этот атрибут переопределяет значение по умолчанию для полей записей, которые пусты (None, пустая строка и т. п.). Значение по умолчанию — - (тире). Например:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
    empty_value_display = '-empty-'

Вы также можете переопределить empty_value_display для всех страниц администрирования с помощью AdminSite.empty_value_display или для определённых полей так:

from django.contrib import admin

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('name', 'title', 'view_birth_date')

    @admin.display(empty_value='???')
    def view_birth_date(self, obj):
        return obj.birth_date
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, за исключением того, что вызовы функций не принимаются. Имена методов модели и модели администрирования будут использоваться только в том случае, если они перечислены в readonly_fields.

Для отображения нескольких полей в одной строке оберните эти поля в свои собственные кортежи. В этом примере поля url и title будут отображаться в одной строке, а поле content будет отображаться под ними в отдельной строке:

class FlatPageAdmin(admin.ModelAdmin):
    fields = (('url', 'title'), 'content')

Примечание

Эта опция fields не следует путать с ключом словаря fields, который находится внутри опции fieldsets, как описано в следующей секции.

Если ни опция fields ни fieldsets не присутствуют, Django по умолчанию будет отображать каждое поле, которое не является AutoField и имеет editable=True, в одной группе полей в том же порядке, что и в определении модели.

ModelAdmin.fieldsets

Установите fieldsets для управления макетом страниц администрирования «добавить» и «изменить».

fieldsets представляет собой список пар кортежей, в котором каждая пара кортежей представляет собой <fieldset> на странице формы администрирования. (Группа полей — это «раздел» формы.)

Двухэлементные кортежи имеют формат (name, field_options), где name — строка, представляющая заголовок группы полей, а field_options — словарь с информацией о группе полей, включая список полей, которые будут отображаться в ней.

Полный пример, взятый из модели django.contrib.flatpages.models.FlatPage:

from django.contrib import admin

class FlatPageAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {
            'fields': ('url', 'title', 'content', 'sites')
        }),
        ('Advanced options', {
            'classes': ('collapse',),
            'fields': ('registration_required', 'template_name'),
        }),
    )

Это приводит к странице администрирования, которая выглядит следующим образом:

../../../_images/fieldsets.png

Если ни опция 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.contrib import admin
from django.db import models

# Import our custom widget and our model from where they're defined
from myapp.models import MyModel
from myapp.widgets import RichTextEditorWidget

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.TextField: {'widget': RichTextEditorWidget},
    }

Обратите внимание, что ключом в словаре является фактический класс поля, а не строка. Значением является другой словарь; эти аргументы будут переданы методу __init__() поля формы. См. API форм для получения дополнительных сведений.

Предупреждение

Если вы хотите использовать пользовательский виджет с полем отношения (т. е. ForeignKey или ManyToManyField), убедитесь, что вы не включили имя этого поля в raw_id_fields, radio_fields, или autocomplete_fields.

formfield_overrides не позволит вам изменить виджет в полях отношения, для которых raw_id_fields, radio_fields, или autocomplete_fields установлены. Это потому, что raw_id_fields, radio_fields, и autocomplete_fields подразумевают свои собственные пользовательские виджеты.

ModelAdmin.inlines

См. объекты InlineModelAdmin ниже, а также ModelAdmin.get_formsets_with_inlines().

ModelAdmin.list_display

Установите list_display для управления полями, отображаемыми на странице списка изменений админки.

Пример:

list_display = ('first_name', 'last_name')

Если вы не установите list_display, админка отобразит один столбец, показывающий __str__() представление каждого объекта.

В list_display можно использовать четыре типа значений. Все, кроме самых простых, могут использовать декоратор display(), который используется для настройки отображения поля:

  • Имя поля модели. Например:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'last_name')
    
  • Вызываемый объект, принимающий один аргумент — экземпляр модели. Например:

    @admin.display(description='Name')
    def upper_case_name(obj):
        return ("%s %s" % (obj.first_name, obj.last_name)).upper()
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = (upper_case_name,)
    
  • Строка, представляющая метод ModelAdmin, принимающий один аргумент — экземпляр модели. Например:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ('upper_case_name',)
    
        @admin.display(description='Name')
        def upper_case_name(self, obj):
            return ("%s %s" % (obj.first_name, obj.last_name)).upper()
    
  • Строка, представляющая атрибут или метод модели (без необходимых аргументов). Например:

    from django.contrib import admin
    from django.db import models
    
    class Person(models.Model):
        name = models.CharField(max_length=50)
        birthday = models.DateField()
    
        @admin.display(description='Birth decade')
        def decade_born_in(self):
            return '%d’s' % (self.birthday.year // 10 * 10)
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'decade_born_in')
    

Несколько особых случаев относительно list_display:

  • Если поле является ForeignKey, Django отобразит __str__() связанного объекта.
  • ManyToManyField поля не поддерживаются, потому что это потребует выполнения отдельного SQL-запроса для каждой строки в таблице. Если вы хотите это сделать всё равно, добавьте в вашу модель пользовательский метод и укажите имя этого метода в list_display. (Подробности о пользовательских методах в list_display см. ниже.)
  • Если поле является BooleanField, Django отобразит значок «да», «нет» или «неизвестно» вместо True, False, или None.
  • Если заданная строка — метод модели, ModelAdmin или вызываемый объект, Django по умолчанию HTML-экранирует вывод. Чтобы экранировать пользовательский ввод и разрешить собственные неэкранированные теги, используйте format_html().

    Вот полный пример модели:

    from django.contrib import admin
    from django.db import models
    from django.utils.html import format_html
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
        color_code = models.CharField(max_length=6)
    
        @admin.display
        def colored_name(self):
            return format_html(
                '<span style="color: #{};">{} {}</span>',
                self.color_code,
                self.first_name,
                self.last_name,
            )
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'last_name', 'colored_name')
    
  • Как уже показано в некоторых примерах, при использовании вызываемого объекта, метода модели или ModelAdmin метода, вы можете настроить заголовок столбца, обернув вызываемый объект декоратором display() и передав аргумент description.
  • Если значение поля None, пустая строка или итерируемый объект без элементов, Django отобразит - (тире). Вы можете переопределить это с помощью AdminSite.empty_value_display:

    from django.contrib import admin
    
    admin.site.empty_value_display = '(None)'
    

    Вы также можете использовать ModelAdmin.empty_value_display:

    class PersonAdmin(admin.ModelAdmin):
        empty_value_display = 'unknown'
    

    Или на уровне поля:

    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'birth_date_view')
    
        @admin.display(empty_value='unknown')
        def birth_date_view(self, obj):
             return obj.birth_date
    
  • Если заданная строка — метод модели, ModelAdmin или вызываемый объект, возвращающий True, False, или None, Django отобразит значок «да», «нет» или «неизвестно», если вы обернёте метод декоратором display(), передав аргумент boolean со значением True:

    from django.contrib import admin
    from django.db import models
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        birthday = models.DateField()
    
        @admin.display(boolean=True)
        def born_in_fifties(self):
            return 1950 <= self.birthday.year < 1960
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'born_in_fifties')
    
  • Метод __str__() так же допустим в list_display как и любой другой метод модели, поэтому это вполне допустимо:

    list_display = ('__str__', 'some_other_field')
    
  • Обычно элементы list_display , которые не являются фактическими полями базы данных, не могут использоваться в сортировке (потому что Django выполняет всю сортировку на уровне базы данных).

    Однако, если элемент list_display представляет собой определённое поле базы данных, вы можете указать это, используя декоратор display() на методе, передав аргумент ordering:

    from django.contrib import admin
    from django.db import models
    from django.utils.html import format_html
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        color_code = models.CharField(max_length=6)
    
        @admin.display(ordering='first_name')
        def colored_first_name(self):
            return format_html(
                '<span style="color: #{};">{}</span>',
                self.color_code,
                self.first_name,
            )
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'colored_first_name')
    

    Это позволит Django сортировать по полю first_name при попытке сортировки по colored_first_name в админке.

    Для указания убывающей сортировки с помощью аргумента ordering можно использовать префикс дефиса перед именем поля. Используя вышеприведённый пример, это будет выглядеть так:

    @admin.display(ordering='-first_name')
    

    Аргумент ordering поддерживает запросы для сортировки по значениям в связанных моделях. В этом примере присутствует столбец «Имя автора (первое имя)» в списке отображения и позволяет сортировать его по первому имени:

    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')
    
        @admin.display(ordering='author__first_name')
        def author_first_name(self, obj):
            return obj.author.first_name
    

    Выражения запроса могут использоваться с аргументом ordering:

    from django.db.models import Value
    from django.db.models.functions import Concat
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        @admin.display(ordering=Concat('first_name', Value(' '), 'last_name'))
        def full_name(self):
            return self.first_name + ' ' + self.last_name
    
  • Элементы list_display также могут быть свойствами:

    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        @property
        @admin.display(
            ordering='last_name',
            description='Full name of the person',
        )
        def full_name(self):
            return self.first_name + ' ' + self.last_name
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('full_name',)
    

    Обратите внимание, что @property должно быть выше @display. Если вы используете старый способ — непосредственное задание атрибутов, относящихся к отображению, а не использование декоратора display() — имейте в виду, что функцию property() , а не декоратор @property следует использовать:

    def my_property(self):
        return self.first_name + ' ' + self.last_name
    my_property.short_description = "Full name of the person"
    my_property.admin_order_field = 'last_name'
    
    full_name = property(my_property)
    
  • Имена полей в 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 принимает список или кортеж имён полей для активации фильтрации, но доступны и несколько более продвинутых вариантов. Подробнее см. в Фильтры списка ModelAdmin.

ModelAdmin.list_max_show_all

Установите list_max_show_all для управления количеством элементов, которые могут отображаться на странице списка изменений админки с опцией «Показать всё». Админка отобразит ссылку «Показать всё» на странице списка изменений только если общее количество результатов меньше или равно этому значению. По умолчанию, это значение установлено в 200.

ModelAdmin.list_per_page

Установите list_per_page для управления количеством элементов на каждой постраничной странице списка изменений админки. По умолчанию, это значение установлено в 100.

ModelAdmin.list_select_related

Установите list_select_related, чтобы указать Django использовать select_related() при получении списка объектов на странице изменения админ-панели. Это может сэкономить несколько запросов к базе данных.

Значение должно быть либо булевым значением, либо списком или кортежем. По умолчанию False.

Когда значение True, select_related() всегда вызывается. Когда значение установлено в False, Django обратится к list_display и вызовет select_related() , если присутствуют какие-либо ForeignKey.

Если вам нужен более точный контроль, используйте кортеж (или список) в качестве значения для list_select_related. Пустой кортеж предотвратит вызов select_related Django вообще. Любой другой кортеж будет передан напрямую в select_related в качестве параметров. Например:

class ArticleAdmin(admin.ModelAdmin):
    list_select_related = ('author', 'category')

вызовет select_related('author', 'category').

Если вам нужно указать динамическое значение, основанное на запросе, вы можете реализовать метод get_list_select_related().

Примечание

ModelAdmin игнорирует этот атрибут, когда select_related() уже был вызван на QuerySet changelist.

ModelAdmin.ordering

Установите ordering для указания порядка сортировки списков объектов в представлениях Django admin. Это должен быть список или кортеж в том же формате, что и параметр ordering модели.

Если это не указано, Django admin будет использовать порядок сортировки по умолчанию модели.

Если вам нужен динамический порядок (например, зависящий от пользователя или языка), вы можете реализовать метод get_ordering().

Учет производительности при сортировке и упорядочивании

Для обеспечения детерминированного порядка результатов changelist добавляет pk к сортировке, если не может найти единственный или уникальный вместе набор полей, которые обеспечивают полную сортировку.

Например, если порядок по умолчанию задан по полю name, которое не является уникальным, то changelist сортируется по name и pk. Это может быть неэффективным, если у вас много строк и отсутствует индекс по name и pk.

ModelAdmin.paginator

Класс paginator, используемый для постраничного отображения. По умолчанию используется django.core.paginator.Paginator. Если у класса пользовательского paginator нет такого же интерфейса конструктора, как у django.core.paginator.Paginator, вам также потребуется реализовать ModelAdmin.get_paginator().

ModelAdmin.prepopulated_fields

Установите prepopulated_fields в словарь, сопоставляющий имена полей с полями, из которых они должны заполняться:

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

При установке заданные поля будут использовать немного JavaScript для заполнения из назначенных полей. Основное использование этой функциональности — автоматическое формирование значения для SlugField полей из одного или нескольких других полей. Сгенерированное значение формируется путем конкатенации значений исходных полей, а затем преобразования этого результата в допустимый slug (например, замена пробелов дефисами и приведение букв ASCII к нижнему регистру).

Предварительно заполненные поля не изменяются JavaScript после сохранения значения. Обычно нежелательно, чтобы slugs изменялись (что приведет к изменению URL объекта, если slug используется в нем).

prepopulated_fields не принимает DateTimeField, ForeignKey, OneToOneField, и ManyToManyField полей.

ModelAdmin.preserve_filters

По умолчанию примененные фильтры сохраняются на странице списка после создания, изменения или удаления объекта. Вы можете очистить фильтры, установив этот атрибут в False.

ModelAdmin.radio_fields

По умолчанию Django admin использует интерфейс select-box (<select>) для полей, являющихся ForeignKey или имеющих choices. Если поле присутствует в radio_fields, Django вместо этого использует интерфейс радиокнопок. Предполагая, что group является ForeignKey на модели Person.

class PersonAdmin(admin.ModelAdmin):
    radio_fields = {"group": admin.VERTICAL}

У вас есть выбор использовать HORIZONTAL или VERTICAL из модуля django.contrib.admin.

Не включайте поле в radio_fields , если это не ForeignKey или не имеет choices.

ModelAdmin.autocomplete_fields

autocomplete_fields — это список ForeignKey и/или ManyToManyField полей, которые вы хотите изменить на автозаполнение Select2.

По умолчанию администратор использует интерфейс select-box (<select>) для этих полей. Иногда вы не хотите нести затраты на выбор всех связанных экземпляров для отображения в раскрывающемся списке.

Ввод Select2 выглядит аналогично стандартному вводу, но имеет функцию поиска, которая загружает варианты асинхронно. Это быстрее и удобнее для пользователя, если связанная модель имеет много экземпляров.

Вы должны определить search_fields на связанном объекте ModelAdmin, так как поиск автозаполнения использует его.

Чтобы предотвратить несанкционированную утечку данных, пользователи должны иметь разрешение view или change на связанный объект, чтобы использовать автозаполнение.

Порядок и постраничность результатов контролируются связанными ModelAdmin методами get_ordering() и get_paginator().

В следующем примере ChoiceAdmin имеет поле автозаполнения для ForeignKey к Question . Результаты фильтруются по полю question_text и сортируются по полю date_created:

class QuestionAdmin(admin.ModelAdmin):
    ordering = ['date_created']
    search_fields = ['question_text']

class ChoiceAdmin(admin.ModelAdmin):
    autocomplete_fields = ['question']

Учет производительности при работе с большими наборами данных

Сортировка с помощью ModelAdmin.ordering может вызвать проблемы с производительностью, так как сортировка большого набора результатов будет медленной.

Кроме того, если ваши поля поиска включают поля, которые не индексированы в базе данных, вы можете столкнуться с низкой производительностью при работе с очень большими таблицами.

В таких случаях рекомендуется реализовать свой метод ModelAdmin.get_search_results() с использованием полнотекстового индексированного поиска.

Вы также можете изменить Paginator на очень больших таблицах, так как дефолтный paginator всегда выполняет запрос count(). Например, вы можете переопределить стандартную реализацию свойства Paginator.count.

ModelAdmin.raw_id_fields

По умолчанию Django admin использует интерфейс select-box (<select>) для полей, являющихся ForeignKey. Иногда вы не хотите нести затраты на выбор всех связанных экземпляров для отображения в раскрывающемся списке.

raw_id_fields — это список полей, которые вы хотите преобразовать в виджет Input для ForeignKey или ManyToManyField:

class ArticleAdmin(admin.ModelAdmin):
    raw_id_fields = ("newspaper",)

Виджет raw_id_fields Input должен содержать первичный ключ, если поле является ForeignKey , или список значений, разделенных запятыми, если поле является ManyToManyField . Виджет raw_id_fields отображает значок лупы рядом с полем, что позволяет пользователям искать и выбирать значение:

../../../_images/raw_id_fields.png
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',)

    # description functions like a model field's verbose_name
    @admin.display(description='Address')
    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>")
ModelAdmin.save_as

Установите save_as для включения функции «сохранить как новый» на формах изменения администратора.

Обычно объекты имеют три варианта сохранения: «Сохранить», «Сохранить и продолжить редактирование» и «Сохранить и добавить другой». Если save_as равно True, «Сохранить и добавить другой» будет заменено кнопкой «Сохранить как новый», которая создаст новый объект (с новым ID) вместо обновления существующего объекта.

По умолчанию save_as установлено в False.

ModelAdmin.save_as_continue

При save_as=True по умолчанию перенаправление после сохранения нового объекта происходит на страницу изменения этого объекта. Если установить save_as_continue=False, перенаправление будет на страницу списка изменений.

По умолчанию save_as_continue установлено в True.

ModelAdmin.save_on_top

Установите save_on_top для добавления кнопок сохранения в верхней части форм изменения администратора.

Обычно кнопки сохранения отображаются только в нижней части форм. Если вы установите save_on_top, кнопки будут отображаться как вверху, так и внизу.

По умолчанию save_on_top установлено в False.

ModelAdmin.search_fields

Установите search_fields для включения поля поиска на странице списка изменений администратора. Этот параметр должен быть списком имён полей, которые будут проиндексированы при каждом запросе поиска.

Эти поля должны быть какими-либо текстовыми полями, такими как CharField или TextField. Вы также можете выполнить связанный поиск по ForeignKey или ManyToManyField с использованием обозначения API поиска “follow”:

search_fields = ['foreign_key__related_fieldname']

Например, если у вас есть запись блога с автором, следующее определение позволит искать записи блога по адресу электронной почты автора:

search_fields = ['user__email']

Когда пользователь выполняет поиск в поле поиска администратора, Django разбивает запрос на слова и возвращает все объекты, содержащие каждое слово, не учитывая регистр (используя icontains поиск), где каждое слово должно присутствовать хотя бы в одном из 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%')

Запрос поиска может содержать цитируемые фразы с пробелами. Например, если пользователь ищет "john winston" или 'john winston', Django выполнит запрос, эквивалентный следующему SQL WHERE условию:

WHERE (first_name ILIKE '%john winston%' OR last_name ILIKE '%john winston%')

Если вы не хотите использовать icontains в качестве поиска, вы можете использовать любой поиск, добавив его к полю. Например, вы можете использовать exact, установив search_fields в ['first_name__exact'].

Также доступны некоторые (старые) сокращения для указания поиска по полю. Вы можете префиксровать поле в search_fields следующим символом, и это эквивалентно добавлению __<lookup> к полю:

Префикс Поиск
^ startswith
= iexact
@ search
None icontains

Если вам нужно настроить поиск, вы можете использовать ModelAdmin.get_search_results() для предоставления дополнительных или альтернативных функций поиска.

Изменено в Django 4.1:

Поиск с использованием нескольких поисковых терминов теперь применяется в одном вызове filter(), а не в последовательных filter() вызовах.

Для многозначных отношений это означает, что строки из связанной модели должны соответствовать всем терминам, а не любому термину. Например, если search_fields установлено в ['child__name', 'child__age'] и пользователь ищет 'Jamal 17', строки родительских объектов будут возвращаться только в том случае, если существует отношение к некоторому 17-летнему ребенку по имени Джамаль, а не также возвращаться родителям, у которых есть только младший или старший ребенок по имени Джамаль, помимо других 17-летних.

См. раздел Spanning multi-valued relationships для более подробного обсуждения этого различия.

ModelAdmin.search_help_text
New in Django 4.0.

Установите search_help_text для задания описательного текста для поля поиска, который будет отображаться под ним.

ModelAdmin.show_full_result_count

Установите show_full_result_count для управления отображением полного количества объектов на отфильтрованной странице администратора (например, 99 results (103 total)). Если этот параметр установлен в False, вместо этого отображается текст, подобный 99 results (Show all).

По умолчанию show_full_result_count=True генерирует запрос для выполнения подсчета всех строк таблицы, что может быть затратно по ресурсам, если таблица содержит большое количество строк.

ModelAdmin.sortable_by

По умолчанию страница списка изменений позволяет сортировать по всем полям модели (и вызовам, которые используют ordering аргумент декоратора display() или имеют admin_order_field атрибут) указанные в list_display.

Если вы хотите отключить сортировку для некоторых столбцов, установите sortable_by в коллекцию (например, list, tuple, или set), подмножество list_display, которое вы хотите отсортировать. Пустая коллекция отключает сортировку для всех столбцов.

Если вам нужно динамически указать этот список, реализуйте метод get_sortable_by() вместо этого.

ModelAdmin.view_on_site

Установите view_on_site для управления отображением ссылки «Просмотреть на сайте». Эта ссылка должна перенаправлять вас на URL, где можно отобразить сохранённый объект.

Это значение может быть либо логическим флагом, либо вызываемым объектом. Если True (по умолчанию), будет использован метод объекта get_absolute_url() для генерации URL.

Если у вашей модели есть метод get_absolute_url(), но вы не хотите, чтобы отображалась кнопка «Просмотреть на сайте», вам нужно только установить view_on_site в False:

from django.contrib import admin

class PersonAdmin(admin.ModelAdmin):
    view_on_site = False

В случае вызываемого объекта он принимает экземпляр модели в качестве параметра. Например:

from django.contrib import admin
from django.urls import reverse

class PersonAdmin(admin.ModelAdmin):
    def view_on_site(self, obj):
        url = reverse('person-detail', kwargs={'slug': obj.slug})
        return 'https://example.com' + url

Custom template options

Раздел Переопределение шаблонов административной панели описывает, как переопределить или расширить стандартные шаблоны административной панели. Используйте следующие параметры для переопределения стандартных шаблонов, используемых представлениями ModelAdmin:

ModelAdmin.add_form_template

Путь к пользовательскому шаблону, используемому представлением add_view().

ModelAdmin.change_form_template

Путь к пользовательскому шаблону, используемому представлением change_view().

ModelAdmin.change_list_template

Путь к пользовательскому шаблону, используемому представлением changelist_view().

ModelAdmin.delete_confirmation_template

Путь к пользовательскому шаблону, используемому представлением delete_view() для отображения страницы подтверждения при удалении одного или нескольких объектов.

ModelAdmin.delete_selected_confirmation_template

Путь к пользовательскому шаблону, используемому методом действия delete_selected, для отображения страницы подтверждения при удалении одного или нескольких объектов. См. документацию по действиям.

ModelAdmin.object_history_template

Путь к пользовательскому шаблону, используемому представлением history_view().

ModelAdmin.popup_response_template

Путь к пользовательскому шаблону, используемому представлениями response_add(), response_change() и response_delete().

ModelAdmin методы

Предупреждение

При переопределении методов ModelAdmin.save_model() и ModelAdmin.delete_model() ваш код должен сохранять/удалять объект. Они не предназначены для отмены, а позволяют выполнять дополнительные операции.

ModelAdmin.save_model(request, obj, form, change)

Метод save_model получает HttpRequest, экземпляр модели, экземпляр ModelForm, и булево значение, указывающее на добавление или изменение объекта. Переопределение этого метода позволяет выполнять операции до или после сохранения. Вызовите super().save_model() для сохранения объекта с помощью Model.save().

Например, чтобы добавить request.user к объекту перед сохранением:

from django.contrib import admin

class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        super().save_model(request, obj, form, change)
ModelAdmin.delete_model(request, obj)

Метод delete_model получает HttpRequest и экземпляр модели. Переопределение этого метода позволяет выполнять операции до или после удаления. Вызовите super().delete_model() для удаления объекта с помощью Model.delete().

ModelAdmin.delete_queryset(request, queryset)

Метод delete_queryset() получает HttpRequest и QuerySet объектов для удаления. Переопределите этот метод, чтобы настроить процесс удаления для действия «удалить выбранные объекты» действие.

ModelAdmin.save_formset(request, form, formset, change)

Метод save_formset получает HttpRequest, экземпляр родительского ModelForm и булево значение, указывающее на добавление или изменение родительского объекта.

Например, чтобы добавить request.user к каждому экземпляру модели формочета с изменениями:

class ArticleAdmin(admin.ModelAdmin):
    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        for obj in formset.deleted_objects:
            obj.delete()
        for instance in instances:
            instance.user = request.user
            instance.save()
        formset.save_m2m()

См. также Сохранение объектов в формочете.

ModelAdmin.get_ordering(request)

Метод get_ordering принимает request в качестве параметра и должен возвращать list или tuple для сортировки, аналогично атрибуту ordering. Например:

class PersonAdmin(admin.ModelAdmin):

    def get_ordering(self, request):
        if request.user.is_superuser:
            return ['name', 'rank']
        else:
            return ['name']
ModelAdmin.get_search_results(request, queryset, search_term)

Метод get_search_results изменяет список отображаемых объектов на те, которые соответствуют предоставленному поисковому запросу. Он принимает запрос, набор результатов, применяющий текущие фильтры, и введенный пользователем поисковый запрос. Он возвращает кортеж, содержащий измененный набор результатов для реализации поиска и булево значение, указывающее, могут ли результаты содержать дубликаты.

По умолчанию поиск выполняется по полям, указанным в 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, may_have_duplicates = super().get_search_results(
            request, queryset, search_term,
        )
        try:
            search_term_as_int = int(search_term)
        except ValueError:
            pass
        else:
            queryset |= self.model.objects.filter(age=search_term_as_int)
        return queryset, may_have_duplicates

Эта реализация более эффективна, чем search_fields = ('name', '=age'), которая приводит к строковому сравнеию для числового поля, например ... OR UPPER("polls_choice"."votes"::text) = UPPER('4') в PostgreSQL.

Изменено в Django 4.1:

Поиск по нескольким поисковым терминам теперь применяется в одном вызове filter(), а не в последовательных вызовах filter().

Для многозначных отношений это означает, что строки из связанной модели должны соответствовать всем терминам, а не любому термину. Например, если search_fields установлено на ['child__name', 'child__age'], и пользователь ищет 'Jamal 17', родительские строки будут возвращены только в том случае, если существует отношение к какому-то 17-летнему ребенку по имени Джамаль, а не возвращать также родителей, у которых просто есть младший или старший ребенок по имени Джамаль, кроме какого-то другого 17-летнего ребенка.

См. раздел Связывание многозначных отношений для более подробного обсуждения этого различия.

ModelAdmin.save_related(request, form, formsets, change)

Метод save_related получает HttpRequest, родительский ModelForm экземпляр, список формочетов для встроенных элементов и булево значение, указывающее на добавление или изменение родительского объекта. Здесь вы можете выполнять любые предварительные или последующие операции сохранения для объектов, связанных с родителем. Обратите внимание, что на этом этапе родительский объект и его форма уже сохранены.

ModelAdmin.get_autocomplete_fields(request)

Метод get_autocomplete_fields() получает HttpRequest и должен возвращать list или tuple имен полей, которые будут отображаться с виджетом автозаполнения, как описано выше в разделе ModelAdmin.autocomplete_fields.

ModelAdmin.get_readonly_fields(request, obj=None)

Метод get_readonly_fields получает HttpRequest и редактируемый obj (или None в форме добавления) и должен возвращать list или tuple имен полей, которые будут отображаться как только для чтения, как описано выше в разделе ModelAdmin.readonly_fields.

ModelAdmin.get_prepopulated_fields(request, obj=None)

Метод get_prepopulated_fields получает HttpRequest и obj, которые редактируются (или None в форме добавления), и ожидается, что он вернёт dictionary, как описано в разделе ModelAdmin.prepopulated_fields.

ModelAdmin.get_list_display(request)

Метод get_list_display получает HttpRequest и ожидается, что он вернёт list или tuple имён полей, которые будут отображаться на странице списка изменений, как описано в разделе ModelAdmin.list_display.

ModelAdmin.get_list_display_links(request, list_display)

Метод get_list_display_links получает HttpRequest и list или tuple, возвращаемые методом ModelAdmin.get_list_display(). Ожидается, что он вернёт либо None, либо list или tuple имён полей на странице списка изменений, которые будут связаны со страницей изменения, как описано в разделе ModelAdmin.list_display_links.

ModelAdmin.get_exclude(request, obj=None)

Метод get_exclude получает HttpRequest и obj редактируемого объекта (или None в форме добавления) и ожидается, что он вернёт список полей, как описано в ModelAdmin.exclude.

ModelAdmin.get_fields(request, obj=None)

Метод get_fields получает HttpRequest и obj редактируемого объекта (или None в форме добавления) и ожидается, что он вернёт список полей, как описано в разделе ModelAdmin.fields.

ModelAdmin.get_fieldsets(request, obj=None)

Метод get_fieldsets получает HttpRequest и obj редактируемого объекта (или None в форме добавления) и ожидается, что он вернёт список пар кортежей, где каждая пара кортежей представляет собой <fieldset> на странице формы администрирования, как описано в разделе ModelAdmin.fieldsets.

ModelAdmin.get_list_filter(request)

Метод get_list_filter получает HttpRequest и ожидается, что он вернёт тот же тип последовательности, что и для атрибута list_filter.

ModelAdmin.get_list_select_related(request)

Метод get_list_select_related получает HttpRequest и должен вернуть булевое значение или список, как и атрибут ModelAdmin.list_select_related.

ModelAdmin.get_search_fields(request)

Метод get_search_fields получает HttpRequest и ожидается, что он вернёт тот же тип последовательности, что и для атрибута search_fields.

ModelAdmin.get_sortable_by(request)

Метод get_sortable_by() получает HttpRequest и ожидается, что вернёт коллекцию (например, list, tuple, или set) имён полей, которые можно сортировать на странице списка изменений.

Его стандартная реализация возвращает значение атрибута sortable_by, если он задан, в противном случае делегирует выполнение методу get_list_display().

Например, чтобы предотвратить сортировку по одному или нескольким столбцам:

class PersonAdmin(admin.ModelAdmin):

    def get_sortable_by(self, request):
        return {*self.get_list_display(request)} - {'rank'}
ModelAdmin.get_inline_instances(request, obj=None)

Метод get_inline_instances получает HttpRequest и obj редактируемого объекта (или None в форме добавления) и ожидается, что он вернёт list или tuple объектов InlineModelAdmin, как описано ниже в разделе InlineModelAdmin. Например, следующее вернёт встраиваемые объекты без стандартного фильтрации по разрешениям на добавление, изменение, удаление и просмотр:

class MyModelAdmin(admin.ModelAdmin):
    inlines = (MyInline,)

    def get_inline_instances(self, request, obj=None):
        return [inline(self.model, self.admin_site) for inline in self.inlines]

Если вы переопределяете этот метод, убедитесь, что возвращаемые встраиваемые объекты являются экземплярами классов, определённых в inlines, иначе при добавлении связанных объектов может возникнуть ошибка «Неверный запрос».

ModelAdmin.get_inlines(request, obj)

Метод get_inlines получает HttpRequest и obj редактируемого объекта (или None в форме добавления) и ожидается, что он вернёт итерируемый объект встраиваемых объектов. Вы можете переопределить этот метод, чтобы динамически добавлять встраиваемые объекты на основе запроса или экземпляра модели вместо указания их в ModelAdmin.inlines.

ModelAdmin.get_urls()

Метод get_urls на объекте ModelAdmin возвращает URL-адреса, которые будут использоваться для данного ModelAdmin аналогично URLconf. Поэтому вы можете их расширять, как описано в диспетчере URL:

from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path

class MyModelAdmin(admin.ModelAdmin):
    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            path('my_view/', self.my_view),
        ]
        return my_urls + urls

    def my_view(self, request):
        # ...
        context = dict(
           # Include common variables for rendering the admin template.
           self.admin_site.each_context(request),
           # Anything else you want in the context...
           key=value,
        )
        return TemplateResponse(request, "sometemplate.html", context)

Если вы хотите использовать макет администрирования, расширьте admin/base_site.html:

{% extends "admin/base_site.html" %}
{% block content %}
...
{% endblock %}

Примечание

Обратите внимание, что пользовательские шаблоны включены перед стандартными URL-адресами администрирования: шаблоны URL-адресов администрирования очень общие и будут соответствовать почти всему, поэтому, как правило, вы захотите поместить свои пользовательские URL-адреса перед встроенными.

В этом примере, my_view будет доступен по адресу /admin/myapp/mymodel/my_view/ (предполагается, что URL-адреса администрирования включены в /admin/.)

Однако, функция self.my_view зарегистрированная выше, имеет две проблемы:

  • Она не выполняет проверки разрешений, поэтому она будет доступна всем пользователям.
  • Она не предоставляет никаких заголовков, чтобы предотвратить кэширование. Это означает, что если страница извлекает данные из базы данных, а кэширование включено, страница может отображать устаревшую информацию.

Поскольку это обычно не то, что вы хотите, Django предоставляет удобную оболочку для проверки разрешений и маркировки представления как некэшируемого. Эта оболочка - AdminSite.admin_view() (то есть self.admin_site.admin_view внутри экземпляра ModelAdmin); используйте её так:

class MyModelAdmin(admin.ModelAdmin):
    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            path('my_view/', self.admin_site.admin_view(self.my_view))
        ]
        return my_urls + urls

Обратите внимание на обернутое представление в пятой строке выше:

path('my_view/', self.admin_site.admin_view(self.my_view))

Это обертывание защитит self.my_view от несанкционированного доступа и применит декоратор django.views.decorators.cache.never_cache(), чтобы убедиться, что он не будет кэширован, если включено кэширование.

Если страница кэшируемая, но вы всё равно хотите, чтобы проверка разрешений выполнялась, вы можете передать аргумент cacheable=True в AdminSite.admin_view():

path('my_view/', self.admin_site.admin_view(self.my_view, cacheable=True))

ModelAdmin представления имеют атрибут model_admin. Другие AdminSite представления имеют атрибут admin_site.

ModelAdmin.get_form(request, obj=None, **kwargs)

Возвращает класс ModelForm для использования в админских представлениях добавления и изменения, см. add_view() и change_view().

Базовая реализация использует modelform_factory() для создания подкласса form, модифицированного такими атрибутами, как fields и exclude. Например, если вы хотите предложить дополнительные поля для суперпользователей, вы можете заменить базовую форму следующим образом:

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        if request.user.is_superuser:
            kwargs['form'] = MySuperuserForm
        return super().get_form(request, obj, **kwargs)

Также вы можете вернуть непосредственно пользовательский класс ModelForm.

ModelAdmin.get_formsets_with_inlines(request, obj=None)

Возвращает пары (FormSet, InlineModelAdmin) для использования в админских представлениях добавления и изменения.

Например, если вы хотите отобразить определённый inline только в представлении изменения, вы можете переопределить get_formsets_with_inlines следующим образом:

class MyModelAdmin(admin.ModelAdmin):
    inlines = [MyInline, SomeOtherInline]

    def get_formsets_with_inlines(self, request, obj=None):
        for inline in self.get_inline_instances(request, obj):
            # hide MyInline in the add view
            if not isinstance(inline, MyInline) or obj is not None:
                yield inline.get_formset(request, obj), inline
ModelAdmin.formfield_for_foreignkey(db_field, request, **kwargs)

Метод formfield_for_foreignkey на ModelAdmin позволяет переопределить стандартное поле формы для поля foreign key. Например, чтобы вернуть подмножество объектов для этого поля foreign key, основанное на пользователе:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "car":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

Это использует экземпляр HttpRequest для фильтрации поля foreign key Car так, чтобы отображались только автомобили, принадлежащие экземпляру User.

Для более сложных фильтров вы можете использовать метод ModelForm.__init__() для фильтрации на основе instance вашей модели (см. Поля, обрабатывающие отношения). Например:

class CountryAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['capital'].queryset = self.instance.cities.all()

class CountryAdmin(admin.ModelAdmin):
    form = CountryAdminForm
ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)

Как и метод formfield_for_foreignkey, метод formfield_for_manytomany может быть переопределён для изменения стандартного поля формы для поля many-to-many. Например, если владелец может владеть несколькими машинами, а машины могут принадлежать нескольким владельцам (отношение many-to-many) — вы можете отфильтровать поле foreign key Car для отображения только автомобилей, принадлежащих экземпляру User:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "cars":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super().formfield_for_manytomany(db_field, request, **kwargs)
ModelAdmin.formfield_for_choice_field(db_field, request, **kwargs)

Как и методы formfield_for_foreignkey и formfield_for_manytomany, метод formfield_for_choice_field может быть переопределён для изменения стандартного поля формы для поля, для которого объявлены варианты выбора. Например, если доступные варианты для суперпользователя должны отличаться от вариантов для обычных сотрудников, можно поступить следующим образом:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_choice_field(self, db_field, request, **kwargs):
        if db_field.name == "status":
            kwargs['choices'] = (
                ('accepted', 'Accepted'),
                ('denied', 'Denied'),
            )
            if request.user.is_superuser:
                kwargs['choices'] += (('ready', 'Ready for deployment'),)
        return super().formfield_for_choice_field(db_field, request, **kwargs)

Примечание

Любой атрибут choices, установленный на поле формы, будет ограничен только этим полем. Если соответствующее поле в модели имеет заданные варианты выбора, предоставленные варианты формы должны быть допустимым подмножеством этих вариантов, иначе отправка формы завершится ошибкой с ValidationError при валидации модели перед сохранением.

ModelAdmin.get_changelist(request, **kwargs)

Возвращает класс Changelist для использования в списке. По умолчанию используется django.contrib.admin.views.main.ChangeList. Наследуя этот класс, вы можете изменить поведение списка.

ModelAdmin.get_changelist_form(request, **kwargs)

Возвращает класс ModelForm для использования в Formset на странице списка изменений. Чтобы использовать пользовательскую форму, например:

from django import forms

class MyForm(forms.ModelForm):
    pass

class MyModelAdmin(admin.ModelAdmin):
    def get_changelist_form(self, request, **kwargs):
        return MyForm

Примечание

Если вы определены атрибут Meta.model на ModelForm, вы также должны определить атрибут Meta.fields (или атрибут Meta.exclude). Однако ModelAdmin игнорирует это значение, переопределяя его атрибутом ModelAdmin.list_editable. Проще всего опустить атрибут Meta.model, так как ModelAdmin предоставит правильную модель для использования.

ModelAdmin.get_changelist_formset(request, **kwargs)

Возвращает класс ModelFormSet для использования на странице списка изменений, если используется list_editable. Чтобы использовать пользовательский набор форм, например:

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
    pass

class MyModelAdmin(admin.ModelAdmin):
    def get_changelist_formset(self, request, **kwargs):
        kwargs['formset'] = MyAdminFormSet
        return super().get_changelist_formset(request, **kwargs)
ModelAdmin.lookup_allowed(lookup, value)

Объекты на странице списка изменений могут быть отфильтрованы с помощью запросов из строки запроса URL. Так, например, работает list_filter. Запросы похожи на используемые в QuerySet.filter() (например, user__email=user@example.com). Поскольку запросы в строке запроса могут быть изменены пользователем, они должны быть очищены, чтобы предотвратить раскрытие несанкционированных данных.

Методу lookup_allowed() передаётся путь запроса из строки запроса (например, 'user__email') и соответствующее значение (например, 'user@example.com'), а возвращается булево значение, указывающее, разрешено ли отфильтровать список изменений QuerySet с использованием параметров. Если lookup_allowed() возвращает False, генерируется DisallowedModelAdminLookup (подкласс SuspiciousOperation).

По умолчанию lookup_allowed() разрешает доступ к локальным полям модели, путям полей, используемым в list_filter (но не путям из get_list_filter()), и запросам, необходимым для корректной работы limit_choices_to в raw_id_fields.

Переопределите этот метод для настройки запросов, разрешённых для вашего подкласса ModelAdmin.

ModelAdmin.has_view_permission(request, obj=None)

Должно возвращать True, если просмотр obj разрешён, False в противном случае. Если obj является None, должно возвращать True или False для указания разрешения просмотра объектов этого типа в целом (например, False будет интерпретироваться как то, что текущий пользователь не имеет права просматривать ни один объект этого типа).

По умолчанию реализация возвращает True , если пользователь имеет права «изменить» или «просмотреть».

ModelAdmin.has_add_permission(request)

Должно возвращать True, если добавление объекта разрешено, False в противном случае.

ModelAdmin.has_change_permission(request, obj=None)

Должно возвращать True если редактирование obj разрешено, False в противном случае. Если obj является None, должно возвращать True или False для указания разрешения редактирования объектов этого типа в целом (например, False будет интерпретироваться как то, что текущий пользователь не имеет права редактировать ни один объект этого типа).

END_OF_DOCUMENT_MARKER
ModelAdmin.has_delete_permission(request, obj=None)

Должно возвращать True если удаление obj разрешено, False в противном случае. Если obj равно None, должно возвращать True или False для указания разрешения на удаление объектов данного типа в целом (например, False будет означать, что текущий пользователь не имеет разрешения на удаление любого объекта данного типа).

ModelAdmin.has_module_permission(request)

Должно возвращать True если модуль отображается на странице админ-индекса и доступ к странице индекса модуля разрешен, False в противном случае. По умолчанию использует User.has_module_perms(). Переопределение не ограничивает доступ к представлениям просмотра, добавления, изменения или удаления, has_view_permission(), has_add_permission(), has_change_permission() и has_delete_permission() должны использоваться для этого.

ModelAdmin.get_queryset(request)

Метод get_queryset на ModelAdmin возвращает QuerySet всех экземпляров модели, которые могут быть изменены сайтом администрирования. Одним из вариантов использования переопределения этого метода является отображение объектов, принадлежащих вошедшему пользователю:

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)
ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False)

Отправляет сообщение пользователю, используя django.contrib.messages бэкэнд. См. пример custom ModelAdmin.

Использование ключевых аргументов позволяет изменить уровень сообщения, добавить дополнительные теги CSS или молча проигнорировать ошибку, если contrib.messages фреймворк не установлен. Эти ключевые аргументы соответствуют аргументам django.contrib.messages.add_message(), см. документацию этой функции для получения более подробной информации. Различие состоит в том, что уровень может быть передан как строковая метка помимо целого числа/константы.

ModelAdmin.get_paginator(request, queryset, per_page, orphans=0, allow_empty_first_page=True)

Возвращает экземпляр пагинатора, который следует использовать для этого представления. По умолчанию создает экземпляр paginator.

ModelAdmin.response_add(request, obj, post_url_continue=None)

Определяет HttpResponse для стадии add_view().

response_add вызывается после отправки формы администрирования и сразу после создания и сохранения объекта и всех связанных экземпляров. Вы можете переопределить его, чтобы изменить стандартное поведение после создания объекта.

ModelAdmin.response_change(request, obj)

Определяет HttpResponse для стадии change_view().

response_change вызывается после отправки формы администрирования и сразу после сохранения объекта и всех связанных экземпляров. Вы можете переопределить его, чтобы изменить стандартное поведение после изменения объекта.

ModelAdmin.response_delete(request, obj_display, obj_id)

Определяет HttpResponse для стадии delete_view().

response_delete вызывается после удаления объекта. Вы можете переопределить его, чтобы изменить стандартное поведение после удаления объекта.

obj_display — строка с именем удаленного объекта.

obj_id — сериализованный идентификатор, используемый для получения объекта, подлежащего удалению.

ModelAdmin.get_formset_kwargs(request, obj, inline, prefix)
Новое в Django 4.0.

Метод для настройки ключевых аргументов, передаваемых в конструктор formset. Например, для передачи request формам formset:

class MyModelAdmin(admin.ModelAdmin):
    def get_formset_kwargs(self, request, obj, inline, prefix):
        return {
            **super().get_formset_kwargs(request, obj, inline, prefix),
            'form_kwargs': {'request': request},
        }

Также можно использовать для установки initial для форм formset.

ModelAdmin.get_changeform_initial_data(request)

Метод для начальных данных в формах изменения администрирования. По умолчанию полям присваиваются начальные значения из параметров GET. Например, ?name=initial_value установит начальное значение поля name в initial_value.

Этот метод должен возвращать словарь вида {'fieldname': 'fieldval'}:

def get_changeform_initial_data(self, request):
    return {'name': 'custom_initial_value'}
ModelAdmin.get_deleted_objects(objs, request)

Метод для настройки процесса удаления для delete_view() и действия «удалить выбранные» действие.

Аргумент objs — однородный итерируемый набор объектов (QuerySet, или список экземпляров модели), подлежащих удалению, а request — HttpRequest.

Этот метод должен возвращать 4-кортеж (deleted_objects, model_count, perms_needed, protected).

deleted_objects — список строк, представляющих все объекты, которые будут удалены. Если есть какие-либо связанные объекты, подлежащие удалению, список является вложенным и включает эти связанные объекты. Список отформатирован в шаблоне с использованием фильтра unordered_list.

model_count — словарь, сопоставляющий множественное число verbose_name каждого модели к количеству объектов, которые будут удалены.

perms_needed — множество verbose_name моделей, которые пользователь не имеет разрешения удалять.

protected — список строк, представляющих все защищенные связанные объекты, которые не могут быть удалены. Список отображается в шаблоне.

Другие методы

ModelAdmin.add_view(request, form_url='', extra_context=None)

Представление Django для страницы добавления экземпляра модели. См. примечание ниже.

ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)

Представление Django для страницы редактирования экземпляра модели. См. примечание ниже.

ModelAdmin.changelist_view(request, extra_context=None)

Представление Django для страницы списка/действий изменения экземпляров модели. См. примечание ниже.

ModelAdmin.delete_view(request, object_id, extra_context=None)

Представление Django для страницы подтверждения удаления экземпляра(ов) модели. См. примечание ниже.

ModelAdmin.history_view(request, object_id, extra_context=None)

Представление Django для страницы истории изменений заданного экземпляра модели.

Изменено в Django 4.1:

Добавлена пагинация.

В отличие от методов типа ModelAdmin в предыдущем разделе, эти пять методов фактически предназначены для вызова как представлений Django из обработчика маршрутизации URL приложения администрирования для отображения страниц, которые обрабатывают операции CRUD экземпляров модели. Полное переопределение этих методов существенно изменит поведение приложения администрирования.

Одной из распространённых причин переопределения этих методов является расширение контекстных данных, предоставляемых шаблону, который отображает представление. В следующем примере представление изменения переопределяется таким образом, что отображаемому шаблону предоставляются дополнительные данные сопоставления, которые в противном случае были бы недоступны:

class MyModelAdmin(admin.ModelAdmin):

    # A template for a very customized change view:
    change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'

    def get_osm_info(self):
        # ...
        pass

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['osm_data'] = self.get_osm_info()
        return super().change_view(
            request, object_id, form_url, extra_context=extra_context,
        )

Эти представления возвращают TemplateResponse экземпляры, которые позволяют легко настроить данные ответа перед отображением. Более подробную информацию см. в документации TemplateResponse.

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

Django admin JavaScript использует библиотеку jQuery.

Чтобы избежать конфликтов с пользовательскими скриптами или библиотеками, jQuery Django (версия 3.6.0) имеет пространство имён django.jQuery. Если вы хотите использовать jQuery в собственном admin JavaScript без включения второй копии, вы можете использовать объект django.jQuery в списках изменений и представлениях добавления/редактирования. Кроме того, ваши собственные admin-формы или виджеты, зависящие от django.jQuery должны указывать js=['admin/js/jquery.init.js', …] при определении активов форм.

Изменено в Django 4.0:

jQuery был обновлён с версии 3.5.1 до 3.6.0.

Класс 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
class StackedInline

В административном интерфейсе есть возможность редактировать модели на той же странице, что и родительская модель. Это называются строками. Предположим, у вас есть эти две модели:

from django.db import models

class Author(models.Model):
   name = models.CharField(max_length=100)

class Book(models.Model):
   author = models.ForeignKey(Author, on_delete=models.CASCADE)
   title = models.CharField(max_length=100)

Вы можете редактировать книги, написанные автором, на странице автора. Вы добавляете строки в модель, указав их в ModelAdmin.inlines:

from django.contrib import admin

class BookInline(admin.TabularInline):
    model = Book

class AuthorAdmin(admin.ModelAdmin):
    inlines = [
        BookInline,
    ]

Django предоставляет два подкласса InlineModelAdmin:

  • TabularInline
  • StackedInline

Разница между ними заключается только в используемой шаблоне.

InlineModelAdmin опции

InlineModelAdmin обладает многими из тех же возможностей, что и ModelAdmin, и добавляет некоторые свои собственные (общие возможности фактически определены в суперклассе BaseModelAdmin). Общие возможности:

  • form
  • fieldsets
  • fields
  • formfield_overrides
  • exclude
  • filter_horizontal
  • filter_vertical
  • ordering
  • prepopulated_fields
  • get_fieldsets()
  • get_queryset()
  • radio_fields
  • readonly_fields
  • raw_id_fields
  • formfield_for_choice_field()
  • formfield_for_foreignkey()
  • formfield_for_manytomany()
  • has_module_permission()

Класс InlineModelAdmin добавляет или настраивает:

InlineModelAdmin.model

Модель, используемая строкой. Это обязательно.

InlineModelAdmin.fk_name

Имя внешнего ключа в модели. В большинстве случаев это обрабатывается автоматически, но fk_name нужно указать явно, если существует более одного внешнего ключа к той же родительской модели.

InlineModelAdmin.formset

По умолчанию это BaseInlineFormSet. Использование собственного набора форм предоставляет множество возможностей для настройки. Строки основаны на наборах форм моделей.

InlineModelAdmin.form

Значение form по умолчанию ModelForm. Это то, что передаётся в inlineformset_factory() при создании набора форм для этой строки.

Предупреждение

При написании пользовательской валидации для форм InlineModelAdmin, будьте осторожны при написании валидации, которая полагается на функции родительской модели. Если родительская модель не прошла валидацию, она может быть оставлена в несогласованном состоянии, как описано в предупреждении в Валидация в ModelForm.

InlineModelAdmin.classes

Список или кортеж, содержащий дополнительные CSS-классы, применяемые к области с элементами управления, которая отображается для вложенных элементов. По умолчанию None. Как и с классами, настроенными в fieldsets, вложенные элементы с классом collapse будут первоначально свёрнуты, а в заголовке будет ссылка «показать».

InlineModelAdmin.extra

Этот параметр управляет количеством дополнительных форм, которые будет отображать формасет, помимо начальных форм. По умолчанию 3. Подробнее см. документацию по формасетам.

Для пользователей с браузерами, поддерживающими 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.verbose_name, Django будет использовать InlineModelAdmin.verbose_name + 's'.

Изменено в Django 4.0:

Была добавлена поддержка возврата к InlineModelAdmin.verbose_name.

InlineModelAdmin.can_delete

Определяет, можно ли удалять вложенные объекты во вложенном элементе. По умолчанию True.

InlineModelAdmin.show_change_link

Определяет, отображать ли ссылку на форму изменения для вложенных объектов, которые могут быть изменены в админке. По умолчанию False.

InlineModelAdmin.get_formset(request, obj=None, **kwargs)

Возвращает класс BaseInlineFormSet для использования в админских представлениях добавления/изменения. obj — редактируемый родительский объект, или None при добавлении нового родителя. См. пример для ModelAdmin.get_formsets_with_inlines.

InlineModelAdmin.get_extra(request, obj=None, **kwargs)

Возвращает количество дополнительных форм вложенного элемента. По умолчанию возвращает атрибут InlineModelAdmin.extra.

Переопределите этот метод, чтобы программно определить количество дополнительных форм вложенного элемента. Например, это может основываться на экземпляре модели (переданном в качестве аргумента obj):

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

    def get_extra(self, request, obj=None, **kwargs):
        extra = 2
        if obj:
            return extra - obj.binarytree_set.count()
        return extra
InlineModelAdmin.get_max_num(request, obj=None, **kwargs)

Возвращает максимальное количество дополнительных форм вложенного элемента. По умолчанию возвращает атрибут InlineModelAdmin.max_num.

Переопределите этот метод, чтобы программно определить максимальное количество форм вложенного элемента. Например, это может основываться на экземпляре модели (переданном в качестве аргумента obj):

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

    def get_max_num(self, request, obj=None, **kwargs):
        max_num = 10
        if obj and obj.parent:
            return max_num - 5
        return max_num
InlineModelAdmin.get_min_num(request, obj=None, **kwargs)

Возвращает минимальное количество форм вложенного элемента. По умолчанию возвращает атрибут InlineModelAdmin.min_num.

Переопределите этот метод, чтобы программно определить минимальное количество форм вложенного элемента. Например, это может основываться на экземпляре модели (переданном в качестве аргумента obj).

InlineModelAdmin.has_add_permission(request, obj)

Должно возвращать True если добавление вложенного объекта разрешено, False в противном случае. obj — редактируемый родительский объект, или None при добавлении нового родителя.

InlineModelAdmin.has_change_permission(request, obj=None)

Должно возвращать True если редактирование вложенного объекта разрешено, False в противном случае. obj — редактируемый родительский объект.

InlineModelAdmin.has_delete_permission(request, obj=None)

Должно возвращать True если удаление вложенного объекта разрешено, False в противном случае. obj — редактируемый родительский объект.

Примечание

Аргумент obj, переданный в методы InlineModelAdmin, является редактируемым родительским объектом или None при добавлении нового родителя.

Работа с моделью с двумя или более внешними ключами к одной и той же родительской модели

Иногда возможно иметь более одного внешнего ключа к той же модели. Возьмем, к примеру, эту модель:

from django.db import models

class Friendship(models.Model):
    to_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="friends")
    from_person = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="from_friends")

Если вы хотите отобразить вложенный элемент на страницах администрирования добавления/изменения Person, вам необходимо явно определить внешний ключ, так как автоматически это сделать невозможно:

from django.contrib import admin
from myapp.models import Friendship

class FriendshipInline(admin.TabularInline):
    model = Friendship
    fk_name = "to_person"

class PersonAdmin(admin.ModelAdmin):
    inlines = [
        FriendshipInline,
    ]

Работа с моделями многие-ко-многим

По умолчанию виджеты администрирования для взаимосвязей «многие ко многим» будут отображаться в той модели, которая содержит фактическую ссылку на ManyToManyField. В зависимости от вашего ModelAdmin определения, каждое поле «многие ко многим» в вашей модели будет представлено стандартным HTML <select multiple>, горизонтальным или вертикальным фильтром, или виджетом raw_id_fields. Однако также возможно заменить эти виджеты встроенными.

Предположим, что у нас есть следующие модели:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, related_name='groups')

Если вы хотите отобразить связи «многие ко многим» с помощью встроенного элемента, вы можете сделать это, определив объект InlineModelAdmin для отношения:

from django.contrib import admin

class MembershipInline(admin.TabularInline):
    model = Group.members.through

class PersonAdmin(admin.ModelAdmin):
    inlines = [
        MembershipInline,
    ]

class GroupAdmin(admin.ModelAdmin):
    inlines = [
        MembershipInline,
    ]
    exclude = ('members',)

В этом примере стоит отметить две особенности.

Во-первых, класс MembershipInline ссылается на Group.members.through. Атрибут through представляет ссылку на модель, которая управляет отношением «многие ко многим». Эта модель автоматически создается Django при определении поля «многие ко многим».

Во-вторых, класс GroupAdmin должен вручную исключить поле members. Django отображает виджет администрирования для поля «многие ко многим» в модели, которая определяет отношение (в данном случае, Group). Если вы хотите использовать встроенную модель для представления отношения «многие ко многим», вы должны указать Django, чтобы он *не* отображал этот виджет — в противном случае у вас на странице администрирования будет два виджета для управления отношением.

Обратите внимание, что при использовании этого метода сигналы m2m_changed не срабатывают. Это потому, что, с точки зрения администрирования, through — это просто модель с двумя полями внешнего ключа, а не отношение «многие ко многим».

Во всех остальных аспектах, InlineModelAdmin ничем не отличается от других. Вы можете настроить его внешний вид, используя любые стандартные ModelAdmin свойства.

Работа с промежуточными моделями "многие ко многим"

При указании промежуточной модели с помощью аргумента through для ManyToManyField, администрирование по умолчанию не отобразит виджет. Это связано с тем, что каждый экземпляр этой промежуточной модели требует больше информации, чем может быть отображено в одном виджете, а необходимая для нескольких виджетов компоновка будет различаться в зависимости от промежуточной модели.

Однако мы по-прежнему хотим иметь возможность редактировать эту информацию встроенным способом. К счастью, это можно сделать с помощью встроенных моделей администрирования. Предположим, у нас есть следующие модели:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

Первый шаг для отображения этой промежуточной модели в администрировании — определить встроенный класс для модели Membership:

class MembershipInline(admin.TabularInline):
    model = Membership
    extra = 1

В этом примере используются значения по умолчанию InlineModelAdmin для модели Membership, и ограничивается количество дополнительных форм добавления одной. Это можно настроить с помощью любого из доступных вариантов для классов InlineModelAdmin.

Теперь создайте представления администрирования для моделей Person и Group:

class PersonAdmin(admin.ModelAdmin):
    inlines = (MembershipInline,)

class GroupAdmin(admin.ModelAdmin):
    inlines = (MembershipInline,)

Наконец, зарегистрируйте ваши модели Person и Group в сайте администрирования:

admin.site.register(Person, PersonAdmin)
admin.site.register(Group, GroupAdmin)

Теперь ваш сайт администрирования настроен для редактирования объектов Membership встроенным способом из страниц деталей Person или Group.

Использование обобщенных отношений как встроенного элемента

Возможно использовать встроенный элемент с обобщенно связанными объектами. Предположим, у вас есть следующие модели:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.db import models

class Image(models.Model):
    image = models.ImageField(upload_to="images")
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")

class Product(models.Model):
    name = models.CharField(max_length=100)

Если вы хотите разрешить редактирование и создание экземпляра Image на страницах изменения/добавления Product, вы можете использовать GenericTabularInline или GenericStackedInline (оба являются подклассами GenericInlineModelAdmin), предоставляемыми admin. Они реализуют табличные и сточные визуальные макеты для форм, представляющих встроенные объекты, соответственно, точно так же, как и их необобщенные аналоги. Они ведут себя как любые другие встроенные элементы. В вашем admin.py для этого приложения:

from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline

from 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/ нашего проекта и внесли необходимые изменения.

Если мы хотели добавить инструмент в представление списка изменений только для определенной модели с именем «Страница», мы бы скопировали тот же файл в каталог templates/admin/my_app/page нашего проекта.

Переопределение против замещения шаблона администрирования

Из-за модульной структуры шаблонов администрирования обычно не нужно и не рекомендуется заменять весь шаблон. Почти всегда лучше переопределить только ту часть шаблона, которую необходимо изменить.

Продолжая пример выше, мы хотим добавить новую ссылку рядом с инструментом History для модели Page. После изучения change_form.html мы определяем, что нам нужно только переопределить блок object-tools-items. Поэтому вот наш новый шаблон change_form.html:

{% extends "admin/change_form.html" %}
{% load i18n admin_urls %}
{% block object-tools-items %}
    <li>
        <a href="{% url opts|admin_urlname:'history' original.pk|admin_urlquote %}" class="historylink">{% translate "History" %}</a>
    </li>
    <li>
        <a href="mylink/" class="historylink">My Link</a>
    </li>
    {% if has_absolute_url %}
        <li>
            <a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% translate "View on site" %}</a>
        </li>
    {% endif %}
{% endblock %}

И это всё! Если мы разместили этот файл в каталоге templates/admin/my_app , наша ссылка появится в форме изменения для всех моделей в приложении my_app.

Шаблоны, которые можно переопределить по приложению или модели

Не каждый шаблон в contrib/admin/templates/admin может быть переопределен по приложению или по модели. Следующие можно:

  • actions.html
  • app_index.html
  • change_form.html
  • change_form_object_tools.html
  • change_list.html
  • change_list_object_tools.html
  • change_list_results.html
  • date_hierarchy.html
  • delete_confirmation.html
  • object_history.html
  • pagination.html
  • popup_response.html
  • prepopulated_fields_js.html
  • search_form.html
  • submit_line.html

Для тех шаблонов, которые нельзя переопределить таким образом, вы всё ещё можете переопределить их для всего проекта, поместив новую версию в ваш каталог templates/admin. Это особенно полезно для создания пользовательских страниц 404 и 500.

Примечание

Некоторые шаблоны администрирования, такие как change_list_results.html используются для рендеринга пользовательских тегов включения. Их можно переопределить, но в таких случаях, вероятно, лучше создать свою версию интересующего тега и дать ему другое имя. Таким образом, вы можете использовать его выборочно.

Шаблоны корневой и входной страниц

Если вы хотите изменить шаблоны индекса, входа или выхода, вам лучше создать свой собственный экземпляр AdminSite (см. ниже) и изменить свойства AdminSite.index_template , AdminSite.login_template или AdminSite.logout_template.

Поддержка оформления

Администрирование использует переменные CSS для определения цветов. Это позволяет изменять цвета без необходимости переопределения многих отдельных правил CSS. Например, если вы предпочитаете фиолетовый вместо синего, вы можете добавить переопределение шаблона admin/base.html в свой проект:

{% extends 'admin/base.html' %}

{% block extrastyle %}{{ block.super }}
<style>
:root {
  --primary: #9774d5;
  --secondary: #785cab;
  --link-fg: #7c449b;
  --link-selected-fg: #8f5bb2;
}
</style>
{% endblock %}

Список переменных CSS определён в django/contrib/admin/static/admin/css/base.css.

Переменные тёмной темы, учитывающие медиа-запрос prefers-color-scheme, определены в django/contrib/admin/static/admin/css/dark_mode.css. Эта ссылка связана с документом в {% block dark-mode-vars %}.

Изменено в Django 4.1:

Переменные тёмной темы были перемещены в отдельный файл стилей и блок шаблона.

AdminSite объекты

class AdminSite(name='admin')

Сайт администратора Django представлен экземпляром django.contrib.admin.sites.AdminSite; по умолчанию, создается экземпляр этого класса как django.contrib.admin.site, и вы можете зарегистрировать ваши модели и экземпляры ModelAdmin с ним.

Если вы хотите настроить сайт администратора по умолчанию, вы можете переопределить его.

При создании экземпляра AdminSite, вы можете указать уникальное имя экземпляра, используя аргумент name конструктора. Это имя экземпляра используется для идентификации экземпляра, особенно при обращении к URL-адресам администратора. Если имя экземпляра не указано, используется имя по умолчанию admin. См. Настройка класса AdminSite для примера настройки класса AdminSite.

AdminSite атрибуты

Шаблоны могут переопределять или расширять базовые шаблоны администратора, как описано в Переопределении шаблонов администратора.

AdminSite.site_header

Текст, отображаемый вверху каждой страницы администратора, как <h1> (строка). По умолчанию это “Django administration”.

AdminSite.site_title

Текст, отображаемый внизу каждой страницы администратора, как <title> (строка). По умолчанию это “Django site admin”.

AdminSite.site_url

URL-адрес ссылки «Просмотреть сайт» вверху каждой страницы администратора. По умолчанию, site_url это /. Установите его в None для удаления ссылки.

Для сайтов, работающих на подпути, метод each_context() проверяет, установлен ли request.META['SCRIPT_NAME'] в текущем запросе, и использует это значение, если site_url не установлено на значение, отличное от /.

AdminSite.index_title

Текст, отображаемый вверху страницы индекса администратора (строка). По умолчанию это “Site administration”.

AdminSite.index_template

Путь к пользовательскому шаблону, который будет использоваться главной страницей индекса сайта администратора.

AdminSite.app_index_template

Путь к пользовательскому шаблону, который будет использоваться страницей индекса приложения сайта администратора.

AdminSite.empty_value_display

Строка, используемая для отображения пустых значений в списке изменений сайта администратора. По умолчанию - дефис. Значение также может быть переопределено для каждого ModelAdmin и в пользовательском поле в ModelAdmin путем установки атрибута empty_value_display в поле. См. ModelAdmin.empty_value_display для примеров.

AdminSite.enable_nav_sidebar

Булево значение, определяющее, отображать ли боковую панель навигации на больших экранах. По умолчанию, оно установлено в True.

AdminSite.final_catch_all_view

Булево значение, определяющее, добавлять ли финальный обработчик всех запросов в администратора, перенаправляющий неавторизованных пользователей на страницу входа. По умолчанию, оно установлено в True.

Предупреждение

Не рекомендуется устанавливать это значение в False так как этот обработчик защищает от потенциальной проблемы с конфиденциальностью перечисления моделей.

AdminSite.login_template

Путь к пользовательскому шаблону, который будет использоваться при входе на сайт администратора.

AdminSite.login_form

Подкласс AuthenticationForm, который будет использоваться при входе на сайт администратора.

AdminSite.logout_template

Путь к пользовательскому шаблону, который будет использоваться при выходе из сайта администратора.

AdminSite.password_change_template

Путь к пользовательскому шаблону, который будет использоваться при смене пароля на сайте администратора.

AdminSite.password_change_done_template

Путь к пользовательскому шаблону, который будет использоваться после успешной смены пароля на сайте администратора.

AdminSite методы

AdminSite.each_context(request)

Возвращает словарь переменных для контекста шаблона для каждой страницы сайта администратора.

По умолчанию включает следующие переменные и значения:

  • site_header: AdminSite.site_header
  • site_title: AdminSite.site_title
  • site_url: AdminSite.site_url
  • has_permission: AdminSite.has_permission()
  • available_apps: список приложений из реестра приложений, доступных текущему пользователю. Каждый элемент списка — словарь, представляющий приложение с следующими ключами:

    • app_label: метка приложения
    • app_url: URL-адрес страницы индекса приложения в администраторе
    • has_module_perms: булево значение, указывающее, разрешен ли просмотр и доступ к странице индекса модуля для текущего пользователя
    • models: список моделей, доступных в приложении

    Каждая модель — словарь со следующими ключами:

    • model: класс модели
    • object_name: имя класса модели
    • name: множественное число имени модели
    • perms: dict отслеживающий add, change, delete, и view разрешения
    • admin_url: URL-адрес списка изменений администратора для модели
    • add_url: URL-адрес администратора для добавления новой модели
Изменено в Django 4.0:

Была добавлена переменная model для каждой модели.

END_OF_DOCUMENT_MARKER
AdminSite.get_app_list(request, app_label=None)

Возвращает список приложений из реестра приложений, доступных для текущего пользователя. Вы можете необязательно передать аргумент app_label для получения подробностей по одному приложению. Каждая запись в списке — это словарь, представляющий приложение с следующими ключами:

  • app_label: метка приложения
  • app_url: URL-адрес страницы индекса приложения в админке
  • has_module_perms: логическое значение, указывающее, разрешен ли просмотр и доступ к странице индекса модуля для текущего пользователя
  • models: список моделей, доступных в приложении
  • name: имя приложения

Каждая модель — это словарь со следующими ключами:

  • model: класс модели
  • object_name: имя класса модели
  • name: множественное число имени модели
  • perms: отслеживание dict add, change, delete, и view разрешений
  • admin_url: URL-адрес списка изменений админки для модели
  • add_url: URL-адрес админки для добавления новой записи модели

Списки приложений и моделей отсортированы по именам в алфавитном порядке. Вы можете переопределить этот метод, чтобы изменить порядок по умолчанию на странице индекса админки.

Изменено в Django 4.1:

Был добавлен аргумент app_label.

AdminSite.has_permission(request)

Возвращает True, если у пользователя для данного HttpRequest есть разрешение на просмотр хотя бы одной страницы в админке. По умолчанию требует, чтобы оба User.is_active и User.is_staff были True.

AdminSite.register(model_or_iterable, admin_class=None, **options)

Регистрирует указанный класс модели (или итерируемый список классов) с указанным admin_class. По умолчанию admin_class равен ModelAdmin (настройки админки по умолчанию). Если указаны именованные аргументы, например list_display, они будут применяться в качестве опций к классу админки.

Возбуждает ImproperlyConfigured, если модель абстрактная, и django.contrib.admin.sites.AlreadyRegistered если модель уже зарегистрирована.

AdminSite.unregister(model_or_iterable)

Удаляет регистрацию указанного класса модели (или итерируемого списка классов).

Возбуждает django.contrib.admin.sites.NotRegistered если модель не зарегистрирована.

Подключение экземпляров AdminSite в ваш URLconf

Последний шаг настройки Django админки — подключить ваш экземпляр AdminSite в ваш URLconf. Сделайте это, указав URL для метода AdminSite.urls. Необязательно использовать include().

В этом примере мы регистрируем стандартный экземпляр AdminSite django.contrib.admin.site по адресу /admin/

# urls.py
from django.contrib import admin
from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]

Настройка класса AdminSite

Если вы хотите создать свой сайт админки со своими настройками, вы можете наследовать AdminSite и переопределить или добавить необходимые элементы. Затем создайте экземпляр вашего класса AdminSite (так же, как вы создаёте любой другой Python класс) и зарегистрируйте ваши модели и ModelAdmin подклассы с ним, а не со стандартным сайтом. Наконец, обновите myproject/urls.py для ссылки на ваш подкласс AdminSite.

myapp/admin.py
from django.contrib import admin

from .models import MyModel

class MyAdminSite(admin.AdminSite):
    site_header = 'Monty Python administration'

admin_site = MyAdminSite(name='myadmin')
admin_site.register(MyModel)
myproject/urls.py
from django.urls import path

from myapp.admin import admin_site

urlpatterns = [
    path('myadmin/', admin_site.urls),
]

Обратите внимание, что при использовании собственного экземпляра AdminSite вам, вероятно, не нужна автоматическая загрузка модулей admin, так как вы, скорее всего, импортируете все модули admin для каждого приложения в вашем модуле myproject.admin. Это означает, что нужно указать 'django.contrib.admin.apps.SimpleAdminConfig' вместо 'django.contrib.admin' в настройке INSTALLED_APPS.

Переопределение стандартного сайта админки

Вы можете переопределить стандартный django.contrib.admin.site установив атрибут default_site пользовательского AppConfig на путь импорта AdminSite подкласса или вызываемого объекта, возвращающего экземпляр сайта.

myproject/admin.py
from django.contrib import admin

class MyAdminSite(admin.AdminSite):
    ...
myproject/apps.py
from django.contrib.admin.apps import AdminConfig

class MyAdminConfig(AdminConfig):
    default_site = 'myproject.admin.MyAdminSite'
myproject/settings.py
INSTALLED_APPS = [
    ...
    'myproject.apps.MyAdminConfig',  # replaces 'django.contrib.admin'
    ...
]

Несколько сайтов админки в одном URLconf

Вы можете создать несколько экземпляров сайта админки на одном сайте Django. Создайте несколько экземпляров AdminSite и разместите каждый по отдельному URL.

В этом примере URL /basic-admin/ и /advanced-admin/ содержат отдельные версии сайта админки, использующие экземпляры AdminSite myproject.admin.basic_site и myproject.admin.advanced_site, соответственно:

# urls.py
from django.urls import path
from myproject.admin import advanced_site, basic_site

urlpatterns = [
    path('basic-admin/', basic_site.urls),
    path('advanced-admin/', advanced_site.urls),
]

Экземпляры AdminSite принимают один аргумент в конструктор — имя, которое может быть любым. Этот аргумент становится префиксом для имён URL для целей обратного перевода. Это необходимо только если вы используете более одного AdminSite.

Добавление представлений в сайты админки

Как и ModelAdmin, AdminSite предоставляет метод get_urls(), который можно переопределить для определения дополнительных представлений для сайта. Чтобы добавить новое представление в свой сайт админки, расширьте метод get_urls() и включите шаблон для вашего нового представления.

Примечание

Любое представление, которое использует шаблоны админки или расширяет базовый шаблон админки, должно задать request.current_app перед рендерингом шаблона. Оно должно быть установлено либо в self.name, если ваше представление находится на странице AdminSite, либо в self.admin_site.name если ваше представление находится на странице ModelAdmin.

Добавление функции сброса пароля

Вы можете добавить функцию сброса пароля в сайт админки, добавив несколько строк в ваш URLconf. Конкретно, добавьте эти четыре шаблона:

from django.contrib.auth import views as auth_views

path(
    'admin/password_reset/',
    auth_views.PasswordResetView.as_view(),
    name='admin_password_reset',
),
path(
    'admin/password_reset/done/',
    auth_views.PasswordResetDoneView.as_view(),
    name='password_reset_done',
),
path(
    'reset/<uidb64>/<token>/',
    auth_views.PasswordResetConfirmView.as_view(),
    name='password_reset_confirm',
),
path(
    'reset/done/',
    auth_views.PasswordResetCompleteView.as_view(),
    name='password_reset_complete',
),

(Предполагается, что вы добавили админку по адресу admin/ и необходимо расположить URL, начинающиеся с ^admin/ перед строкой, включающей сам модуль админки).

Наличие admin_password_reset URL вызовет появление ссылки «забыли пароль?» на стандартной странице входа в админку под полем пароля.

LogEntry объекты

class models.LogEntry

Класс LogEntry отслеживает добавления, изменения и удаления объектов, выполненные через интерфейс админки.

LogEntry атрибуты

LogEntry.action_time

Дата и время действия.

LogEntry.user

Пользователь (экземпляр AUTH_USER_MODEL), выполнивший действие.

LogEntry.content_type

Тип содержимого ContentType изменённого объекта.

LogEntry.object_id

Текстовое представление первичного ключа изменённого объекта.

LogEntry.object_repr

Представление объекта repr() после изменения.

LogEntry.action_flag

Тип зарегистрированного действия: ADDITION, CHANGE, DELETION.

Например, чтобы получить список всех добавлений, выполненных через админ-панель:

from django.contrib.admin.models import ADDITION, LogEntry

LogEntry.objects.filter(action_flag=ADDITION)
LogEntry.change_message

Подробное описание изменения. В случае редактирования, например, сообщение содержит список изменённых полей. Сайт Django Admin форматирует это содержимое как JSON-структуру, чтобы get_change_message() мог пересобрать сообщение на языке текущего пользователя. Однако пользовательский код может установить его как обычную строку. Вам рекомендуется использовать метод get_change_message() для получения этого значения вместо прямого доступа к нему.

LogEntry методы

LogEntry.get_edited_object()

Сокращённая функция, которая возвращает ссылку на объект.

LogEntry.get_change_message()

Форматирует и переводит change_message на язык текущего пользователя. Сообщения, созданные до Django 1.10, всегда будут отображаться на языке, на котором они были записаны.

Обращение к URL-адресам админки

Когда AdminSite развернут, к представленным им видам можно получить доступ с помощью системы обратного поиска URL-адресов Django.

AdminSite предоставляет следующие именованные URL-шаблоны:

Страница Имя URL Параметры
Главная index
Вход login
Выход logout
Смена пароля password_change
Смена пароля выполнена password_change_done
JavaScript для i18n 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, а также в пространстве имён экземпляра, соответствующем имени экземпляра Site.

Итак, если вам нужно получить ссылку на представление Change для конкретного объекта Choice (из приложения polls) в стандартной админке, вы вызовите:

>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,))

Это найдёт первый зарегистрированный экземпляр приложения админки (какое угодно имя экземпляра) и обратится к представлению для изменения объектов poll.Choice в этом экземпляре.

Если вам нужно найти URL в определённом экземпляре админки, укажите имя этого экземпляра в качестве подсказки для обратного вызова. Например, если вам нужен административный вид из экземпляра админки под названием custom, вам нужно вызвать:

>>> change_url = reverse('admin:polls_choice_change', args=(c.id,), current_app='custom')

Дополнительную информацию см. в документации по обращению к именованным URL-адресам.

Чтобы облегчить обращение к URL-адресам админки в шаблонах, Django предоставляет фильтр admin_urlname, который принимает действие в качестве аргумента:

{% load admin_urls %}
<a href="{% url opts|admin_urlname:'add' %}">Add user</a>
<a href="{% url opts|admin_urlname:'delete' user.pk %}">Delete this user</a>

Действие в приведённых примерах соответствует последней части имён URL-адресов для экземпляров ModelAdmin, описанных выше. Переменная opts может быть любым объектом, имеющим атрибуты app_label и model_name, и обычно предоставляется представлениями админки для текущей модели.

Декоратор display

display(*, boolean=None, ordering=None, description=None, empty_value=None)

Этот декоратор может быть использован для установки определённых атрибутов в пользовательских функциях отображения, которые могут быть использованы с list_display или readonly_fields:

@admin.display(
    boolean=True,
    ordering='-publish_date',
    description='Is Published?',
)
def is_published(self, obj):
    return obj.publish_date is not None

Это эквивалентно установке некоторых атрибутов (с исходными, более длинными именами) непосредственно на функции:

def is_published(self, obj):
    return obj.publish_date is not None
is_published.boolean = True
is_published.admin_order_field = '-publish_date'
is_published.short_description = 'Is Published?'

Также обратите внимание, что параметр декоратора empty_value отображается в атрибуте empty_value_display, назначаемом непосредственно функции. Он не может быть использован совместно с boolean — они взаимоисключающие.

Использование этого декоратора не обязательно для создания функции отображения, но может быть полезно использовать его без аргументов как метку в вашем коде, чтобы определить назначение функции:

@admin.display
def published_year(self, obj):
    return obj.publish_date.year

В этом случае он не добавит никаких атрибутов к функции.

Декоратор staff_member_required

staff_member_required(redirect_field_name='next', login_url='admin:login')

Этот декоратор используется для представлений админки, требующих авторизации. Представление, украшенное этой функцией, будет вести себя следующим образом:

  • Если пользователь авторизован, является сотрудником (User.is_staff=True) и активен (User.is_active=True), выполнение представления происходит в обычном режиме.
  • В противном случае запрос будет перенаправлен на URL, указанный параметром login_url, с исходным запрошенным путём в переменной запроса, заданной параметром redirect_field_name. Например: /admin/login/?next=/admin/polls/question/3/.

Пример использования:

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
def my_view(request):
    ...

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.1/ref/contrib/admin/index/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API