Spec-Zone.ru › Django 3.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.

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

    django.template.context_processors.request был добавлен как требование в опцию 'context_processors' для поддержки нового AdminSite.enable_nav_sidebar.

  3. Если вы настроили значение MIDDLEWARE, django.contrib.auth.middleware.AuthenticationMiddleware и django.contrib.messages.middleware.MessageMiddleware должны быть включены.
  4. Подключите URL-адреса администрирования к вашему URLconf.

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

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

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

Другие темы

  • Действия администрирования
  • Генератор документации для Django администрирования
  • Настройка JavaScript в администрировании

См. также

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

Есть проблемы? Попробуйте Вопросы и ответы: Администрирование.

ModelAdmin объекты

class ModelAdmin

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

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

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

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

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

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

admin.site.register(Author)

Декоратор register

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

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

from django.contrib import admin
from .models import Author

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

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

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

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

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

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

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

class apps.AdminConfig

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

class apps.SimpleAdminConfig

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

default_site

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

autodiscover()

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

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

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

ModelAdmin опции

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

from django.contrib import admin

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

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

ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom

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

ModelAdmin.actions_selection_counter

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

ModelAdmin.date_hierarchy

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

Пример:

date_hierarchy = 'pub_date'

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

date_hierarchy = 'author__pub_date'

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

Примечание

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

ModelAdmin.empty_value_display

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

from django.contrib import admin

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

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

from django.contrib import admin

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

    def view_birth_date(self, obj):
        return obj.birth_date

    view_birth_date.empty_value_display = '???'
ModelAdmin.exclude

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

Например, рассмотрим следующую модель:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3)
    birth_date = models.DateField(blank=True, null=True)

Если вы хотите форму для модели Author, которая включает только поля name и title, вы должны указать fields или exclude следующим образом:

from django.contrib import admin

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

class AuthorAdmin(admin.ModelAdmin):
    exclude = ('birth_date',)

Поскольку модель Author имеет только три поля, name, title, и birth_date, формы, полученные из вышеупомянутых объявлений, будут содержать точно такие же поля.

ModelAdmin.fields

Используйте опцию fields для внесения простых изменений в макет форм на страницах «Добавить» и «Изменить», таких как отображение только подмножества доступных полей, изменение их порядка или группировка их в строки. Например, вы можете определить упрощённую версию формы администрирования для модели django.contrib.flatpages.models.FlatPage следующим образом:

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

В приведённом примере будут отображаться только поля url, title и content, последовательно, в форме. fields может содержать значения, определённые в ModelAdmin.readonly_fields, для отображения в режиме только для чтения.

Для более сложных потребностей в макете см. опцию fieldsets.

Опция fields принимает те же типы значений, что и list_display, за исключением того, что вызовы не принимаются. Имена методов модели и модели администрирования будут использоваться только в том случае, если они перечислены в 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:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Однако, если элемент list_display представляет собой определённое поле базы данных, вы можете указать этот факт, установив атрибут admin_order_field элемента.

    Например:

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

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

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

    colored_first_name.admin_order_field = '-first_name'
    

    admin_order_field поддерживает поисковые запросы для сортировки по значениям в связанных моделях. Этот пример включает столбец «имя автора» в отображении списка и позволяет сортировать его по имени:

    class Blog(models.Model):
        title = models.CharField(max_length=255)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)
    
    class BlogAdmin(admin.ModelAdmin):
        list_display = ('title', 'author', 'author_first_name')
    
        def author_first_name(self, obj):
            return obj.author.first_name
    
        author_first_name.admin_order_field = 'author__first_name'
    

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

    from django.db.models import Value
    from django.db.models.functions import Concat
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        def full_name(self):
            return self.first_name + ' ' + self.last_name
        full_name.admin_order_field = Concat('first_name', Value(' '), 'last_name')
    
  • Элементы list_display также могут быть свойствами. Однако обратите внимание, что из-за того, как работают свойства в Python, установка short_description или admin_order_field на свойство возможна только при использовании функции property() и не с декоратором @property.

    Например:

    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        def my_property(self):
            return self.first_name + ' ' + self.last_name
        my_property.short_description = "Full name of the person"
        my_property.admin_order_field = 'last_name'
    
        full_name = property(my_property)
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('full_name',)
    
  • Имена полей в list_display также будут отображаться как CSS-классы в HTML-выводе в виде column-<field_name> в каждом элементе <th>. Это можно использовать, например, для настройки ширины столбцов в файле CSS.
  • Django будет пытаться интерпретировать каждый элемент list_display в таком порядке:

    • Поле модели.
    • Вызываемый объект.
    • Строка, представляющая атрибут ModelAdmin.
    • Строка, представляющая атрибут модели.

    Например, если у вас есть first_name как поле модели и как атрибут ModelAdmin, будет использоваться поле модели.

ModelAdmin.list_display_links

Используйте list_display_links для управления тем, какие поля в list_display должны быть связаны со страницей «изменить» объекта.

По умолчанию, страница списка изменений будет связывать первый столбец — первое поле, указанное в list_display — со страницей изменения каждого элемента. Но list_display_links позволяет это изменить:

  • Установите его в значение None для отключения ссылок вообще.
  • Установите его в список или кортеж полей (в том же формате, что и list_display) , столбцы которых вы хотите преобразовать в ссылки.

    Вы можете указать одно или несколько полей. Пока поля появляются в list_display, Django не важно, сколько (или как мало) полей связаны ссылками. Единственное требование состоит в том, что если вы хотите использовать list_display_links таким образом, вам необходимо определить list_display.

В этом примере поля first_name и last_name будут связаны на странице списка изменений:

class PersonAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'birthday')
    list_display_links = ('first_name', 'last_name')

В этом примере на странице списка изменений не будет ссылок:

class AuditEntryAdmin(admin.ModelAdmin):
    list_display = ('timestamp', 'message')
    list_display_links = None
ModelAdmin.list_editable

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

Примечание

list_editable взаимодействует с некоторыми другими параметрами определённым образом; обратите внимание на следующие правила:

  • Любое поле в list_editable также должно быть в list_display. Вы не можете редактировать поле, которое не отображается!
  • Одно и то же поле не может быть указано как в list_editable, так и в list_display_links — поле не может быть одновременно элементом формы и ссылкой.

Если нарушены эти правила, вы получите ошибку валидации.

ModelAdmin.list_filter

Установите list_filter для активации фильтров в правой боковой панели страницы списка изменений администратора, как показано на следующем снимке экрана:

../../../_images/list_filter.png

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

  • имя поля, где указанное поле должно быть либо BooleanField, CharField, DateField, DateTimeField, IntegerField, ForeignKey или ManyToManyField, например:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = ('is_staff', 'company')
    

    Имена полей в list_filter также могут охватывать отношения с использованием __ lookup, например:

    class PersonAdmin(admin.UserAdmin):
        list_filter = ('company__name',)
    
  • класс, наследуемый от django.contrib.admin.SimpleListFilter, для которого вы должны предоставить title и parameter_name атрибуты и переопределить lookups и queryset методы, например:

    from datetime import date
    
    from django.contrib import admin
    from django.utils.translation import gettext_lazy as _
    
    class DecadeBornListFilter(admin.SimpleListFilter):
        # Human-readable title which will be displayed in the
        # right admin sidebar just above the filter options.
        title = _('decade born')
    
        # Parameter for the filter that will be used in the URL query.
        parameter_name = 'decade'
    
        def lookups(self, request, model_admin):
            """
            Returns a list of tuples. The first element in each
            tuple is the coded value for the option that will
            appear in the URL query. The second element is the
            human-readable name for the option that will appear
            in the right sidebar.
            """
            return (
                ('80s', _('in the eighties')),
                ('90s', _('in the nineties')),
            )
    
        def queryset(self, request, queryset):
            """
            Returns the filtered queryset based on the value
            provided in the query string and retrievable via
            `self.value()`.
            """
            # Compare the requested value (either '80s' or '90s')
            # to decide how to filter the queryset.
            if self.value() == '80s':
                return queryset.filter(birthday__gte=date(1980, 1, 1),
                                        birthday__lte=date(1989, 12, 31))
            if self.value() == '90s':
                return queryset.filter(birthday__gte=date(1990, 1, 1),
                                        birthday__lte=date(1999, 12, 31))
    
    class PersonAdmin(admin.ModelAdmin):
        list_filter = (DecadeBornListFilter,)
    

    Примечание

    Для удобства объект HttpRequest передаётся методам lookups и queryset, например:

    class AuthDecadeBornListFilter(DecadeBornListFilter):
    
        def lookups(self, request, model_admin):
            if request.user.is_superuser:
                return super().lookups(request, model_admin)
    
        def queryset(self, request, queryset):
            if request.user.is_superuser:
                return super().queryset(request, queryset)
    

    Также для удобства объект ModelAdmin передаётся методу lookups, например, если вы хотите базировать выборки на доступных данных:

    class AdvancedDecadeBornListFilter(DecadeBornListFilter):
    
        def lookups(self, request, model_admin):
            """
            Only show the lookups if there actually is
            anyone born in the corresponding decades.
            """
            qs = model_admin.get_queryset(request)
            if qs.filter(birthday__gte=date(1980, 1, 1),
                          birthday__lte=date(1989, 12, 31)).exists():
                yield ('80s', _('in the eighties'))
            if qs.filter(birthday__gte=date(1990, 1, 1),
                          birthday__lte=date(1999, 12, 31)).exists():
                yield ('90s', _('in the nineties'))
    
  • кортеж, где первый элемент — имя поля, а второй — класс, наследуемый от django.contrib.admin.FieldListFilter, например:

    class PersonAdmin(admin.ModelAdmin):
        list_filter = (
            ('is_staff', admin.BooleanFieldListFilter),
        )
    

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

    class BookAdmin(admin.ModelAdmin):
        list_filter = (
            ('author', admin.RelatedOnlyFieldListFilter),
        )
    

    Предполагая, что author является ForeignKey к модели User, это ограничит выбор list_filter пользователями, которые написали книгу вместо перечисления всех пользователей.

    Вы можете отфильтровать пустые значения с помощью EmptyFieldListFilter, который может фильтровать как пустые строки, так и null, в зависимости от того, что поле позволяет хранить:

    class BookAdmin(admin.ModelAdmin):
        list_filter = (
            ('title', admin.EmptyFieldListFilter),
        )
    

    Примечание

    API FieldListFilter считается внутренним и может быть изменён.

    Примечание

    Поле GenericForeignKey не поддерживается.

    Введено в Django 3.1:

    Класс EmptyFieldListFilter был добавлен.

Фильтры списка обычно отображаются только если фильтр имеет более одного варианта. Метод has_output() фильтра определяет, отображается ли он или нет.

Можно указать пользовательский шаблон для рендеринга фильтра списка:

class FilterWithCustomTemplate(admin.SimpleListFilter):
    template = "custom_template.html"

См. предоставленный Django по умолчанию шаблон (admin/filter.html) для конкретного примера.

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

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

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

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

Примечание

ModelAdmin игнорирует этот атрибут, когда select_related() уже был вызван на QuerySet 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 букв к нижнему регистру и удаление различных английских стоп-слов, таких как ‘a’, ‘an’, ‘as’ и аналогичных).

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

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

ModelAdmin.preserve_filters

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

ModelAdmin.radio_fields

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

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

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

Не включайте поле в radio_fields если оно не является ForeignKey или не имеет choices заданным.

ModelAdmin.autocomplete_fields

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ModelAdmin.raw_id_fields

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

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

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

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

../../../_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',)

    def address_report(self, instance):
        # assuming get_full_address() returns a list of strings
        # for each line of the address and you want to separate each
        # line by a linebreak
        return format_html_join(
            mark_safe('<br>'),
            '{}',
            ((line,) for line in instance.get_full_address()),
        ) or mark_safe("<span class='errors'>I can't determine this address.</span>")

    # short_description functions like a model field's verbose_name
    address_report.short_description = "Address"
ModelAdmin.save_as

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

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

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

ModelAdmin.save_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 (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

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

Обратите внимание, что поскольку поисковые термины разделены и объединены с помощью AND, как описано ранее, поиск с помощью exact работает только с одним поисковым словом, так как два или более слова не могут быть точным совпадением, если все слова не одинаковы.

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

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

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

ModelAdmin.show_full_result_count

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

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

ModelAdmin.sortable_by

По умолчанию страница списка изменений позволяет сортировать по всем полям модели (и вызовам, которые имеют свойство 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

Настраиваемые параметры шаблона

Раздел Замена шаблонов администратора описывает, как заменить или расширить стандартные шаблоны администратора. Используйте следующие параметры для замены стандартных шаблонов, используемых представлениями 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 к каждому изменённому экземпляру модели formset:

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

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

ModelAdmin.get_ordering(request)

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

class PersonAdmin(admin.ModelAdmin):

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

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

По умолчанию поиск выполняется по полям, перечисленным в ModelAdmin.search_fields.

Этот метод можно переопределить, чтобы реализовать свой собственный метод поиска. Например, вы можете выполнить поиск по целочисленному полю или использовать внешний инструмент, такой как Solr или Haystack. Вы должны определить, может ли реализованный вами метод поиска вносить дубликаты в результаты, и возвратить True во втором элементе возвращаемого значения.

Например, чтобы выполнить поиск по name и age, можно использовать:

class PersonAdmin(admin.ModelAdmin):
    list_display = ('name', 'age')
    search_fields = ('name',)

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
        try:
            search_term_as_int = int(search_term)
        except ValueError:
            pass
        else:
            queryset |= self.model.objects.filter(age=search_term_as_int)
        return queryset, use_distinct

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

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

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

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. Например, следующее вернёт inline-объекты без стандартной фильтрации на основе разрешений на добавление, изменение, удаление и просмотр:

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

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

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

ModelAdmin.get_inlines(request, obj)
Новое в Django 3.0.

Метод get_inlines получает HttpRequest и obj, которые редактируются (или None в форме добавления), и ожидается, что он вернёт итерируемый объект inline-объектов. Вы можете переопределить этот метод, чтобы динамически добавлять inline-объекты на основе запроса или экземпляра модели вместо их указания в 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 зарегистрированная выше, имеет две проблемы:

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

Поскольку это обычно не то, что вам нужно, 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(), чтобы убедиться, что он не будет кэширован, если активен кэширующий middleware.

Если страница кэшируема, но вы всё равно хотите, чтобы выполнялась проверка разрешений, вы можете передать аргумент 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__() для фильтрации по экземпляру вашей модели (см. Поля, обрабатывающие отношения). Например:

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. Чтобы использовать пользовательский formset, например:

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
    pass

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

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

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

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

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

ModelAdmin.has_view_permission(request, obj=None)

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

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

ModelAdmin.has_add_permission(request)

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

ModelAdmin.has_change_permission(request, obj=None)

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

ModelAdmin.has_delete_permission(request, obj=None)

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

ModelAdmin.has_module_permission(request)

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

ModelAdmin.get_queryset(request)

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

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

Отправляет сообщение пользователю с помощью бэкенда django.contrib.messages. См. пример настраиваемого 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_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_plural каждой модели с количеством объектов, которые будут удалены.

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

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

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

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

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

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

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

ModelAdmin.changelist_view(request, extra_context=None)

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

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

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

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

Django-представление для страницы, отображающей историю изменений для данного экземпляра модели.

В отличие от методов типа 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-администратор JavaScript использует библиотеку jQuery.

Чтобы избежать конфликтов с пользовательскими скриптами или библиотеками, Django’s jQuery (версия 3.5.1) имеет пространство имён django.jQuery. Если вы хотите использовать jQuery в собственном JavaScript администратора без включения второй копии, вы можете использовать объект django.jQuery в представлениях списка, добавления и редактирования.

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

jQuery был обновлён с версии 3.3.1 до 3.4.1.

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

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

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

Django предоставляет как нескомпрессированные, так и ‘скомпрессированные’ версии jQuery, как jquery.js и jquery.min.js соответственно.

ModelAdmin и InlineModelAdmin имеют свойство media, которое возвращает список объектов Media, хранящих пути к файлам JavaScript для форм и/или наборов форм. Если DEBUG равно True, будет возвращена нескомпрессированная версия различных файлов JavaScript, включая jquery.js; в противном случае — ‘скомпрессированные’ версии.

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

Вы также можете добавить пользовательскую валидацию данных в администратор. Автоматический интерфейс администратора использует django.forms, и класс ModelAdmin позволяет определить собственную форму:

class ArticleAdmin(admin.ModelAdmin):
    form = MyArticleAdminForm

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

class MyArticleAdminForm(forms.ModelForm):
    def clean_name(self):
        # do something that validates your data
        return self.cleaned_data["name"]

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

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.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
END_OF_DOCUMENT_MARKER
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,
    ]

Работа с моделями many-to-many

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

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

from django.db import models

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

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

Если вы хотите отобразить отношения many-to-many с помощью инлайна, вы можете сделать это, определив объект 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 — это ссылка на модель, которая управляет отношением many-to-many. Эта модель автоматически создается Django при определении поля many-to-many.

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

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

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

Работа с промежуточными моделями many-to-many

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

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

from django.db import models

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

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

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

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

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

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

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

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

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

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

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

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

Использование общих отношений в качестве инлайна

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

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

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

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

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

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

from myproject.myapp.models import Image, Product

class ImageInline(GenericTabularInline):
    model = Image

class ProductAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]

admin.site.register(Product, ProductAdmin)

См. документацию по contenttypes для более подробной информации.

Настройка шаблонов администрирования

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

Настройка директорий шаблонов администрирования вашего проекта

Файлы шаблонов администрирования находятся в директории contrib/admin/templates/admin.

Для их настройки создайте директорию admin в директории templates вашего проекта. Это может быть любая директория, указанная в параметре DIRS опции DjangoTemplates бэкэнда в настройке TEMPLATES. Если вы настроили параметр 'loaders', убедитесь, что 'django.template.loaders.filesystem.Loader' расположена перед 'django.template.loaders.app_directories.Loader', чтобы система загрузки шаблонов находила ваши пользовательские шаблоны перед шаблонами, включенными с django.contrib.admin.

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

Чтобы настроить шаблон администрирования для определенного приложения, скопируйте и отредактируйте шаблон из директории django/contrib/admin/templates/admin и сохраните его в одной из созданных вами директорий.

Например, если мы хотели добавить инструмент в представление списка изменений для всех моделей в приложении под названием my_app, мы скопировали бы contrib/admin/templates/admin/change_list.html в директорию templates/admin/my_app/ нашего проекта и внесли необходимые изменения.

Если мы хотели добавить инструмент в представление списка изменений только для определенной модели под названием ‘Page’, мы скопировали бы этот же файл в директорию templates/admin/my_app/page нашего проекта.

Настройка шаблонов администрирования вместо их замены

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

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

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

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

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

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

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

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

Примечание

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

Шаблоны корня и входа

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

AdminSite объекты

class AdminSite(name='admin')

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

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

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

AdminSite атрибуты

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

AdminSite.site_header

Текст, который отображается в верхней части каждой страницы администрирования, как строка. По умолчанию это «Django администрирование».

AdminSite.site_title

Текст, который отображается в конце каждой страницы администрирования (строка). По умолчанию это «Django сайт администрирования».

AdminSite.site_url

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

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

AdminSite.index_title

Текст, который отображается в верхней части страницы индекса администрирования (строка). По умолчанию это «Администрирование сайта».

AdminSite.index_template

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

AdminSite.app_index_template

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

AdminSite.empty_value_display

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

AdminSite.enable_nav_sidebar
Новое в Django 3.1.

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

AdminSite методы

AdminSite.each_context(request)

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

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

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

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

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

    • object_name: имя класса модели
    • name: множественное число имени модели
    • perms: отслеживание dict, add, change, и delete прав
    • admin_url: URL-адрес списка изменений модели в администрировании
    • add_url: URL-адрес добавления новой модели
AdminSite.has_permission(request)

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

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

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

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

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

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

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

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

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

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

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

myapp/admin.py
from django.contrib.admin import AdminSite

from .models import MyModel

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

admin_site = MyAdminSite(name='myadmin')
admin_site.register(MyModel)
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.

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

Вы можете переопределить стандартный сайт администрирования, установив атрибут 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 для целей обратной генерации 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/ перед строкой, включающей сам модуль администрирования).

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

LogEntry объекты

class models.LogEntry

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

LogEntry атрибуты

LogEntry.action_time

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

LogEntry.user

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

LogEntry.content_type

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

LogEntry.object_id

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

LogEntry.object_repr

Объект`s repr() после изменения.

LogEntry.action_flag

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

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

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

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

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

LogEntry методы

LogEntry.get_edited_object()

Сокращение, возвращающее сохранённый объект.

LogEntry.get_change_message()

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

Обратная генерация URL-адресов администрирования

При развертывании AdminSite, предоставляемые им представления доступны с помощью системы обратной генерации URL-адресов Django.

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

Страница Имя URL Параметры
Индекс index
Вход login
Выход logout
Смена пароля password_change
Смена пароля выполнена password_change_done
i18n JavaScript jsi18n
Главная страница приложения app_list app_label
Переадресация на страницу объекта view_on_site content_type_id, object_id

Каждый экземпляр ModelAdmin предоставляет дополнительный набор именованных URL:

Страница Имя URL Параметры
Список изменений {{ 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, и в пространстве имён экземпляра, соответствующем имени экземпляра сайта.

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

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

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

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

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

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

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

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

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

Декоратор staff_member_required

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

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

  • Если пользователь авторизован, является сотрудником (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/3.1/ref/contrib/admin/index/

Spec-Zone.ru

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