Spec-Zone.ru › Django 1.8

Сайт администратора 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_CLASSES. (Все они активны по умолчанию, поэтому вам нужно это делать только в том случае, если вы вручную изменили настройки.)
  4. Определите, какие модели ваших приложений должны быть доступны для редактирования в интерфейсе администратора.
  5. Для каждой из этих моделей, необязательно, создайте класс ModelAdmin, который обобщает настраиваемые функциональные возможности и параметры для этой конкретной модели.
  6. Создайте экземпляр AdminSite и сообщите ему о каждой из ваших моделей и классах ModelAdmin.
  7. Присоедините экземпляр AdminSite к вашей URLconf.

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

Другие темы

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

См. также

Дополнительная информация о предоставлении статических файлов (изображений, 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(*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

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

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

Предыдущие версии Django рекомендовали вызывать эту функцию непосредственно в URLconf. Начиная с Django 1.7, это больше не нужно. AdminConfig заботится об автоматическом выполнении автообнаружения.

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

В предыдущих версиях администратору нужно было указать искать файлы admin.py с помощью autodiscover(). Начиная с Django 1.7, автообнаружение включено по умолчанию и должно быть явно отключено, когда это нежелательно.

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.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': ('enable_comments', 'registration_required', 'template_name')
        }),
    )

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

../../../_images/flatfiles_admin.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 по умолчанию экранирует вывод. Если вам не нужно экранировать вывод метода, задайте атрибут allow_tags со значением True. Однако, чтобы избежать уязвимости XSS, используйте 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)
    
        colored_name.allow_tags = True
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'last_name', 'colored_name')
    
  • Если указанная строка является методом модели, 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.allow_tags = True
        colored_first_name.admin_order_field = 'first_name'
    
    class PersonAdmin(admin.ModelAdmin):
        list_display = ('first_name', 'colored_first_name')
    

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

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

    colored_first_name.admin_order_field = '-first_name'
    

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

    class Blog(models.Model):
        title = models.CharField(max_length=255)
        author = models.ForeignKey(Person, on_delete=models.CASCADE)
    
    class BlogAdmin(admin.ModelAdmin):
        list_display = ('title', 'author', 'author_first_name')
    
        def author_first_name(self, obj):
            return obj.author.first_name
    
        author_first_name.admin_order_field = 'author__first_name'
    
  • Элементы 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), столбцы которых вы хотите преобразовать в ссылки.

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

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

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

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

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

None был добавлен в качестве допустимого значения list_display_links.

ModelAdmin.list_editable

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

Примечание

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

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

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

ModelAdmin.list_filter

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

../../../_images/users_changelist.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 считается внутренним и может быть изменен.

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

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').

ModelAdmin.ordering

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

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

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

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 "<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"
    # in this example, we have used HTML tags in the output
    address_report.allow_tags = True
ModelAdmin.save_as

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

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

«Сохранить как» означает, что объект будет сохранён как новый объект (с новым идентификатором), а не как старый.

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

ModelAdmin.save_on_top

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

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

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

ModelAdmin.search_fields

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

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

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.core.urlresolvers import reverse

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

Дополнительные параметры шаблона

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

ModelAdmin.add_form_template

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

ModelAdmin.change_form_template

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

ModelAdmin.change_list_template

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

ModelAdmin.delete_confirmation_template

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

ModelAdmin.delete_selected_confirmation_template

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

ModelAdmin.object_history_template

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

ModelAdmin методы

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

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

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

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

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

from django.contrib import admin

class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        obj.save()
ModelAdmin.delete_model(request, obj) [source]

Метод delete_model получает HttpRequest и экземпляр модели. Используйте этот метод для выполнения предварительных или последующих операций удаления.

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 во втором элементе возвращаемого значения.

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

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
ModelAdmin.save_related(request, form, formsets, change) [source]

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request) [source]

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

ModelAdmin.get_list_display_links(request, list_display) [source]

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

None был добавлен как допустимое значение возврата get_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 при добавлении формы) и должен вернуть список пар из двух элементов, в которых каждая пара представляет собой набор полей на странице формы администрирования, как описано в разделе ModelAdmin.fieldsets.

ModelAdmin.get_list_filter(request) [source]

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

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

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

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

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

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))
END_OF_DOCUMENT_MARKER
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(request, obj=None) [source]

Устаревшее с версии 1.7: Используйте get_formsets_with_inlines() вместо этого.

Возвращает InlineModelAdmin для использования в представлениях админского добавления и изменения.

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

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

    def get_formsets(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)
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. Наследуя этот класс, вы можете изменить поведение отображения.

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

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

from django import forms

class MyForm(forms.ModelForm):
    pass

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

Примечание

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

ModelAdmin.get_changelist_formset(request, **kwargs) [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 если редактирование объекта разрешено, False в противном случае. Если obj — None, должен возвращать True или False для указания, разрешено ли редактирование объектов этого типа в целом (например, False будет интерпретироваться как запрет редактирования любых объектов этого типа для текущего пользователя).

ModelAdmin.has_delete_permission(request, obj=None)

Должен возвращать True если удаление объекта разрешено, 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)
END_OF_DOCUMENT_MARKER
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().

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

ModelAdmin.response_change(request, obj) [source]

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

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

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

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

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

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

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

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

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

class MyModelAdmin(admin.ModelAdmin):

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

    def get_osm_info(self):
        # ...
        pass

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['osm_data'] = self.get_osm_info()
        return super(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 admin используется библиотека jQuery.

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

Встроенный jQuery был обновлён с версии 1.9.1 до 1.11.2.

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

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

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

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

Добавление пользовательской валидации данных в админ-панели довольно просто. Автоматический интерфейс админки использует 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)
   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.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.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, related_name="friends")
    from_person = models.ForeignKey(Person, related_name="from_friends")

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

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

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

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

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

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

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

from django.db import models

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

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

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

from django.contrib import admin

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

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

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

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

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

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

Во всех остальных аспектах 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)
    group = models.ForeignKey(Group)
    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)
    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 нашего проекта.

END_OF_DOCUMENT_MARKER

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

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

Продолжая пример выше, мы хотим добавить новую ссылку рядом с инструментом 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.

Примечание

Некоторые шаблоны админки, такие как 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 в конструкторе. Это имя экземпляра используется для идентификации экземпляра, особенно при обращении к адресам администрирования. Если имя экземпляра не указано, будет использоваться имя по умолчанию admin. См. Настройка класса AdminSite для примера настройки класса AdminSite.

AdminSite атрибуты

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

AdminSite.site_header

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

AdminSite.site_title

Текст в конце каждой страницы администрирования <title> (строка). По умолчанию это “Django сайт администрирования”.

AdminSite.site_url

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

AdminSite.index_title

Текст в верхней части главной страницы администрирования (строка). По умолчанию это “Администрирование сайта”.

AdminSite.index_template

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

AdminSite.app_index_template

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

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()

Аргумент request и переменная has_permission были добавлены.

AdminSite.has_permission(request) [source]

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

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

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

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

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

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
]

Настройка класса 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 include, url

from myapp.admin import admin_site

urlpatterns = [
    url(r'^myadmin/', include(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 include, url
from myproject.admin import basic_site, advanced_site

urlpatterns = [
    url(r'^basic-admin/', include(basic_site.urls)),
    url(r'^advanced-admin/', include(advanced_site.urls)),
]

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

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

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

Примечание

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

В предыдущих версиях Django вам приходилось передавать аргумент current_app в RequestContext или Context при отображении шаблона.

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

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

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

Методы LogEntry

LogEntry.get_edited_object() [source]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

>>> change_url = urlresolvers.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, и обычно предоставляется представлениями администратора для текущей модели.

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

Spec-Zone.ru

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