Spec-Zone.ru › Django 3.0

Сайт администрирования 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.contrib.auth.context_processors.auth и django.contrib.messages.context_processors.messages в опции 'context_processors' OPTIONS.
  3. Если вы настроили значение MIDDLEWARE, django.contrib.auth.middleware.AuthenticationMiddleware и django.contrib.messages.middleware.MessageMiddleware должны быть включены.
  4. Подключите URL-адреса администрирования в ваш URLconf.

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

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

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

Другие темы

  • Действия администрирования
  • Генератор документации Django admin
  • Настройка 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, если вы этого хотите. В противном случае вы можете использовать обычный текст и 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, сайт админки отобразит один столбец, в котором будет отображаться строковое представление каждого объекта.

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

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

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

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

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

    from django.contrib import admin
    from django.db import models
    
    class Person(models.Model):
        name = models.CharField(max_length=50)
        birthday = models.DateField()
    
        def decade_born_in(self):
            return self.birthday.strftime('%Y')[:3] + "0's"
        decade_born_in.short_description = 'Birth decade'
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'decade_born_in')
    

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

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

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

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

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

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

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

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

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

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

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

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

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

    Например:

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

    Вышеупомянутое сообщит Django о необходимости сортировки по полю first_name при попытке сортировки по colored_first_name в админке.

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

    colored_first_name.admin_order_field = '-first_name'
    

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

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

    Выражения запроса могут использоваться в 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, будет использовано поле модели.

END_OF_DOCUMENT_MARKER
ModelAdmin.list_display_links

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

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

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

    Можно указать одно или несколько полей. Django не заботится о количестве (или количестве) связанных полей, пока поля появляются в list_display. Единственное требование, если вы хотите использовать 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 также могут охватывать связи с использованием __ поиска, например:

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

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

    Примечание

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

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

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

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

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

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

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

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

    Примечание

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

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

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

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

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

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

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

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

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

Примечание

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

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 из одного или нескольких других полей. Сгенерированное значение создаётся путём конкатенации значений исходных полей, а затем преобразованием результата в допустимый слаг (например, замена пробелов дефисами, приведение букв ASCII к нижнему регистру и удаление различных английских стоп-слов, таких как «a», «an», «as» и аналогичных).

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

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

ModelAdmin.preserve_filters

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

END_OF_DOCUMENT_MARKER
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 с помощью синтаксиса поиска «follow»:

search_fields = ['foreign_key__related_fieldname']

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

search_fields = ['user__email']

Когда кто-то производит поиск в поле поиска админки, Django разбивает поисковый запрос на слова и возвращает все объекты, содержащие каждое из слов, без учёта регистра (используя поиск icontains), где каждое слово должно быть в хотя бы одном из search_fields. Например, если search_fields установлено как ['first_name', 'last_name'] и пользователь ищет john lennon, Django выполнит запрос, эквивалентный следующему SQL WHERE:

WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')

Если вам не нужен поиск 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 к каждому изменённому экземпляру модели формосета:

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

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

ModelAdmin.get_ordering(request)

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

class PersonAdmin(admin.ModelAdmin):

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

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

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

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

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

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

    def get_search_results(self, request, queryset, search_term):
        queryset, 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 formsets и булево значение, указывающее, добавляется или изменяется родительский объект. Здесь вы можете выполнить любые операции до или после сохранения объектов, связанных с родителем. Обратите внимание, что на данном этапе родительский объект и его форма уже сохранены.

END_OF_DOCUMENT_MARKER
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 зарегистрированная выше, имеет две проблемы:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ModelAdmin.get_formsets_with_inlines(request, obj=None)

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

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

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

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

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

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

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

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

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

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

Как и метод formfield_for_foreignkey, метод formfield_for_manytomany может быть переопределён для изменения поля формы по умолчанию для поля «многие ко многим». Например, если владелец может владеть несколькими машинами, а машины могут принадлежать нескольким владельцам — отношение «многие ко многим» — вы могли бы отфильтровать поле внешнего ключа Car до отображения только автомобилей, принадлежащих экземпляру User:

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

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

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

Примечание

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

ModelAdmin.get_changelist(request, **kwargs)

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

ModelAdmin.get_changelist_form(request, **kwargs)

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

from django import forms

class MyForm(forms.ModelForm):
    pass

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

Примечание

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

ModelAdmin.get_changelist_formset(request, **kwargs)

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

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
    pass

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

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

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

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

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

ModelAdmin.has_view_permission(request, obj=None)

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

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

ModelAdmin.has_add_permission(request)

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

ModelAdmin.has_change_permission(request, obj=None)

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

ModelAdmin.has_delete_permission(request, obj=None)

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

END_OF_DOCUMENT_MARKER
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-адреса приложения admin для рендеринга страниц, которые обрабатывают операции CRUD с экземплярами моделей. Полное переопределение этих методов существенно изменит поведение приложения admin.

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

class MyModelAdmin(admin.ModelAdmin):

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

    def get_osm_info(self):
        # ...
        pass

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

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

ModelAdmin определения активов

Иногда требуется добавить немного CSS и/или JavaScript в представления добавления/изменения. Это можно сделать, используя внутренний класс Media в вашей модели ModelAdmin:

class ArticleAdmin(admin.ModelAdmin):
    class Media:
        css = {
            "all": ("my_styles.css",)
        }
        js = ("my_code.js",)

Приложение staticfiles добавляет STATIC_URL (или MEDIA_URL, если STATIC_URL равно None) к любым путям активов. Применяются те же правила, что и в определениях обычных активов в формах.

jQuery

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

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

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

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

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

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() также позволяет настраивать количество дополнительных форм.

END_OF_DOCUMENT_MARKER
InlineModelAdmin.max_num

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

InlineModelAdmin.get_max_num() также позволяет настраивать максимальное количество дополнительных форм.

InlineModelAdmin.min_num

Это контролирует минимальное количество форм для отображения во встроенной форме. Смотрите modelformset_factory() для получения дополнительной информации.

InlineModelAdmin.get_min_num() также позволяет настраивать минимальное количество отображаемых форм.

InlineModelAdmin.raw_id_fields

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

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

class BookInline(admin.TabularInline):
    model = Book
    raw_id_fields = ("pages",)
InlineModelAdmin.template

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

InlineModelAdmin.verbose_name

Переопределение verbose_name в внутреннем классе модели Meta.

InlineModelAdmin.verbose_name_plural

Переопределение verbose_name_plural в внутреннем классе модели Meta.

InlineModelAdmin.can_delete

Указывает, можно ли удалять встроенные объекты во встроенной форме. По умолчанию True.

InlineModelAdmin.show_change_link

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

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

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

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

InlineModelAdmin.has_add_permission(request, obj)

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

InlineModelAdmin.has_change_permission(request, obj=None)

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

InlineModelAdmin.has_delete_permission(request, obj=None)

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

Примечание

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

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

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

from django.db import models

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

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

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

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

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

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

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

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

from django.db import models

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

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

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

from django.contrib import admin

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

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

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

В этом примере два момента заслуживают внимания.

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

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

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

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

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

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

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

from django.db import models

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

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

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

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

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

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

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

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

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

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

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

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

Использование обобщённых связей в качестве встроенных форм

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

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

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

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

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

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

from myproject.myapp.models import Image, Product

class ImageInline(GenericTabularInline):
    model = Image

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

admin.site.register(Product, ProductAdmin)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Не каждый шаблон в 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

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

AdminSite.site_title

Текст, который будет отображаться внизу каждой страницы администрирования <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.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, и view
    • admin_url: URL-адрес страницы изменения модели в админ-панели
    • add_url: URL-адрес страницы добавления новой записи модели
AdminSite.has_permission(request)

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

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

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

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

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

Последний шаг настройки Django admin — привязка вашего экземпляра 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),
]

Обратите внимание, что вам, вероятно, не нужно будет использовать автоматическое обнаружение модулей admin при использовании собственного экземпляра AdminSite, так как вы, скорее всего, импортируете все модули 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 для целей обратного преобразования. Это необходимо только если вы используете более одного экземпляра 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 spowoduje добавление ссылки «Забыли пароль?» на стандартной странице входа в админ-панель под полем пароля.

LogEntry объекты

class models.LogEntry

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

END_OF_DOCUMENT_MARKER

LogEntry атрибуты

LogEntry.action_time

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

LogEntry.user

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

LogEntry.content_type

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

LogEntry.object_id

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

LogEntry.object_repr

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

LogEntry.action_flag

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

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

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

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

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

LogEntry методы

LogEntry.get_edited_object()

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

LogEntry.get_change_message()

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

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

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

Система обратного преобразования URL-адресов 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

Система обратного преобразования URL-адресов UserAdmin предоставляет именованный URL:

Страница Имя URL Параметры
Изменение пароля auth_user_password_change user_id

Эти именованные URL-адреса зарегистрированы в пространстве имён приложения admin, и в пространстве имён экземпляра, соответствующем имени экземпляра сайта.

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

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

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

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

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

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

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

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

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

Декоратор 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.0/ref/contrib/admin/index/

Spec-Zone.ru

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