Spec-Zone.ru › Django 1.10

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

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

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

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

Обзор

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

Для справки, вот требования:

  1. Добавьте 'django.contrib.admin' в свой параметр INSTALLED_APPS.
  2. Администрирование зависит от четырёх приложений — django.contrib.auth, django.contrib.contenttypes, django.contrib.messages и django.contrib.sessions. Если эти приложения отсутствуют в вашем списке INSTALLED_APPS, добавьте их.
  3. Добавьте django.contrib.auth.context_processors.auth и django.contrib.messages.context_processors.messages к параметру 'context_processors' используемого DjangoTemplates бэкенда, определённого в ваших TEMPLATES и django.contrib.auth.middleware.AuthenticationMiddleware и django.contrib.messages.middleware.MessageMiddleware в MIDDLEWARE. Они все активны по умолчанию, поэтому вам нужно сделать это только в том случае, если вы вручную настроили параметры.
  4. Определите, модели каких приложений должны быть доступны для редактирования в интерфейсе администрирования.
  5. Для каждой из этих моделей необязательно создать класс ModelAdmin, который инкапсулирует настраиваемую функциональность администрирования и параметры для этой конкретной модели.
  6. Инициализируйте экземпляр AdminSite и укажите ему каждую из ваших моделей и классы ModelAdmin.
  7. Включите экземпляр AdminSite в ваш URLconf.

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

Другие темы

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

См. также

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

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

ModelAdmin объекты

class ModelAdmin [source]

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

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

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

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

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

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

admin.site.register(Author)

Декоратор register

register(*models, site=django.admin.sites.site) [source]

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

from django.contrib import admin
from .models import Author

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

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

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

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

Вы не можете использовать этот декоратор, если вам нужно сослаться на класс модели admin в методе __init__() например, super(PersonAdmin, self).__init__(*args, **kwargs). Если вы используете Python 3 и не должны беспокоиться о поддержке Python 2, вы можете использовать super().__init__(*args, **kwargs) . В противном случае вам придётся использовать admin.site.register() вместо этого декоратора.

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

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

class apps.AdminConfig

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

class apps.SimpleAdminConfig

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

autodiscover() [source]

Эта функция пытается импортировать модуль 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 использует QuerySet.datetimes() внутри. Обратитесь к его документации для некоторых замечаний, когда включена поддержка часовых поясов (USE_TZ = True).

ModelAdmin.empty_value_display
Новое в Django 1.9.

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

from django.contrib import admin

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

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

from django.contrib import admin

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

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

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

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

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

from django.db import models

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

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

from django.contrib import admin

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

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

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

ModelAdmin.fields

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

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

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

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

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

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

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

Примечание

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

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

ModelAdmin.fieldsets

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

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

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

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

from django.contrib import admin

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

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

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

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

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

  • fields

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

    Пример:

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

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

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

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

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

  • classes

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

    Пример:

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

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

  • description

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

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

ModelAdmin.filter_horizontal

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

ModelAdmin.filter_vertical

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

ModelAdmin.form

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

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

Примечание

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

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

Примечание

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

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

class PersonForm(forms.ModelForm):

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

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

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

ModelAdmin.formfield_overrides

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

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

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

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

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

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

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

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

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

ModelAdmin.inlines

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

ModelAdmin.list_display

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

Пример:

list_display = ('first_name', 'last_name')

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

У вас есть четыре возможных значения, которые могут быть использованы в list_display:

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

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

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

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

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

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

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

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

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

    Устарело начиная с версии 1.9: В более старых версиях вы могли добавить атрибут allow_tags к методу, чтобы предотвратить автоматическое экранирование. Этот атрибут устарел, так как безопаснее использовать format_html(), format_html_join() или mark_safe().

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

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

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

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

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

    class PersonAdmin(admin.ModelAdmin):
        list_display = ('name', 'birth_date_view')
    
        def birth_date_view(self, obj):
             return obj.birth_date
    
        birth_date_view.empty_value_display = 'unknown'
    
    Добавлена в Django 1.9:

    Добавлена возможность настраивать empty_value_display.

  • Если заданная строка — это метод модели, ModelAdmin или вызываемый объект, возвращающий True или False, Django отобразит красивый значок «вкл» или «выкл», если вы добавите к методу атрибут boolean со значением True.

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

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

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

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

    Например:

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

    Это сообщит Django, что при попытке отсортировать по colored_first_name в админке необходимо сортировать по полю first_name.

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

    colored_first_name.admin_order_field = '-first_name'
    

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

    class Blog(models.Model):
        title = models.CharField(max_length=255)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)
    
    class BlogAdmin(admin.ModelAdmin):
        list_display = ('title', 'author', 'author_first_name')
    
        def author_first_name(self, obj):
            return obj.author.first_name
    
        author_first_name.admin_order_field = 'author__first_name'
    
  • Элементы list_display также могут быть свойствами. Обратите внимание, что из-за работы свойств в Python, установка short_description на свойстве возможна только при использовании функции property() и не с декоратором @property.

    Например:

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

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

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

ModelAdmin.list_display_links

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

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

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

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

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

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

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

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

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

Примечание

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

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

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

ModelAdmin.list_filter

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

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

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

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

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

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

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

    from datetime import date
    
    from django.contrib import admin
    from django.utils.translation import ugettext_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(AuthDecadeBornListFilter, self).lookups(request, model_admin)
    
        def queryset(self, request, queryset):
            if request.user.is_superuser:
                return super(AuthDecadeBornListFilter, self).queryset(request, queryset)
    

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

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

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

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

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

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

    Примечание

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

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

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

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

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

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

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

будет вызывать select_related('author', 'category').

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

ModelAdmin.ordering

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

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

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

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 (например, замена пробелов на дефисы).

prepopulated_fields не поддерживает поля DateTimeField, ForeignKey, и ManyToManyField.

ModelAdmin.preserve_filters

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

ModelAdmin.radio_fields

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

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

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

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

ModelAdmin.raw_id_fields

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

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

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

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

../../../_images/raw_id_fields.png
ModelAdmin.readonly_fields

По умолчанию, в админке все поля отображаются как редактируемые. Любые поля в этом параметре (которые должны быть list или tuple) будут отображать свои данные в неизменяемом виде; они также исключаются из ModelForm, используемого для создания и редактирования. Обратите внимание, что при указании ModelAdmin.fields или ModelAdmin.fieldsets поля для чтения должны присутствовать, чтобы быть отображенными (в противном случае они игнорируются).

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

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

from django.contrib import admin
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe

class PersonAdmin(admin.ModelAdmin):
    readonly_fields = ('address_report',)

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

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

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

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

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

ModelAdmin.save_as_continue
Добавлено в Django 1.10.

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

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

ModelAdmin.save_on_top

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

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

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

ModelAdmin.search_fields

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

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

search_fields = ['foreign_key__related_fieldname']

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

search_fields = ['user__email']

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

Для более быстрого и/или ограниченного поиска добавьте префикс к имени поля оператором:

^

Используйте оператор ‘^’ для поиска, начинающегося с начала поля. Например, если 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%', так как база данных должна проверить только начало данных столбца, а не искать по всем данным столбца. Кроме того, если для столбца есть индекс, некоторые базы данных могут использовать индекс для этого запроса, даже если это запрос LIKE.

=

Используйте оператор ‘=’ для регистронезависимого точного соответствия. Например, если 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')

Обратите внимание, что входной запрос разделяется пробелами, поэтому, в соответствии с этим примером, в настоящее время невозможно выполнить поиск по всем записям, в которых first_name точно равно 'john winston' (содержащий пробел).

@
Используйте оператор ‘@’ для выполнения полнотекстового поиска. Это как метод поиска по умолчанию, но использует индекс. В настоящее время это доступно только для MySQL.

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

ModelAdmin.show_full_result_count

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

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

ModelAdmin.view_on_site

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

Это значение может быть либо логическим флагом, либо вызываемым объектом. Если True (по умолчанию), для генерации URL будет использован метод объекта get_absolute_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() для отображения страницы подтверждения при удалении одного или нескольких объектов.

END_OF_DOCUMENT_MARKER
ModelAdmin.delete_selected_confirmation_template

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

ModelAdmin.object_history_template

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

ModelAdmin методы

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

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

ModelAdmin.save_model(request, obj, form, change) [source]

Метод 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(ArticleAdmin, self).save_model(request, obj, form, change)
ModelAdmin.delete_model(request, obj) [source]

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

ModelAdmin.save_formset(request, form, formset, change) [source]

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

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

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

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

ModelAdmin.get_ordering(request)

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

class PersonAdmin(admin.ModelAdmin):

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

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

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

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

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

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

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

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

ModelAdmin.save_related(request, form, formsets, change) [source]

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request) [source]

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

ModelAdmin.get_list_display_links(request, list_display) [source]

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

ModelAdmin.get_fields(request, obj=None) [source]

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

ModelAdmin.get_fieldsets(request, obj=None)

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

ModelAdmin.get_list_filter(request) [source]

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

ModelAdmin.get_list_select_related(request) [source]
Новое в Django 1.9.

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

ModelAdmin.get_search_fields(request) [source]

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

ModelAdmin.get_inline_instances(request, obj=None) [source]

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

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

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

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

ModelAdmin.get_urls() [source]

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

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

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

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

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

Примечание

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

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

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

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

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

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

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

url(r'^my_view/$', self.admin_site.admin_view(self.my_view))

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

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

url(r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))
Новое в Django 1.9.

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

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

Возвращает класс 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(MyModelAdmin, self).get_form(request, obj, **kwargs)

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

ModelAdmin.get_formsets_with_inlines(request, obj=None) [source]

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

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

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

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

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

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

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

ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)

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

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

Примечание

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

ModelAdmin.get_changelist(request, **kwargs) [source]

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

END_OF_DOCUMENT_MARKER
ModelAdmin.get_changelist_form(request, **kwargs) [source]

Возвращает класс 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) [source]

Возвращает класс 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(MyModelAdmin, self).get_changelist_formset(request, **kwargs)
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_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(MyModelAdmin, self).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) [source]

Отправляет пользователю сообщение с использованием бэкенда 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) [source]

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

ModelAdmin.response_add(request, obj, post_url_continue=None) [source]

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

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

ModelAdmin.response_change(request, obj) [source]

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

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

ModelAdmin.response_delete(request, obj_display, obj_id) [source]

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

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

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

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

ModelAdmin.get_changeform_initial_data(request) [source]

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

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

def get_changeform_initial_data(self, request):
    return {'name': 'custom_initial_value'}

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

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

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

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

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

ModelAdmin.changelist_view(request, extra_context=None) [source]

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

ModelAdmin.delete_view(request, object_id, extra_context=None) [source]

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

ModelAdmin.history_view(request, object_id, extra_context=None) [source]

Представление 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(MyModelAdmin, self).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 (версия 2.2.3) имеет пространство имён django.jQuery. Если вы хотите использовать jQuery в собственном JavaScript администрирования без добавления второй копии, вы можете использовать объект django.jQuery в представлениях списка, добавления и редактирования.

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

Встроенная jQuery была обновлена с 1.11.2 до 2.1.4. Это приводит к прекращению поддержки Internet Explorer 8 и ниже. Вы можете восстановить поддержку, включив собственную версию jQuery 1.X.

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

Встроенная jQuery была обновлена с 2.1.4 до 2.2.3.

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

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

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_queryset()
  • radio_fields
  • readonly_fields
  • raw_id_fields
  • formfield_for_choice_field()
  • formfield_for_foreignkey()
  • formfield_for_manytomany()
  • has_add_permission()
  • has_change_permission()
  • has_delete_permission()
  • has_module_permission()

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

InlineModelAdmin.model

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

InlineModelAdmin.fk_name

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

InlineModelAdmin.formset

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

InlineModelAdmin.form

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

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

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

InlineModelAdmin.classes
Добавлена в Django 1.10.

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

InlineModelAdmin.extra

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

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

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

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

InlineModelAdmin.max_num

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

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

InlineModelAdmin.min_num

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

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

InlineModelAdmin.raw_id_fields

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

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

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

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

InlineModelAdmin.verbose_name

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

InlineModelAdmin.verbose_name_plural

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

InlineModelAdmin.can_delete

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

InlineModelAdmin.show_change_link

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

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

Возвращает класс BaseInlineFormSet для использования в админ-вьюхах добавления/изменения. См. пример для 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).

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

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

from django.db import models

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

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

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

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

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

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

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

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

from django.db import models

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

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

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

from django.contrib import admin

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

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

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

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

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

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

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

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

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

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

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

from django.db import models

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

from myproject.myapp.models import Image, Product

class ImageInline(GenericTabularInline):
    model = Image

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

admin.site.register(Product, ProductAdmin)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • app_index.html
  • change_form.html
  • change_list.html
  • delete_confirmation.html
  • object_history.html

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

END_OF_DOCUMENT_MARKER

Примечание

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

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

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

AdminSite объекты

class AdminSite(name='admin') [source]

Сайт 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 не установлено на значение отличное от /.

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

Была добавлена поддержка SCRIPT_NAME описанная в предыдущем абзаце.

AdminSite.index_title

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

AdminSite.index_template

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

AdminSite.app_index_template

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

AdminSite.empty_value_display
Новое в Django 1.9.

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

AdminSite методы

AdminSite.each_context(request) [source]

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

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

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

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

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

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

Переменная available_apps была добавлена.

AdminSite.has_permission(request) [source]

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

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

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

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

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

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

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

# urls.py
from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
Изменено в Django 1.9:

В предыдущих версиях вы передавали admin.site.urls методу include().

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

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

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)
from django.conf.urls import url

from myapp.admin import admin_site

urlpatterns = [
    url(r'^myadmin/', admin_site.urls),
]

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

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

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

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

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

urlpatterns = [
    url(r'^basic-admin/', basic_site.urls),
    url(r'^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

url(r'^admin/password_reset/$', auth_views.password_reset, name='admin_password_reset'),
url(r'^admin/password_reset/done/$', auth_views.password_reset_done, name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$', auth_views.password_reset_confirm, name='password_reset_confirm'),
url(r'^reset/done/$', auth_views.password_reset_complete, 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 LogEntry, ADDITION

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

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

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

Ранее этот атрибут всегда был простой строкой. Теперь он имеет JSON структуру, чтобы сообщение можно было перевести на текущий язык пользователя. Старые сообщения остаются без изменений.

LogEntry методы

LogEntry.get_edited_object()

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

LogEntry.get_change_message()
Новое в Django 1.10.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Декоратор staff_member_required

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

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

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

Spec-Zone.ru

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