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

Другие темы

  • Действия администрирования
  • Генератор документации 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):
    fields = ('name', 'title', 'view_birth_date')

    @admin.display(empty_value='???')
    def view_birth_date(self, obj):
        return obj.birth_date
Изменено в Django 3.2:

Аргумент empty_value для декоратора display() эквивалентен установке атрибута empty_value_display на функцию отображения напрямую в предыдущих версиях. Установка атрибута напрямую по-прежнему поддерживается для обратной совместимости.

ModelAdmin.exclude

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

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

from django.db import models

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

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

from django.contrib import admin

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

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

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

ModelAdmin.fields

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

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

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

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

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

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

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

Примечание

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

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

ModelAdmin.fieldsets

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

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

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

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

from django.contrib import admin

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

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

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

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

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

  • fields

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

    Пример:

    {
    'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
    }
    

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

    {
    'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
    }
    

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

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

  • classes

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

    Пример:

    {
    'classes': ('wide', 'extrapretty'),
    }
    

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

  • description

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

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

ModelAdmin.filter_horizontal

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

ModelAdmin.filter_vertical

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

ModelAdmin.form

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

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

Примечание

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

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

Примечание

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

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

class PersonForm(forms.ModelForm):

    class Meta:
        model = Person
        exclude = ['name']

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

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

ModelAdmin.formfield_overrides

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

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

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

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

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

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

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

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

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

ModelAdmin.inlines

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

ModelAdmin.list_display

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

Пример:

list_display = ('first_name', 'last_name')

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

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

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

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

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

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

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

Некоторые особые случаи, связанные с list_display:

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

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

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

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

    Аргумент description декоратора display() эквивалентен прямому установлению атрибута short_description на функцию отображения в предыдущих версиях. Прямое задание атрибута по-прежнему поддерживается для обратной совместимости.

  • Если значение поля None, пустая строка или итерируемый объект без элементов, Django отобразит - (тире). Вы можете переопределить это с помощью AdminSite.empty_value_display:

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

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

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

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

    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'birth_date_view')
    
        @admin.display(empty_value='unknown')
        def birth_date_view(self, obj):
             return obj.birth_date
    
    Изменено в Django 3.2:

    Аргумент empty_value декоратора display() эквивалентен прямому установлению атрибута empty_value_display на функцию отображения в предыдущих версиях. Прямое задание атрибута по-прежнему поддерживается для обратной совместимости.

  • Если заданная строка — метод модели, 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')
    
    Изменено в Django 3.2:

    Аргумент boolean декоратора display() эквивалентен прямому установлению атрибута boolean на функцию отображения в предыдущих версиях. Прямое задание атрибута по-прежнему поддерживается для обратной совместимости.

  • Метод __str__() так же допустим в list_display как и любой другой метод модели, поэтому это абсолютно нормально:

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

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

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

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

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

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

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

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

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

    from django.db.models import Value
    from django.db.models.functions import Concat
    
    class Person(models.Model):
        first_name = models.CharField(max_length=50)
        last_name = models.CharField(max_length=50)
    
        @admin.display(ordering=Concat('first_name', Value(' '), 'last_name'))
        def full_name(self):
            return self.first_name + ' ' + self.last_name
    
    Изменено в Django 3.2:

    Аргумент ordering декоратора display() эквивалентен прямому установлению атрибута admin_order_field на функцию отображения в предыдущих версиях. Прямое задание атрибута по-прежнему поддерживается для обратной совместимости.

  • Элементы list_display также могут быть свойствами:

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

    Обратите внимание, что @property должно быть выше @display.

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

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

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

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

ModelAdmin.list_display_links

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

ModelAdmin.list_filter

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

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

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

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

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

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

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

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

    Примечание

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

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

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

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

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

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

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

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

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

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

    Примечание

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

    Примечание

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

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

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

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

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

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

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

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

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

Примечание

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

ModelAdmin.ordering

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

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

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

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

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

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

ModelAdmin.paginator

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

ModelAdmin.prepopulated_fields

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

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

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

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

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

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

В более ранних версиях из сгенерированных значений удалялись различные английские стоп-слова.

ModelAdmin.preserve_filters

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

ModelAdmin.radio_fields

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

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

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

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

ModelAdmin.autocomplete_fields

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

По умолчанию админка использует интерфейс выпадающего списка (<select>) для этих полей (<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 с помощью обозначения «follow» в 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() для предоставления дополнительных или альтернативных правил поиска.

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

Добавлена поддержка поиска по цитируемым фразам с пробелами.

ModelAdmin.search_help_text
Добавлен в Django 4.0.

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

ModelAdmin.show_full_result_count

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

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

ModelAdmin.sortable_by

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

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

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

ModelAdmin.view_on_site

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

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

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

from django.contrib import admin

class PersonAdmin(admin.ModelAdmin):
    view_on_site = False

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

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

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

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

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

ModelAdmin.add_form_template

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

ModelAdmin.change_form_template

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

ModelAdmin.change_list_template

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

ModelAdmin.delete_confirmation_template

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

ModelAdmin.delete_selected_confirmation_template

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

ModelAdmin.object_history_template

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

ModelAdmin.popup_response_template

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

Методы ModelAdmin

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

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

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

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

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

from django.contrib import admin

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

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

ModelAdmin.delete_queryset(request, queryset)

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

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

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

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

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

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

ModelAdmin.get_ordering(request)

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

class PersonAdmin(admin.ModelAdmin):

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

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

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

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

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

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

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

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

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

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

ModelAdmin.get_autocomplete_fields(request)

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request)

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

ModelAdmin.get_list_display_links(request, list_display)

Метод get_list_display_links получает HttpRequest и список или кортеж, возвращённый методом ModelAdmin.get_list_display(). Он должен вернуть список или кортеж имён полей на странице изменения, которые будут связаны со страницей изменения, как описано в разделе 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 при добавлении) объект и должен вернуть список пар из двух элементов, где каждая пара представляет собой набор полей на странице администрирования, как описано в разделе 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 при добавлении) объект и должен вернуть список или кортеж объектов InlineModelAdmin, как описано в разделе InlineModelAdmin. Например, следующее вернёт inline-объекты без стандартного фильтра, основанного на разрешениях на добавление, изменение, удаление и просмотр:

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

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

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

ModelAdmin.get_inlines(request, obj)

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

ModelAdmin.get_urls()

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

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

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

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

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

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

Примечание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ModelAdmin.get_formsets_with_inlines(request, obj=None)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечание

Любой атрибут choices установленный для formfield, будет ограничен только этим полем формы. Если соответствующее поле в модели имеет установленные варианты, предоставляемые форме варианты должны быть действительной подмножеством этих вариантов, в противном случае отправка формы завершится ошибкой 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 в ModelForm, вы также должны определить атрибут Meta.fields (или атрибут Meta.exclude). Однако, ModelAdmin игнорирует это значение, переопределяя его атрибутом ModelAdmin.list_editable. Самое простое решение — пропустить атрибут Meta.model, поскольку ModelAdmin предоставит правильную модель для использования.

ModelAdmin.get_changelist_formset(request, **kwargs)

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

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
    pass

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

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

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

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

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

ModelAdmin.has_view_permission(request, obj=None)

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

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

ModelAdmin.has_add_permission(request)

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

ModelAdmin.has_change_permission(request, obj=None)

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

ModelAdmin.has_delete_permission(request, obj=None)

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

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)
Новая функция в Django 4.0.

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

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 для форм набора форм.

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'}
END_OF_DOCUMENT_MARKER
ModelAdmin.get_deleted_objects(objs, request)

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

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

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

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

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

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

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

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

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

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

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

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

ModelAdmin.changelist_view(request, extra_context=None)

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

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

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

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

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

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

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

class MyModelAdmin(admin.ModelAdmin):

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

    def get_osm_info(self):
        # ...
        pass

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

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

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

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

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

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

jQuery

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

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

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

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

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

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

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

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

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

class ArticleAdmin(admin.ModelAdmin):
    form = MyArticleAdminForm

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

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

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

InlineModelAdmin объекты

class InlineModelAdmin
class TabularInline
class StackedInline

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

from django.db import models

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

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

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

from django.contrib import admin

class BookInline(admin.TabularInline):
    model = Book

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

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

  • TabularInline
  • StackedInline

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

InlineModelAdmin параметры

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

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

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

InlineModelAdmin.model

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

InlineModelAdmin.fk_name

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

InlineModelAdmin.formset

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

InlineModelAdmin.form

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

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

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

InlineModelAdmin.classes

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

InlineModelAdmin.extra

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

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

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

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

InlineModelAdmin.max_num

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

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

InlineModelAdmin.min_num

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

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

InlineModelAdmin.raw_id_fields

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

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

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

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

InlineModelAdmin.verbose_name

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

InlineModelAdmin.verbose_name_plural

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

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

Добавлена возможность использования InlineModelAdmin.verbose_name по умолчанию.

InlineModelAdmin.can_delete

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

InlineModelAdmin.show_change_link

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

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

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

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

InlineModelAdmin.has_add_permission(request, obj)

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

InlineModelAdmin.has_change_permission(request, obj=None)

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

InlineModelAdmin.has_delete_permission(request, obj=None)

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

Примечание

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

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

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

from django.db import models

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

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

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

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

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

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

По умолчанию виджеты администрирования для отношений many-to-many будут отображаться в той модели, которая содержит фактическую ссылку на ManyToManyField. В зависимости от вашего определения ModelAdmin, каждое поле many-to-many в вашей модели будет представлено стандартным 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')

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

from django.contrib import admin

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

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

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

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

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

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

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

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

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

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

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

from django.db import models

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

from myapp.models import Image, Product

class ImageInline(GenericTabularInline):
    model = Image

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

admin.site.register(Product, ProductAdmin)

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

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

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

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

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

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

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

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

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

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

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

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

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

{% 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.

Поддержка тем

Новое в Django 3.2.

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

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

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

Определена тёмная тема и применена с учётом медиа-запроса prefers-color-scheme.

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

AdminSite объекты

class AdminSite(name='admin')

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

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

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

AdminSite атрибуты

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

AdminSite.site_header

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

AdminSite.site_title

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

AdminSite.site_url

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

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

AdminSite.index_title

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

AdminSite.index_template

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

AdminSite.app_index_template

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

AdminSite.empty_value_display

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

AdminSite.enable_nav_sidebar

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

AdminSite.final_catch_all_view
Новое в Django 3.2.

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

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

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

AdminSite методы

AdminSite.each_context(request)

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

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

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

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

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

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

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

AdminSite.has_permission(request)

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

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

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

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

AdminSite.unregister(model_or_iterable)

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

Вызывает исключение django.contrib.admin.sites.NotRegistered , если модель не зарегистрирована.

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

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

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

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

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

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

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

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

from .models import MyModel

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

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

from myapp.admin import admin_site

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

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

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

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

myproject/admin.py
from django.contrib import admin

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

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

from django.contrib.auth import views as auth_views

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

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

Наличие именованного 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 admin отображает это содержимое в формате JSON, чтобы get_change_message() могло пересобрать сообщение, переведённое на язык текущего пользователя. Однако, пользовательский код может установить это значение как обычную строку. Вам рекомендуется использовать метод get_change_message() для получения этого значения вместо прямого доступа.

LogEntry методы

LogEntry.get_edited_object()

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

LogEntry.get_change_message()

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

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

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

Интерфейс 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)
Добавлена в Django 3.2.

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

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

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

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

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

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

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

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

Декоратор staff_member_required

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

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

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

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

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

@staff_member_required
def my_view(request):
    ...

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

Spec-Zone.ru

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