Spec-Zone.ru › Django 1.11

Сайт администрирования 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' бэкенда, определённого в ваших TEMPLATES, а также django.contrib.auth.middleware.AuthenticationMiddleware и django.contrib.messages.middleware.MessageMiddleware в MIDDLEWARE. По умолчанию они активны, поэтому вам нужно это сделать только в случае ручной настройки настроек.
  4. Определите, модели каких приложений должны быть доступны для редактирования в интерфейсе администрирования.
  5. Для каждой из этих моделей необязательно создать класс ModelAdmin, который encapsulates настраиваемую функциональность администрирования и параметры для данной модели.
  6. Создайте экземпляр AdminSite и сообщите ему о каждой вашей модели и классах ModelAdmin.
  7. Подключите экземпляр AdminSite к вашей URLconf.

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

Другие темы

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

См. также

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

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

ModelAdmin объекты

class ModelAdmin [source]

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

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

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

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

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

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

admin.site.register(Author)

Декоратор register

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

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

from django.contrib import admin
from .models import Author

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

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

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

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

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

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

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

class apps.AdminConfig

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

class apps.SimpleAdminConfig

Этот класс работает так же, как AdminConfig, но не вызывает autodiscover().

autodiscover() [source]

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

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

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

ModelAdmin параметры

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

from django.contrib import admin

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

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

ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom

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

ModelAdmin.actions_selection_counter

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

ModelAdmin.date_hierarchy

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

Пример:

date_hierarchy = 'pub_date'

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

date_hierarchy = 'author__pub_date'

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

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

Добавлена возможность ссылки на поля связанных моделей.

Примечание

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

ModelAdmin.empty_value_display

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

from django.contrib import admin

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

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

from django.contrib import admin

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

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

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

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

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

from django.db import models

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

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

from django.contrib import admin

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

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

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

ModelAdmin.fields

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

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

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

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

Опция fields, в отличие от list_display, может содержать только имена полей модели или формы, указанные в 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> на странице формы администрирования. (Набор <fieldset> — это «раздел» формы.)

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

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

from django.contrib import admin

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

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

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

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

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

  • fields

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

    Пример:

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

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

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

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

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

  • classes

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

    Пример:

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

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

  • description

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

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

ModelAdmin.filter_horizontal

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

ModelAdmin.filter_vertical

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

ModelAdmin.form

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

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

Примечание

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

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

Примечание

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

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

class PersonForm(forms.ModelForm):

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

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

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

ModelAdmin.formfield_overrides

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

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

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

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

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

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

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

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

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

ModelAdmin.inlines

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

ModelAdmin.list_display

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

Пример:

list_display = ('first_name', 'last_name')

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

В list_display можно использовать четыре типа значений:

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

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

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

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

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

Некоторые особенности list_display:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Например:

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

    Выше приведенный пример укажет Django сортировать по полю 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
ModelAdmin.list_editable

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

Примечание

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

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

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

ModelAdmin.list_filter

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

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

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

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

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

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

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

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

    Примечание

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

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

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

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

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

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

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

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

    Примечание

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

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

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

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

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

ModelAdmin.list_max_show_all

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

ModelAdmin.list_per_page

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

ModelAdmin.list_select_related

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

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

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

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

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

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

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

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

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

ModelAdmin.preserve_filters

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

ModelAdmin.radio_fields

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

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

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

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

END_OF_DOCUMENT_MARKER
ModelAdmin.raw_id_fields

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ModelAdmin.save_as_continue
Новое в Django 1.10.

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

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

ModelAdmin.save_on_top

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

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

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

ModelAdmin.search_fields

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

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

search_fields = ['foreign_key__related_fieldname']

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

search_fields = ['user__email']

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

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

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

^

Используйте оператор ‘^’, чтобы совпадало начало поля. Например, если search_fields установлено в ['^first_name', '^last_name'] и пользователь ищет john lennon, Django выполнит запрос, эквивалентный следующей SQL WHERE фразе:

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

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

=

Используйте оператор ‘=’ для точного совпадения без учёта регистра. Например, если search_fields установлено в ['=first_name', '=last_name'] и пользователь ищет john lennon, Django выполнит запрос, эквивалентный следующей SQL WHERE фразе:

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

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

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

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

ModelAdmin.show_full_result_count

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

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

ModelAdmin.view_on_site

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

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

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

from django.contrib import admin

class PersonAdmin(admin.ModelAdmin):
    view_on_site = False

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

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

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

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

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

ModelAdmin.add_form_template

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

ModelAdmin.change_form_template

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

ModelAdmin.change_list_template

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

ModelAdmin.delete_confirmation_template

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

ModelAdmin.delete_selected_confirmation_template

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

ModelAdmin.object_history_template

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

ModelAdmin.popup_response_template
Новое в Django 1.11.

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

ModelAdmin методы

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

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

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

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

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

from django.contrib import admin

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

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

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

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

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

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

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

ModelAdmin.get_ordering(request)

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

class PersonAdmin(admin.ModelAdmin):

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

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

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

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

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

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

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

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

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

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

ModelAdmin.get_readonly_fields(request, obj=None)

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

ModelAdmin.get_prepopulated_fields(request, obj=None)

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

ModelAdmin.get_list_display(request) [source]

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

ModelAdmin.get_list_display_links(request, list_display) [source]

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

ModelAdmin.get_exclude(request, obj=None)
Новое в Django 1.11.

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

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

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

END_OF_DOCUMENT_MARKER
ModelAdmin.get_fieldsets(request, obj=None)

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

ModelAdmin.get_list_filter(request) [source]

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

ModelAdmin.get_list_select_related(request) [source]

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

ModelAdmin.get_search_fields(request) [source]

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

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

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

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

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

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

ModelAdmin.get_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))

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

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

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

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

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

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

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

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

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

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

    def get_formsets_with_inlines(self, request, obj=None):
        for inline in self.get_inline_instances(request, obj):
            # hide MyInline in the add view
            if 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 при валидации модели перед сохранением.

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

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

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

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

from django import forms

class MyForm(forms.ModelForm):
    pass

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

Примечание

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

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

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

from django.forms import BaseModelFormSet

class MyAdminFormSet(BaseModelFormSet):
    pass

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

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

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

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

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

ModelAdmin.has_add_permission(request)

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

ModelAdmin.has_change_permission(request, obj=None)

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

ModelAdmin.has_delete_permission(request, obj=None)

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

ModelAdmin.has_module_permission(request)

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

ModelAdmin.get_queryset(request)

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

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

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

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

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

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

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

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

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

ModelAdmin.response_change(request, obj) [source]

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

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

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

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

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

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

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

ModelAdmin.get_changeform_initial_data(request) [source]

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

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

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

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

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

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

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

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

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

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

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

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

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

Django-представление для страницы, отображающей историю изменений для данного экземпляра модели.

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

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

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 в представления «add/change». Это можно сделать, используя внутренний класс Media в вашем ModelAdmin:

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

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

jQuery

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

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

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

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

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

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

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

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

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

class ArticleAdmin(admin.ModelAdmin):
    form = MyArticleAdminForm

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

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

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

InlineModelAdmin объекты

class InlineModelAdmin
class TabularInline [source]
class StackedInline [source]

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

from django.db import models

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

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

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

from django.contrib import admin

class BookInline(admin.TabularInline):
    model = Book

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

Django предоставляет два подкласса InlineModelAdmin, и они следующие:

  • TabularInline
  • StackedInline

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

InlineModelAdmin параметры

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

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

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

InlineModelAdmin.model

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

InlineModelAdmin.fk_name

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

InlineModelAdmin.formset

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

InlineModelAdmin.form

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

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

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

InlineModelAdmin.classes
Новое в Django 1.10.

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

InlineModelAdmin.extra

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

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

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

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

InlineModelAdmin.max_num

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

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

InlineModelAdmin.min_num

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

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

InlineModelAdmin.raw_id_fields

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

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

InlineModelAdmin.show_change_link

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

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

Возвращает класс BaseInlineFormSet для использования в админских представлениях добавления/изменения. Смотрите пример для ModelAdmin.get_formsets_with_inlines.

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

class BinaryTreeAdmin(admin.TabularInline):
    model = BinaryTree

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

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

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

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

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

from django.db import models

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

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

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

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

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

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

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

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

from django.db import models

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

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

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

from django.contrib import admin

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

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

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

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

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

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

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

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

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

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

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

from django.db import models

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

from myproject.myapp.models import Image, Product

class ImageInline(GenericTabularInline):
    model = Image

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

admin.site.register(Product, ProductAdmin)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • app_index.html
  • change_form.html
  • change_list.html
  • delete_confirmation.html
  • object_history.html
  • popup_response.html
Изменено в Django 1.11:

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

AdminSite атрибуты

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

AdminSite.site_header

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

AdminSite.site_title

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

AdminSite.site_url

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

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

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

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

AdminSite.index_title

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

AdminSite.index_template

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

AdminSite.app_index_template

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

AdminSite.empty_value_display

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

AdminSite.login_template

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

AdminSite.login_form

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

AdminSite.logout_template

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

AdminSite.password_change_template

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

AdminSite.password_change_done_template

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

AdminSite методы

AdminSite.each_context(request) [source]

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

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

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

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

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

    • object_name: имя класса модели
    • name: множественное число имени модели
    • perms: dict отслеживает add, change, и delete разрешения
    • admin_url: URL списка изменений модели в админке
    • add_url: URL админки для добавления новой записи модели
AdminSite.has_permission(request) [source]

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

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

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

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

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

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

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

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

urlpatterns = [
    url(r'^admin/', 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 url

from myapp.admin import admin_site

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

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

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

Легко создать несколько экземпляров сайта администрирования на одном сайте Django. Просто создайте несколько экземпляров AdminSite и привяжите каждый из них к разным URL.

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

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

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

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

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

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

Примечание

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

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

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

from django.contrib.auth import views as auth_views

url(
    r'^admin/password_reset/$',
    auth_views.PasswordResetView.as_view(),
    name='admin_password_reset',
),
url(
    r'^admin/password_reset/done/$',
    auth_views.PasswordResetDoneView.as_view(),
    name='password_reset_done',
),
url(
    r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
    auth_views.PasswordResetConfirmView.as_view(),
    name='password_reset_confirm',
),
url(
    r'^reset/done/$',
    auth_views.PasswordResetCompleteView.as_view(),
    name='password_reset_complete',
),

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

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

LogEntry объекты

class models.LogEntry

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

LogEntry атрибуты

LogEntry.action_time

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

LogEntry.user

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

LogEntry.content_type

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

LogEntry.object_id

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

LogEntry.object_repr

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

LogEntry.action_flag

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

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

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

LogEntry.objects.filter(action_flag=ADDITION)

LogEntry.change_message

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

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

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

LogEntry методы

LogEntry.get_edited_object()

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

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

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

Обратные ссылки на admin URL

При развертывании AdminSite, предоставляемые им представления доступны через систему обратного преобразования URL Django URL reversing system.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Декоратор staff_member_required

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

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

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

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

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

@staff_member_required
def my_view(request):
    ...

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

Spec-Zone.ru

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