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

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

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

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

Другие темы

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

См. также

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

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

ModelAdmin объекты

class ModelAdmin

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

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


class AuthorAdmin(admin.ModelAdmin):
    pass


admin.site.register(Author, AuthorAdmin)

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

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

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

admin.site.register(Author)

Декоратор register

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

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

from django.contrib import admin
from .models import Author


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

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

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


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

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

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

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

class apps.AdminConfig

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

class apps.SimpleAdminConfig

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

default_site

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

autodiscover()

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

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

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

ModelAdmin опции

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

from django.contrib import admin


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

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

ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom

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

ModelAdmin.actions_selection_counter

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

ModelAdmin.date_hierarchy

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

Пример:

date_hierarchy = "pub_date"

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

date_hierarchy = "author__pub_date"

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

Примечание

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

ModelAdmin.empty_value_display

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

from django.contrib import admin


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

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

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    list_display = ["name", "title", "view_birth_date"]

    @admin.display(empty_value="???")
    def view_birth_date(self, obj):
        return obj.birth_date
ModelAdmin.exclude

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

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

from django.db import models


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

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

from django.contrib import admin


class AuthorAdmin(admin.ModelAdmin):
    fields = ["name", "title"]


class AuthorAdmin(admin.ModelAdmin):
    exclude = ["birth_date"]

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

ModelAdmin.fields

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

class FlatPageAdmin(admin.ModelAdmin):
    fields = ["url", "title", "content"]

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

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

Опция fields принимает те же типы значений, что и list_display, за исключением того, что вызываемые объекты не принимаются. Имена методов модели и модели администратора будут использоваться только в том случае, если они перечислены в readonly_fields.

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

class FlatPageAdmin(admin.ModelAdmin):
    fields = [("url", "title"), "content"]

Возможная путаница с опцией ModelAdmin.fieldsets

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

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

ModelAdmin.fieldsets

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

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

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

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

from django.contrib import admin


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

Это приводит к отображению страницы администрирования, подобной:

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

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

Словарь field_options может содержать следующие ключи:

  • fields

    Список или кортеж имен полей для отображения в этом полесете. Этот ключ обязателен.

    Пример:

    {
        "fields": ["first_name", "last_name", "address", "city", "state"],
    }
    

    Как и с опцией fields, чтобы отобразить несколько полей в одной строке, оберните эти поля в свои собственные кортежи. В этом примере поля first_name и last_name будут отображаться в одной строке:

    {
        "fields": [("first_name", "last_name"), "address", "city", "state"],
    }
    

    fields может содержать значения, определенные в readonly_fields для отображения в качестве только для чтения.

    Если вы добавите имя вызываемого объекта в fields, то же правило применяется, что и с опцией fields: вызываемый объект должен быть перечислен в readonly_fields.

  • classes

    Список или кортеж, содержащий дополнительные CSS-классы для применения к полесету.

    Пример:

    {
        "classes": ["wide", "extrapretty"],
    }
    

    Два полезных класса, определенные в таблице стилей по умолчанию, — это collapse и wide. Полесеты со стилем collapse будут изначально схлопнуты в администрировании и заменены небольшой ссылкой «нажать, чтобы развернуть». Полесеты со стилем wide будут иметь дополнительное горизонтальное пространство.

  • description

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

    Обратите внимание, что это значение не экранируется с помощью HTML при отображении в интерфейсе администрирования. Это позволяет включать HTML, если у вас есть такая необходимость. В качестве альтернативы вы можете использовать обычный текст и django.utils.html.escape() для экранирования любых специальных символов HTML.

ModelAdmin.filter_horizontal

По умолчанию ManyToManyField отображается в админ-сайте с <select multiple>. Однако многовыборные поля могут быть сложными для использования при выборе многих элементов. Добавление ManyToManyField в этот список вместо этого будет использовать удобный неуловимый интерфейс JavaScript «фильтр», который позволяет искать в вариантах. Невыбранные и выбранные варианты отображаются в двух полях рядом друг с другом. См. filter_vertical для использования вертикального интерфейса.

ModelAdmin.filter_vertical

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

ModelAdmin.form

По умолчанию для вашей модели динамически создается ModelForm. Она используется для создания формы, отображаемой на страницах добавления/изменения. Вы можете легко предоставить собственную ModelForm для переопределения любого поведения формы по умолчанию на страницах добавления/изменения. В качестве альтернативы, вы можете настроить форму по умолчанию, а не указывать совершенно новую, используя метод ModelAdmin.get_form().

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

Опустите атрибут Meta.model

Если вы определяете атрибут Meta.model для ModelForm, вы также должны определить атрибут Meta.fields (или атрибут Meta.exclude). Однако, так как админпанель имеет свой способ определения полей, атрибут Meta.fields будет игнорироваться.

Если атрибут ModelForm будет использоваться только для админпанели, самый простой способ — опустить атрибут Meta.model, так как ModelAdmin предоставит правильную модель для использования. В качестве альтернативы, вы можете установить fields = [] в классе Meta для удовлетворения валидации на ModelForm.

ModelAdmin.exclude имеет приоритет

Если ваши ModelForm и ModelAdmin оба определяют опцию exclude, тогда ModelAdmin имеет приоритет:

from django import forms
from django.contrib import admin
from myapp.models import Person


class PersonForm(forms.ModelForm):
    class Meta:
        model = Person
        exclude = ["name"]


class PersonAdmin(admin.ModelAdmin):
    exclude = ["age"]
    form = PersonForm

В приведенном выше примере поле «возраст» будет исключено, а поле «имя» — включено в сгенерированную форму.

ModelAdmin.formfield_overrides

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

Так как это немного абстрактно, давайте рассмотрим конкретный пример. Наиболее частое использование formfield_overrides — это добавление пользовательского виджета для определенного типа поля. Например, предположим, что мы написали RichTextEditorWidget для использования с полями большого текста вместо стандартного <textarea>. Вот как мы это сделаем:

from django.contrib import admin
from django.db import models

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


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

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

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

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

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

ModelAdmin.inlines

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

ModelAdmin.list_display

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

Пример:

list_display = ["first_name", "last_name"]

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

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

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

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

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

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

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

Несколько особых случаев, касающихся list_display:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    @admin.display(ordering="-first_name")
    def colored_first_name(self): ...
    

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

    class Blog(models.Model):
        title = models.CharField(max_length=255)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)
    
    
    class BlogAdmin(admin.ModelAdmin):
        list_display = ["title", "author", "author_first_name"]
    
        @admin.display(ordering="author__first_name")
        def author_first_name(self, obj):
            return obj.author.first_name
    

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

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

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

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

    def my_property(self):
        return self.first_name + " " + self.last_name
    
    
    my_property.short_description = "Full name of the person"
    my_property.admin_order_field = "last_name"
    my_property.boolean = False
    
    full_name = property(my_property)
    
    Изменено в Django 5.0:

    Добавлена поддержка атрибута boolean для свойств.

  • Имена полей в list_display также будут отображаться как CSS классы в HTML выводе, в форме column-<field_name> в каждом элементе <th>. Это можно использовать для установки ширины столбцов в CSS-файле, например.
  • Django попытается интерпретировать каждый элемент list_display в таком порядке:

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

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

ModelAdmin.list_display_links

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

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

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

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

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

class PersonAdmin(admin.ModelAdmin):
    list_display = ["first_name", "last_name", "birthday"]
    list_display_links = ["first_name", "last_name"]

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

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

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

Примечание

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

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

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

ModelAdmin.list_filter

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

В самом простом случае list_filter принимает список или кортеж имён полей для активации фильтрации, но доступны и более продвинутые варианты. Подробности см. в Фильтр списка модели.

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

class ArticleAdmin(admin.ModelAdmin):
    list_select_related = ["author", "category"]

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

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

Примечание

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

ModelAdmin.ordering

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

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

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

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

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

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

ModelAdmin.paginator

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

ModelAdmin.prepopulated_fields

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

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

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

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

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

ModelAdmin.preserve_filters

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

ModelAdmin.show_facets
Новое в Django 5.0.

Управляет отображением подсчётов аспектов для фильтров в админском списке изменений. По умолчанию ShowFacets.ALLOW.

При отображении подсчёты аспектов обновляются в соответствии с текущими применёнными фильтрами.

class ShowFacets
Новое в Django 5.0.

Перечисление допустимых значений для ModelAdmin.show_facets.

ALWAYS

Всегда отображать подсчёты аспектов.

ALLOW

Отображать подсчёты аспектов, когда параметр строки запроса _facets задан.

NEVER

Никогда не отображать подсчёты аспектов.

Установите show_facets на необходимое значение ShowFacets. Например, чтобы всегда отображать подсчёты аспектов, без необходимости предоставления параметра запроса:

from django.contrib import admin


class MyModelAdmin(admin.ModelAdmin):
    ...
    # Have facets always shown for this model admin.
    show_facets = admin.ShowFacets.ALWAYS

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

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

ModelAdmin.radio_fields

По умолчанию Django admin использует интерфейс выпадающего списка (<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"]

    # description functions like a model field's verbose_name
    @admin.display(description="Address")
    def address_report(self, instance):
        # assuming get_full_address() returns a list of strings
        # for each line of the address and you want to separate each
        # line by a linebreak
        return format_html_join(
            mark_safe("<br>"),
            "{}",
            ((line,) for line in instance.get_full_address()),
        ) or mark_safe("<span class='errors'>I can't determine this address.</span>")
ModelAdmin.save_as

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

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

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

ModelAdmin.save_as_continue

Когда save_as=True, стандартный перенаправление после сохранения нового объекта — в представление изменения для этого объекта. Если вы установите save_as_continue=False, перенаправление будет в представление списка изменений.

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

ModelAdmin.save_on_top

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

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

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

ModelAdmin.search_fields

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

Эти поля должны быть полями типа текст, такими как CharField или TextField. Вы также можете выполнить связанный поиск по ForeignKey или ManyToManyField с помощью обозначения API поиска «следовать»:

search_fields = ["foreign_key__related_fieldname"]

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

search_fields = ["user__email"]

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

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

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

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

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

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

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

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

ModelAdmin.search_help_text

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

END_OF_DOCUMENT_MARKER
ModelAdmin.show_full_result_count

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

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

ModelAdmin.sortable_by

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

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

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

ModelAdmin.view_on_site

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

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

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

from django.contrib import admin


class PersonAdmin(admin.ModelAdmin):
    view_on_site = False

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

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


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

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

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

ModelAdmin.add_form_template

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

ModelAdmin.change_form_template

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

ModelAdmin.change_list_template

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

ModelAdmin.delete_confirmation_template

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

ModelAdmin.delete_selected_confirmation_template

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

ModelAdmin.object_history_template

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

ModelAdmin.popup_response_template

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

Методы ModelAdmin

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

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

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

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

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

from django.contrib import admin


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

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

ModelAdmin.delete_queryset(request, queryset)

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

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

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

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

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

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

ModelAdmin.get_ordering(request)

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

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

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

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

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

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

class PersonAdmin(admin.ModelAdmin):
    list_display = ["name", "age"]
    search_fields = ["name"]

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

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

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

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

ModelAdmin.get_autocomplete_fields(request)

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request)

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

ModelAdmin.get_list_display_links(request, list_display)

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

ModelAdmin.get_exclude(request, obj=None)

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

ModelAdmin.get_fields(request, obj=None)

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

ModelAdmin.get_fieldsets(request, obj=None)

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

ModelAdmin.get_list_filter(request)

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

ModelAdmin.get_list_select_related(request)

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

ModelAdmin.get_search_fields(request)

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

ModelAdmin.get_sortable_by(request)

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

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

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

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

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

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

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

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

ModelAdmin.get_inlines(request, obj)

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

END_OF_DOCUMENT_MARKER
ModelAdmin.get_urls()

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

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.admin_site.admin_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 %}

Примечание

Обратите внимание, как функция self.my_view обернута в self.admin_site.admin_view. Это важно, так как гарантирует две вещи:

  1. Проверка разрешений выполняется, гарантируя, что только активные сотрудники могут получить доступ к представлению.
  2. Декоратор django.views.decorators.cache.never_cache() применяется для предотвращения кэширования, гарантируя актуальность возвращаемой информации.

Примечание

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

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

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

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

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

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

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

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

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

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

ModelAdmin.get_formsets_with_inlines(request, obj=None)

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

Например, если вы хотите отобразить определённый инлайн только в представлении изменения, вы можете переопределить 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"].append(("ready", "Ready for deployment"))
        return super().formfield_for_choice_field(db_field, request, **kwargs)

choices ограничения

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

ModelAdmin.get_changelist(request, **kwargs)

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

ModelAdmin.get_changelist_form(request, **kwargs)

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

from django import forms


class MyForm(forms.ModelForm):
    pass


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

Опустить атрибут Meta.model

Если вы определённый атрибут 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, request)

Объекты на странице изменения могут быть отфильтрованы с помощью поисков из строки запроса 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.

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

Добавлен аргумент request.

ModelAdmin.has_view_permission(request, obj=None)

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

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

ModelAdmin.has_add_permission(request)

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

ModelAdmin.has_change_permission(request, obj=None)

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

ModelAdmin.has_delete_permission(request, obj=None)

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

ModelAdmin.has_module_permission(request)

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

ModelAdmin.get_queryset(request)

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

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

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

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

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

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

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

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

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

ModelAdmin.response_change(request, obj)

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

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

ModelAdmin.response_delete(request, obj_display, obj_id)

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

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

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

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

ModelAdmin.get_formset_kwargs(request, obj, inline, prefix)

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

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

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

ModelAdmin.get_changeform_initial_data(request)

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

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

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

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

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

Метод должен вернуть кортеж из 4 элементов (deleted_objects, model_count, perms_needed, protected).

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

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

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

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

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

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

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

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

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

ModelAdmin.changelist_view(request, extra_context=None)

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

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

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

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

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

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

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

class MyModelAdmin(admin.ModelAdmin):
    # A template for a very customized change view:
    change_form_template = "admin/myapp/extras/openstreetmap_change_form.html"

    def get_osm_info(self):
        # ...
        pass

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

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

ModelAdmin определения ресурсов

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

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

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

jQuery

JavaScript приложения Django администратора использует библиотеку jQuery.

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

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

jQuery был обновлен с 3.6.0 до 3.6.4.

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

jQuery был обновлен с 3.6.4 до 3.7.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. Использование собственного formset предоставляет множество возможностей настройки. Инлайны построены на основе наборов форм модели.

InlineModelAdmin.form

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

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

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

InlineModelAdmin.classes

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

InlineModelAdmin.extra

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

Для пользователей с браузерами, поддерживающими JavaScript, предоставляется ссылка «Добавить ещё», чтобы можно было добавить любое количество дополнительных инлайнов в дополнение к тем, которые были предоставлены в результате аргумента extra.

Динамическая ссылка не появится, если количество отображаемых в настоящее время форм превышает max_num, или если пользователь не включил JavaScript.

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

InlineModelAdmin.max_num

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

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

InlineModelAdmin.min_num

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

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

InlineModelAdmin.raw_id_fields

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

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

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

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

InlineModelAdmin.verbose_name

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

InlineModelAdmin.verbose_name_plural

Переопределение verbose_name_plural из внутреннего класса Meta модели. Если это не задано, и InlineModelAdmin.verbose_name определён, Django будет использовать InlineModelAdmin.verbose_name + 's'.

InlineModelAdmin.can_delete

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

InlineModelAdmin.show_change_link

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

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

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

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

InlineModelAdmin.has_add_permission(request, obj)

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

InlineModelAdmin.has_change_permission(request, obj=None)

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

InlineModelAdmin.has_delete_permission(request, obj=None)

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

Примечание

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

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

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

from django.db import models


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

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

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


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


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

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

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

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

from django.db import models


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


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

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

from django.contrib import admin


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


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


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

Есть две особенности, на которые стоит обратить внимание в этом примере.

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

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

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

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

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

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

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

from django.db import models


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


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


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

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

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

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

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

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


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

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

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

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

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

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

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


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


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

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

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

from myapp.models import Image, Product


class ImageInline(GenericTabularInline):
    model = Image


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


admin.site.register(Product, ProductAdmin)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

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

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

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

{% block extrastyle %}{{ block.super }}
<style>
html[data-theme="light"], :root {
  --primary: #9774d5;
  --secondary: #785cab;
  --link-fg: #7c449b;
  --link-selected-fg: #8f5bb2;
}
</style>
{% endblock %}

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

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

AdminSite объекты

class AdminSite(name='admin')

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

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

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

django.contrib.admin.sites.all_sites

WeakSet содержит все экземпляры сайтов администрирования.

AdminSite атрибуты

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

AdminSite.site_header

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

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

В более ранних версиях site_header использовал тег <h1>.

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.enable_nav_sidebar

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

AdminSite.final_catch_all_view

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

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

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

AdminSite методы

AdminSite.each_context(request)

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

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

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

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

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

    • model: класс модели
    • object_name: имя класса модели
    • name: множественное число имени модели
    • perms: отслеживание dict, add, change, и delete прав
    • admin_url: URL страницы списка изменений модели в админке
    • add_url: URL страницы добавления новой модели в админке
  • is_popup: отображается ли текущая страница в всплывающем окне
  • is_nav_sidebar_enabled: AdminSite.enable_nav_sidebar
  • log_entries: AdminSite.get_log_entries()
AdminSite.get_app_list(request, app_label=None)

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

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

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

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

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

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.exceptions.AlreadyRegistered если модель уже зарегистрирована.

AdminSite.unregister(model_or_iterable)

Дерегистрирует заданный класс модели (или итерируемый объект классов).

Вызывает django.contrib.admin.exceptions.NotRegistered если модель не зарегистрирована.

AdminSite.get_model_admin(model)
Новое в Django 5.0.

Возвращает класс админки для заданного класса модели. Вызывает django.contrib.admin.exceptions.NotRegistered если модель не зарегистрирована.

AdminSite.get_log_entries(request)
Новое в Django 5.0.

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

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

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

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

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

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

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

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

myapp/admin.py
from django.contrib import admin

from .models import MyModel


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


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

from myapp.admin import admin_site

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

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

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

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

myproject/admin.py
from django.contrib import admin


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


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

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

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

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

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

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

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

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

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

Примечание

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

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

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

from django.contrib import admin
from django.contrib.auth import views as auth_views

path(
    "admin/password_reset/",
    auth_views.PasswordResetView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="admin_password_reset",
),
path(
    "admin/password_reset/done/",
    auth_views.PasswordResetDoneView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="password_reset_done",
),
path(
    "reset/<uidb64>/<token>/",
    auth_views.PasswordResetConfirmView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="password_reset_confirm",
),
path(
    "reset/done/",
    auth_views.PasswordResetCompleteView.as_view(
        extra_context={"site_header": admin.site.site_header}
    ),
    name="password_reset_complete",
),

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

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

LogEntry объекты

class models.LogEntry

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

LogEntry атрибуты

LogEntry.action_time

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

LogEntry.user

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

LogEntry.content_type

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

LogEntry.object_id

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

LogEntry.object_repr

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

LogEntry.action_flag

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

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

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

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

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

LogEntry методы

LogEntry.get_edited_object()

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

LogEntry.get_change_message()

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

Обратное преобразование URL администрирования

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

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

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

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

Страница Имя URL Параметры
Список изменений {{ app_label }}_{{ model_name }}_changelist
Добавление {{ app_label }}_{{ model_name }}_add
История {{ app_label }}_{{ model_name }}_history object_id
Удаление {{ app_label }}_{{ model_name }}_delete object_id
Изменение {{ app_label }}_{{ model_name }}_change object_id

Экземпляр UserAdmin предоставляет именованный URL:

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

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

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

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

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

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

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

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

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

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

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

Декоратор display

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

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

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

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

def is_published(self, obj):
    return obj.publish_date is not None


is_published.boolean = True
is_published.admin_order_field = "-publish_date"
is_published.short_description = "Is Published?"

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

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

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

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

Декоратор staff_member_required

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

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

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

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

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


@staff_member_required
def my_view(request): ...

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

Spec-Zone.ru

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