Разное

Django admin: Руководство Django часть 4: административная панель Django — Изучение веб-разработки

Содержание

Руководство Django часть 4: административная панель Django — Изучение веб-разработки

Теперь, когда модели для сайта местной библиотеки созданы, добавим некоторые «настоящие» данные о книгах, используя административную панель Django Admin. Для начала мы покажем, как зарегистрировать в ней модели, потом как войти и создать какие-нибудь данные. В конце статьи мы покажем некоторые способы дальнейшего улучшения вида админ-панели.

Предусловия:Сначала завершите: Руководство часть 3: использование моделей.
Цель:

Уяснить преимущества и ограничения админ-панели Django, научиться использовать её для создания записей для наших моделей.

Обзор

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

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

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

Регистрация моделей 

Вначале откройте файл admin.py в папке приложения (/locallibrary/catalog/admin.py). Пока он выглядит так (заметьте, что он уже содержит импорт  django.contrib.admin):

from django.contrib import admin

# Register your models here.

Зарегистрируйте модели путем вставки следующего текста в нижнюю часть этого файла. Этот код просто импортирует модели и затем вызывает  admin.site.register для регистрации каждой из них.

from .models import Author, Genre, Book, BookInstance

admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Genre)
admin.site.register(BookInstance)

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

Это самый простой способ регистрации модели или моделей. Админ-панель имеет множество настроек. Мы рассмотрим другие способы регистрации ваших моделей ниже.

Создание суперпользователя

Для того, чтобы войти в админ-панель, нам необходимо иметь учетную запись пользователя со статусом Staff (сотрудники). Для просмотра и создания записей, пользователю также понадобится разрешение для управления всеми нашими объектами. Вы можете создать учетную запись  «superuser», которая дает полный доступ к сайту и все необходимые разрешения, используя manage.py.

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

python3 manage.py createsuperuser

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

python3 manage.py runserver

Вход в админ-панель и ее использование

Для входа в админ-панель откройте ссылку /admin (например  http://127.0.0.1:8000/admin) и введите логин и пароль вашего нового суперпользователя  (вас перенаправят на login-страницу и потом обратно на /admin после ввода всех деталей).

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

Кликните на ссылке Add справа от Books, чтобы создать новую книгу (появится диалоговое окно как на картинке внизу). Заметьте, что заголовок каждого поля — это тип используемого виджета, и    help_text (если есть) совпадает со значением, которое вы указали в модели. 

Введите значение для полей. Вы можете создавать новых авторов или жанры, нажимая на значок «+ «, расположенный рядом с соответствующим полем (или выберите существующее значение из списков, если вы уже создали их). Когда вы закончили, нажмите на SAVE,  Save and add another, или Save and continue editing, чтобы сохранить записи.

Примечание: А сейчас, хотелось бы, чтобы вы добавили несколько книг, авторов и жанров (например,  Фэнтези) в ваше приложение. Удостоверьтесь, что каждый автор и жанр включает пару различных книг (позже, когда мы реализуем представления «list» и «detail», это сделает их более интересными).

После того, когда книги добавлены, для перехода на главную страницу админ-панели кликните на ссылке Home в верхней части страницы. Потом кликните на ссылке Books для отображения текущего списка книг (или на одной из других ссылок, чтобы увидеть список соответствующей модели). После добавления нескольких книг список может выглядеть наподобие скриншота ниже.  Отображается название каждой из книг. Его возвращает метод __str__() в модели Book, созданной в предыдущей статье.

Для удаления книги из этого списка выберите чекбокс рядом с ней и действие delete…  из выпадающего списка Action, а затем нажмите кнопку Go. Также можно добавить новую книгу, нажав на кнопку ADD BOOK

Вы можете редактировать книгу, кликнув по ссылке с ее названием. Страница редактирования книги, приведенная ниже, практически идентична странице добавления новой книги. Основные отличия — это заголовок страницы (Change book) и наличие кнопок Delete, HISTORY и VIEW ON SITE.  Последняя присутствует, так как мы определили метод get_absolute_url() в нашей модели.

Теперь перейдите назад на страницу Home (используя ссылку Home в навигационной цепочке вверху страницы) и просмотрите списки Author и Genre. В них уже должно быть несколько элементов, созданных при добавлении новых книг. Если хотите, добавьте еще.

Однако у вас не будет ни одного экземпляра книги, потому что они не создаются из модели Book (хотя можно создать книгу из модели BookInstance — такова природа поля ForeignKey). Для отображения страницы Add book instance (см. рисунок ниже) вернитесь на страницу Home  и нажмите кнопку Add. Обратите внимание на длинный уникальный Id для идентификации конкретного экземпляра книги в библиотеке.

Создайте несколько экземпляров для каждой из ваших книг. Установите статус Available (доступен) для некоторых экземплров и On loan (выдан) для остальных. Если статус экземпляра not Available (недоступен), то также установите дату возврата (Due back).

Вот и все!  Вы изучили как запустить и использовать админ-панель. Также были созданы записи для Book, BookInstance, Genre и Author, которые можно будет использовать после создания наших собственных представлений и шаблонов.

«Продвинутая» конфигурация

Django выполняет неплохую работу по созданию базовой админ-панели используя информацию из зарегистрированых моделей:

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

Можно настроить интерфейс пользователя для упрощения его использования. Некоторые доступные настройки:

  • List views: 
    • добавление дополнительных отображаемых полей или информации для каждой записи. 
    • добавление фильтров для отбора записей по разным критериям (например, статус выдачи книги).
    • добавление дополнительных вариантов выбора в меню действий и места расположения этого меню на форме.
  • Detail views
    • выбор отображаемых полей, их порядка, группирования и т.д. 
    • добавление связанных полей к записи  (например, возможности добавления и редактирования записей книг при создании записи автора).

В этом разделе рассмотрим некоторые изменения для совершенствования интерфейса пользователя нашей местной библиотеки, а именно: добавление дополнительной информации в списки моделей Book и Author ,  а также улучшение расположения элементов соответствующих представлений редактирования. Пользовательский интерфейс моделей Language and Genre изменять не будем, так как это не даст заметного улучшения, поскольку он содержит только по одному полю!

Полное руководство по всем возможным вариантам настройки админ-панели можно найти в The Django Admin site (документация Django).

Регистрация класса ModelAdmin

Для измененения отображения модели в пользовательском интерфейсе админ-панели, необходимо определить класс ModelAdmin  (он описывает расположение элементов интерфейса, где Model — наименование модели) и зарегистрировать его для использования с этой моделью.

Давайте начнем с модели Author. Откройте файл admin.py в каталоге приложения (/locallibrary/catalog/admin.py). Закомментируйте исходную регистрацию (используя префикс #) этой модели:

# admin.site.register(Author)

Теперь добавьте новый класс AuthorAdmin и зарегистрируйте его как показано ниже:

# Define the admin class
class AuthorAdmin(admin.ModelAdmin):
    pass

# Register the admin class with the associated model
admin.site.register(Author, AuthorAdmin)

Сейчас мы добавим классы ModelAdmin для моделей Book  BookInstance. Нам снова нужно закомментировать исходную регистрацию:

#admin.site.register(Book)
#admin.site.register(BookInstance)

В этот раз для создания и регистрации новых моделей используем декоратор  @register (он делает то же самое, что и метод admin.site.register()):

# Register the Admin classes for Book using the decorator

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    pass

# Register the Admin classes for BookInstance using the decorator

@admin.register(BookInstance) 
class BookInstanceAdmin(admin.ModelAdmin):
    pass

Пока что все наши admin-классы пустые (см. «pass"), поэтому ничего не изменится ! Добавим код для задания особенностей интерфейса моделей.

Настройка отображения списков

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

Замените класс AuthorAdmin кодом, приведенным ниже. Названия полей, которые будут отображаться в списке, перечислены в кортеже list_display в требуемом порядке  (это те же имена, что и в исходной модели).

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')

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

Для нашей модели Book добавим отображение полей author и genre. Поле author  — это  внешний ключ (ForeignKey ) связи один к одному, поэтому оно будет представлено значением __str()__  для связанной записи. Замените класс BookAdmin на версию, приведенную ниже.

class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'display_genre')

К сожалению, мы не можем напрямую поместить поле genre в list_display, так как оно является  ManyToManyField (Django не позволяет это из-за большой «стоимости» доступа к базе данных). Вместо этого мы определим функцию display_genre для получения строкового представления информации (вызов этой функции есть в list_display,  ее определение см. ниже).

Примечание: Получение здесь значения поля genre возможно не самая хорошая идея вследствие «стоимости» операции базы данных. Мы показываем это, потому что вызов функций в ваших моделях может быть очень полезен по другим причинам, например, для добавления ссылки  Delete рядом с каждым пунктом списка.

Добавьте следующий код в вашу модель Book (models.py). В нем создается строка из первых трех значений поля genre (если они существуют) и short_description,  которое может быть использовано в админ-панели.

    def display_genre(self):
        """
        Creates a string for the Genre. This is required to display genre in Admin.
        """
        return ', '.join([ genre.name for genre in self.genre.all()[:3] ])
    display_genre.short_description = 'Genre'

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

Модель Genre (и модель Language, если вы ее определили) имеет единственное поле. Поэтому нет необходимости создания для них дополнительных моделей с целью отображения дополнительных полей.

Примечание: целесообразно, чтобы в списке модели BookInstance отображались хотя бы статус и ожидаемая дата возврата. Мы добавили это в качестве «испытания» в конце этой статьи!

Добавление фильтров списка

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

class BookInstanceAdmin(admin.ModelAdmin):
    list_filter = ('status', 'due_back')

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

Формирование макета с подробным представлением

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

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

Управление отображаемыми и вложенными полями

Обновите ваш AuthorAdmin класс, чтобы добавить строку полей, как показано ниже (выделено полужирным шрифтом):

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')
    fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]

Атрибут полей перечисляет только те поля, которые должны отображаться в форме, по порядку. Поля отображаются по вертикали по умолчанию, но будут отображаться горизонтально, если вы дополнительно группируете их в кортеже (как показано в полях «date» выше).

Перезагрузите приложение и перейдите к подробному представлению автора — он должен теперь отображаться, как показано ниже:

Примечание: Так же, вы можете использовать exclude атрибут для объявления списка атрибутов, которые будут исключены из формы (все остальные атрибутыв модели, будут отображаться). 

Разделение на секции/Выделение подробного представления

Вы можете добавлять «разделы» (sections) для группировки связанной информации в модели в форме детализации, используя атрибут fieldsets .

В модели BookInstance мы имеем информацию соответствия конкретной книги (т.е. name, imprint, and id) и датой когда она вновь станет доступной (status, due_back). Мы можем добавить их  в разные секции, добавив текст жирным шрифтом в наш BookInstanceAdmin класс. 

@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):
    list_filter = ('status', 'due_back')
    
    fieldsets = (
        (None, {
            'fields': ('book','imprint', 'id')
        }),
        ('Availability', {
            'fields': ('status', 'due_back')
        }),
    )

Каждая секция имеет свой заголовок (или None, если заголовок не нужен) и ассоциированный кортеж полей в словаре — формат сложный для описания, но относительно простой для понимания, если вы посмотрите на фрагмент кода, представленный выше.

Перезапустите сайт и перейдите к списку экземпляров; форма должна отображаться следующим образом:

Встроенное редактирование связанных записей

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

Вы можете это сделать, объявив inlines, и указав тип TabularInline (горизонтальное расположение) или  StackedInline (вертикальное расположение, так же как и в модели по умолчанию). Вы можете добавить  BookInstance информацию в подробное описание  Book , добавив строки, представленные ниже и распологающиеся рядом с  BookAdmin

class BooksInstanceInline(admin.TabularInline):
    model = BookInstance

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'display_genre')
    inlines = [BooksInstanceInline]

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

В этом случае, всё, что мы сделали — объявили наш встроенный класс tablular, который просто добавляет все поля из встроенной модели. Вы можете указать все виды дополнительной информации для макета, включая отображаемые поля, их порядок, независимо от того, являются ли они только для чтения или нет, и т. д. (См. TabularInline для получения дополнительной информации). 

Примечание: В этой функции есть некоторые неприятные ограничения! На скриншоте выше у нас есть три существующих экземпляра книги, за которыми следуют три поля для новых экземпляров книги (которые очень похожи!). Было бы лучше НЕ иметь лишних экземпляров книг по умолчанию и просто добавить их с помощью ссылки Add another Book instance или иметь возможность просто перечислять BookInstances как нечитаемые здесь ссылки. Первый вариант можно сделать, установив extra атрибут в 0 в модели BookInstanceInline, попробуйте сами.

Проверьте себя

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

  1. Для представления списка BookInstance , добавьте код  для отображения книги, статуса, даты возврата, и id (вместо значения по умолчанию возвращаемого  __str__() ).
  2. Добавьте встроенный список перечня Book в представление списка Author , используя тот же самый подход, который мы применили для Book/BookInstance.

Заключение

Вот и всё! Теперь вы узнали, как настроить сайт администрирования как в самой простой, так и в улучшенной форме, о создании суперпользователя и о том, как перемещаться по сайту администратора, просматривать, удалять и обновлять записи. По пути вы создали множество книг, экземпляров, жанров и авторов, которые мы сможем перечислить и отобразить, как только мы создадим собственный вид и шаблоны.

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

Настройка Django Admin | Guru

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

Оглавление

  • Предпосылки
  • Настройка администратора Django
  • Кастомизация администратора Django
  • Изменение списка изменений с помощью list_display
  • Предоставление ссылок на страницы других объектов
  • Добавление фильтров на экран списка
  • Добавление поиска на экран списка
  • Изменение способа редактирования моделей
  • Переопределение шаблонов администратора Django
  • Вывод

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

В этом руководстве вы узнаете, как:

  • Добавить столбцы атрибутов в список объектов модели
  • Связь между объектами модели
  • Добавить фильтры в список объектов модели
  • Сделать списки объектов модели доступными для поиска
  • Изменить формы редактирования объекта
  • Переопределить шаблоны администратора Django

Предпосылки

Чтобы получить максимальную отдачу от этого руководства, вам понадобится некоторое знакомство с Django, особенно с объектами модели. Поскольку Django не входит в стандартную библиотеку Python, лучше всего, если вы также знакомы с pip и pyenv (или аналогичным инструментом виртуальной среды).

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

Настройка Django Admin

Django Admin предоставляет веб-интерфейс для создания объектов модели базы данных и управления ими. Чтобы увидеть это в действии, вам сначала понадобится проект Django и несколько объектных моделей. Установите Django в чистой виртуальной среде:

$ python -m pip install django
$ django-admin startproject School
$ cd School
$ ./manage.py startapp core
$ ./manage.py migrate
$ ./manage.py createsuperuser
Username: admin
Email address: [email protected]
Password:
Password (again):

Сначала вы создаете новый проект Django под названием School с приложением под названием core. Затем вы переносите таблицы аутентификации и создаете администратора. Доступ к экранам администратора Django разрешен только пользователям с флагами персонала или суперпользователя, поэтому вы используете команду управления createduperuser, чтобы создать суперпользователя.

Вам также необходимо изменить School/settings.py, чтобы включить новое приложение с именем core:

# School/settings.py
# ...

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "core",    # Add this line
]

Каталог основного приложения будет начинаться со следующих файлов внутри:

core/
│
├── migrations/
│   └── __init__.py
│
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py

Вас интересуют два из этих файлов:

  1. models.py определяет ваши модели базы данных.
  2. admin.py регистрирует ваши модели у администратора Django.

Чтобы продемонстрировать результат при настройке администратора Django, вам понадобятся несколько моделей. Отредактируйте core/models.py:

from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models

class Person(models.Model):
    last_name = models.TextField()
    first_name = models.TextField()
    courses = models.ManyToManyField("Course", blank=True)

    class Meta:
        verbose_name_plural = "People"

class Course(models.Model):
    name = models.TextField()
    year = models.IntegerField()

    class Meta:
        unique_together = ("name", "year", )

class Grade(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    grade = models.PositiveSmallIntegerField(
        validators=[MinValueValidator(0), MaxValueValidator(100)])
    course = models.ForeignKey(Course, on_delete=models.CASCADE)

Эти модели представляют учащихся, посещающих курсы в школе. У курса есть name и year, в котором он был предложен. Person имеет имя и фамилию и может пройти ноль или более курсов. Оценка содержит процентную оценку, полученную человеком на курсе.

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

Имена основных таблиц в базе данных немного отличаются от этих, но они связаны с моделями, показанными выше.

Каждую модель, которую вы хотите, чтобы Django представлял в интерфейсе администратора, необходимо зарегистрировать. Вы делаете это в файле admin.py. Модели из core/models.py регистрируются в соответствующем файле core/admin.py:

from core.models import Person, Course, Grade

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    pass

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    pass

@admin.register(Grade)
class GradeAdmin(admin.ModelAdmin):
    pass

Вы почти готовы к работе. После переноса моделей баз данных вы можете запустить сервер разработки Django и увидеть результаты:

$ ./manage.py makemigrations
$ ./manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, core, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  ...
  Applying core.0001_initial... OK
  Applying core.0002_auto_20200609_2120... OK
  Applying sessions.0001_initial... OK
$ ./manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
Django version 3.0.7, using settings 'School.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Теперь посетите http://127.0.0.1:8000/admin, чтобы увидеть интерфейс администратора. Вам будет предложено войти в систему. Используйте учетные данные, созданные с помощью команды управления createduperuser.

На главном экране администратора перечислены все зарегистрированные модели баз данных:

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

Список начинается пустым, как и ваша база данных. Нажав ADD PERSON, вы можете создать человека в базе данных. После сохранения вы вернетесь к списку объектов Person:

Хорошая новость в том, что у вас есть объект. Плохая новость в том, что объект Person (1) сообщает вам идентификатор объекта и ничего больше. По умолчанию администратор Django отображает каждый объект, вызывая для него str(). Вы можете сделать этот экран более полезным, добавив метод .__str __() к классу Person в core / models.py:

class Person(models.Model):
    last_name = models.TextField()
    first_name = models.TextField()
    courses = models.ManyToManyField("Course", blank=True)

    def __str__(self):
        return f"{self.last_name}, {self.first_name}"

Добавление Person .__ str __ () изменяет отображение, чтобы включить в интерфейс имя и фамилию Person. Вы можете обновить экран, чтобы увидеть изменения:

Так немного лучше! Теперь вы можете увидеть некоторую информацию об объекте Person. Рекомендуется добавить похожие методы как к объектам Course, так и к объектам Grade:

class Course(models.Model):
    # ...

    def __str__(self):
        return f"{self.name}, {self.year}"

class Grade(models.Model):
    # ...

    def __str__(self):
        return f"{self.grade}, {self.person}, {self.course}"

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


Django позволяет загружать данные в базу данных и из нее в файлах, называемых фикстурами. Скопируйте следующее в файл с именем core/fixtures/school.json:

[
    {
        "model": "core.person",
        "pk": 1,
        "fields": {
            "last_name": "Harris",
            "first_name": "Xander",
            "courses": [
                1,
                3
            ]
        }
    },
    {
        "model": "core.person",
        "pk": 3,
        "fields": {
            "last_name": "Rosenberg",
            "first_name": "Willow",
            "courses": [
                1,
                2,
                3
            ]
        }
    },
    {
        "model": "core.person",
        "pk": 16,
        "fields": {
            "last_name": "Summers",
            "first_name": "Buffy",
            "courses": [
                1,
                2,
                3
            ]
        }
    },
    {
        "model": "core.course",
        "pk": 1,
        "fields": {
            "name": "CompSci G11",
            "year": 1998
        }
    },
    {
        "model": "core.course",
        "pk": 2,
        "fields": {
            "name": "Psych 101",
            "year": 1999
        }
    },
    {
        "model": "core.course",
        "pk": 3,
        "fields": {
            "name": "Library Science G10",
            "year": 1997
        }
    },
    {
        "model": "core.grade",
        "pk": 1,
        "fields": {
            "person": 16,
            "grade": 68,
            "course": 1
        }
    },
    {
        "model": "core.grade",
        "pk": 2,
        "fields": {
            "person": 16,
            "grade": 87,
            "course": 2
        }
    },
    {
        "model": "core.grade",
        "pk": 3,
        "fields": {
            "person": 16,
            "grade": 76,
            "course": 3
        }
    },
    {
        "model": "core.grade",
        "pk": 4,
        "fields": {
            "person": 1,
            "grade": 58,
            "course": 1
        }
    },
    {
        "model": "core.grade",
        "pk": 5,
        "fields": {
            "person": 1,
            "grade": 58,
            "course": 3
        }
    },
    {
        "model": "core.grade",
        "pk": 6,
        "fields": {
            "person": 3,
            "grade": 98,
            "course": 3
        }
    },
    {
        "model": "core.grade",
        "pk": 7,
        "fields": {
            "person": 3,
            "grade": 97,
            "course": 2
        }
    }
]

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

$ ./manage.py loaddata school
Installed 13 object(s) from 1 fixture(s)

Теперь в вашей базе данных есть образцы объектов Person, Course и Grade.


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

Кастоимизация Django Admin

Умные люди, создавшие структуру Django, не только создали админку, но и сделали это таким образом, чтобы вы могли настроить его для своих проектов. Когда вы ранее регистрировали объект PersonAdmin, он унаследовал от admin.ModelAdmin. Большая часть настроек, которые вы можете сделать с помощью администратора Django, выполняется путем изменения ModelAdmin, и вы, конечно, можете изменить его!

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

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

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

Django Admin разделен на три основные области:

  1. Индекс приложения
  2. Списки изменений
  3. Изменить формы

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

В предыдущем примере индекс приложения отображал объекты Person, Course и Grade. При нажатии кнопки «People» отображаются списки изменений для объектов «Person». На странице со списком изменений Person, щелкнув объект Buffy Summers, вы попадете в форму изменения, чтобы отредактировать данные Buffy.

Изменение списка изменений с помощью list_display.

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

Вы можете настроить страницы списка изменений гораздо большим количеством способов, чем просто изменить строковое представление объекта. Атрибут list_display объекта admin.ModelAdmin указывает, какие столбцы отображаются в списке изменений. Это значение представляет собой набор атрибутов моделируемого объекта. Например, в core/admin.py измените PersonAdmin следующим образом:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ("last_name", "first_name")

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

Два столбца являются интерактивными, что позволяет сортировать страницу по данным столбца. Администратор также учитывает атрибут ordering, Meta раздела:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ("last_name", "first_name", "show_average")

    def show_average(self, obj):
        from django.db.models import Avg
        result = Grade.objects.filter(person=obj).aggregate(Avg("grade"))
        return result["grade__avg"]

В приведенном выше коде вы добавляете столбец для администратора, в котором отображается средняя оценка каждого учащегося. show_average() вызывается один раз для каждого объекта, отображаемого в списке.

Параметр obj – это объект для отображаемой строки. В этом случае вы используете его для запроса соответствующих объектов Grade для учащегося, с усреднением ответа по Grade.grade. Вы можете увидеть результаты здесь:

Имейте в виду, что среднюю оценку действительно нужно рассчитывать в объекте модели Person. Скорее всего, вам понадобятся данные где-нибудь еще, а не только в админке Django. Если бы у вас был такой метод, вы могли бы добавить его в атрибут list_display. Пример здесь показывает, что вы можете делать в объекте ModelAdmin, но, вероятно, это не лучший выбор для вашего кода.

По умолчанию сортируются только те столбцы, которые являются атрибутами объекта. show_average() нет. Это связано с тем, что сортировка выполняется базовым QuerySet, а не отображаемыми результатами. В некоторых случаях есть способы сортировки этих столбцов, но это выходит за рамки этого руководства.

Заголовок столбца основан на имени метода. Вы можете изменить заголовок, добавив атрибут к методу:

def show_average(self, obj):
    result = Grade.objects.filter(person=obj).aggregate(Avg("grade"))
    return result["grade__avg"]

show_average.short_description = "Average Grade"

По умолчанию Django защищает вас от HTML в строках, если строка введена пользователем. Чтобы отображение включало HTML, вы должны использовать format_html():

def show_average(self, obj):
    from django.utils.html import format_html

    result = Grade.objects.filter(person=obj).aggregate(Avg("grade"))
    return format_html("<b><i>{}</i></b>", result["grade__avg"])

show_average.short_description = "Average"

show_average() теперь имеет настраиваемый заголовок «Average» и отформатирован курсивом:

К сожалению, Django еще не добавил поддержку f-строки для format_html(), поэтому вы застряли на синтаксисе str.format().

Предоставление ссылок на страницы других объектов

Довольно часто объекты ссылаются на другие объекты с помощью внешних ключей. Вы можете указать list_display на метод, который возвращает ссылку HTML. Внутри core/admin.py измените класс CourseAdmin следующим образом:

from django.urls import reverse
from django.utils.http import urlencode

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ("name", "year", "view_students_link")

    def view_students_link(self, obj):
        count = obj.person_set.count()
        url = (
            reverse("admin:core_person_changelist")
            + "?"
            + urlencode({"courses__id": f"{obj.id}"})
        )
        return format_html('<a href="{}">{} Students</a>', url, count)

    view_students_link.short_description = "Students"

Этот код заставляет список изменений Course иметь три столбца:

  1. Название курса
  2. Год, в котором был предложен курс
  3. Ссылка, отображающая количество студентов в курсе

Вы можете увидеть результат на следующем снимке экрана:

Когда вы нажимаете 2 ученика, вы попадаете на страницу со списком изменений человека с примененным фильтром. На отфильтрованной странице показаны только ученики из Psych 101, Buffy и Willow. Ксандер не поступил в университет.

В примере кода для поиска URL-адреса в админке Django используется функция reverse(). Вы можете найти любую страницу администратора, используя следующее соглашение об именах:

"admin:%(app)s_%(model)s_%(page)"

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

  • admin: это пространство имен.
  • app это название приложения.
  • model – объект модели.
  • page это тип страницы администратора Django.

В приведенном выше примере view_students_link() вы используете admin:core_person_changelist, чтобы получить ссылку на страницу списка изменений объекта Person в основном приложении.

Вот доступные имена URL:

СтраницаИмя URLЦель
Список изменений%(app)s\_%(model)s\_changelistСписок страниц объектов модели
Добавить%(app)s\_%(model)s\_addСтраница создания объекта
История%(app)s\_%(model)s\_historyСтраница истории изменений объекта
Принимает object_id в качестве параметра
Удалить%(app)s\_%(model)s\_deleteСтраница удаления объекта
Принимает object_id в качестве параметра
Изменить%(app)s\_%(model)s\_changeСтраница редактирования объекта
Принимает object_id в качестве параметра

Вы можете отфильтровать страницу списка изменений, добавив к URL-адресу строку запроса. Эта строка запроса изменяет QuerySet, используемый для заполнения страницы. В приведенном выше примере строка запроса «?course__id={obj.id}» фильтрует список Person только для тех объектов, которые имеют совпадающее значение в Person.course.

Эти фильтры поддерживают поиск полей QuerySet с использованием двойного подчеркивания (__). Вы можете получить доступ к атрибутам связанных объектов, а также использовать модификаторы фильтра, такие как __exact и __startswith.

Вы можете найти полную информацию о том, чего вы можете достичь с помощью атрибута list_display, в документации Django admin.

Добавление фильтров на экран списка

Помимо фильтрации данных в списке изменений через вызывающий URL-адрес, вы также можете фильтровать с помощью встроенного виджета. Добавьте атрибут list_filter к объекту CourseAdmin в core/admin.py:

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ("name", "year", "view_students_link")
    list_filter = ("year", )
# ...

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

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

Если вам нужен больший контроль над фильтрацией, вы даже можете создать объекты фильтра, которые задают атрибуты поиска и соответствующий QuerySet.

Добавление поиска на экран списка

Фильтры экрана – не единственный способ уменьшить объем данных на экране. Django admin также поддерживает поиск с помощью опции search_fields, которая добавляет на экран поле поиска. Вы устанавливаете его с помощью кортежа, содержащего имена полей, которые будут использоваться для построения поискового запроса в базе данных.

Все, что пользователь вводит в поле поиска, используется в предложении ИЛИ полей, фильтрующих QuerySet. По умолчанию каждый параметр поиска окружен знаками%, что означает, что если вы ищете r, то в результатах появится любое слово с r внутри. Вы можете быть более точными, указав модификатор __ в поле поиска.

Отредактируйте PersonAdmin в core/admin.py следующим образом:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    search_fields = ("last_name__startswith", )

В приведенном выше коде поиск основан на фамилии. Модификатор __startswith ограничивает поиск фамилиями, которые начинаются с параметра поиска. Поиск по R дает следующие результаты:

При каждом поиске на странице списка изменений администратор Django вызывает метод get_search_results() вашего объекта admin.ModelAdmin. Он возвращает QuerySet с результатами поиска. Вы можете точно настроить поиск, перегрузив метод и изменив QuerySet. Более подробную информацию можно найти в документации.

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

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

Вы можете контролировать, какие поля включены, а также их порядок, редактируя параметр полей. Измените свой объект PersonAdmin, добавив атрибут fields:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    fields = ("first_name", "last_name", "courses")
# ...

Страницы добавления и изменения для Person теперь помещают атрибут first_name перед атрибутом last_name, хотя сама модель указывает обратное:

ModelAdmin.get_form() отвечает за создание ModelForm для вашего объекта. Вы можете переопределить этот метод, чтобы изменить форму. Добавьте в PersonAdmin следующий метод:

def get_form(self, request, obj=None, **kwargs):
    form = super().get_form(request, obj, **kwargs)
    form.base_fields["first_name"].label = "First Name (Humans only!):"
    return form

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

Сменить ярлык может быть недостаточно, чтобы вампиры не регистрировались в качестве студентов. Если вам не нравится ModelForm, созданная для вас администратором Django, вы можете использовать атрибут form для регистрации пользовательской формы. Внесите следующие дополнения и изменения в core/admin.py:

class PersonAdminForm(forms.ModelForm):
    class Meta:
        model = Person
        fields = "__all__"

    def clean_first_name(self):
        if self.cleaned_data["first_name"] == "Spike":
            raise forms.ValidationError("No Vampires")

        return self.cleaned_data["first_name"]

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    form = PersonAdminForm
# ...

Приведенный выше код обеспечивает дополнительную проверку на страницах добавления и изменения человека. Объекты ModelForm имеют богатый механизм проверки. В этом случае поле first_name проверяется на соответствие имени “Spike”. ValidationError не позволяет студентам с этим именем зарегистрироваться:

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

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

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

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

.../site-packages/django/contrib/admin/templates/
│
├── admin/
│   │
│   ├── auth/
│   │   └── user/
│   │       ├── add_form.html
│   │       └── change_password.html
│   │
│   ├── edit_inline/
│   │   ├── stacked.html
│   │   └── tabular.html
│   │
│   ├── includes/
│   │   ├── fieldset.html
│   │   └── object_delete_summary.html
│   │
│   ├── widgets/
│   │   ├── clearable_file_input.html
│   │   ├── foreign_key_raw_id.html
│   │   ├── many_to_many_raw_id.html
│   │   ├── radio.html
│   │   ├── related_widget_wrapper.html
│   │   ├── split_datetime.html
│   │   └── url.html
│   │
│   ├── 404.html
│   ├── 500.html
│   ├── actions.html
│   ├── app_index.html
│   ├── base.html
│   ├── base_site.html
│   ├── change_form.html
│   ├── change_form_object_tools.html
│   ├── change_list.html
│   ├── change_list_object_tools.html
│   ├── change_list_results.html
│   ├── date_hierarchy.html
│   ├── delete_confirmation.html
│   ├── delete_selected_confirmation.html
│   ├── filter.html
│   ├── index.html
│   ├── invalid_setup.html
│   ├── login.html
│   ├── object_history.html
│   ├── pagination.html
│   ├── popup_response.html
│   ├── prepopulated_fields_js.html
│   ├── search_form.html
│   └── submit_line.html
│
└── registration/
    ├── logged_out.html
    ├── password_change_done.html
    ├── password_change_form.html
    ├── password_reset_complete.html
    ├── password_reset_confirm.html
    ├── password_reset_done.html
    ├── password_reset_email.html
    └── password_reset_form.html

У шаблонизатора Django есть определенный порядок загрузки шаблонов. Когда он загружает шаблон, он использует первый шаблон, соответствующий названию. Вы можете переопределить шаблоны администратора, используя ту же структуру каталогов и имена файлов.

Шаблоны администратора находятся в двух каталогах:

  1. admin для страниц объекта модели.
  2. registration предназначен для смены пароля, входа и выхода.

Чтобы настроить страницу выхода, вам необходимо переопределить правильный файл. Относительный путь, ведущий к файлу, должен быть таким же, как переопределяемый. Вас интересует файл registration/logged_out.html. Начнем с создания каталога в проекте School:

$ mkdir -p templates/registration

Теперь сообщите Django о вашем новом каталоге шаблонов в файле School/settings.py. Найдите директиву TEMPLATES и добавьте папку в список DIR:

# School/settings.py
# ...

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",

        # Add the templates directory to the DIR option:
        "DIRS": [os.path.join(BASE_DIR, "templates"), ],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

Механизм шаблонов ищет каталоги в параметре DIR перед каталогами приложений, поэтому вместо этого будет загружено все, что имеет то же имя, что и шаблон администратора. Чтобы увидеть это в действии, скопируйте файл logged_out.html в каталог templates/registration, затем измените его:

{% extends "admin/base_site.html" %}
{% load i18n %}

{% block breadcrumbs %}<div><a href="{% url 'admin:index' %}">{% trans 'Home' %}</a></div>{% endblock %}

{% block content %}

<p>You are now leaving Sunnydale</p>

<p><a href="{% url 'admin:index' %}">{% trans 'Log in again' %}</a></p>

{% endblock %}

Вы настроили страницу выхода. Если вы нажмете ВЫЙТИ, вы увидите настраиваемое сообщение:

Шаблоны администратора Django глубоко вложены и не очень интуитивно понятны, но вы можете полностью контролировать их представление, если вам это нужно. Некоторые пакеты, включая Grappelli и Django Admin Bootstrap, полностью заменили шаблоны администратора Django, изменив их внешний вид.

Django Admin Bootstrap еще не совместим с Django 3, а Grappelli только недавно добавил поддержку, так что некоторые проблемы все еще могут возникать. При этом, если вы хотите увидеть силу переопределения шаблонов администратора, ознакомьтесь с этими проектами!

Вывод

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

В этом руководстве вы узнали, как:

  • Зарегистрировать свои объектные модели с помощью администратора Django
  • Добавить атрибуты в виде столбцов в списке изменений
  • Создать значений столбцов с вычисляемым содержимым
  • Перекрестные ссылки на административные страницы через ссылки
  • Фильтрация страницы списка изменений по строкам запроса
  • Сделать свой список изменений доступным для поиска
  • Настроить автоматический ModelFormобъект
  • Изменить HTML в шаблонах администратора Django

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


Совершенствуй знания каждый день у нас в Телеграм-каналах

Вопросы, реклама — VK | Telegram

django-admin — Начало работы с django-admin

замечания

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

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

Ресурсы

Версии

Версия Дата выхода
1,10 2106-08-01
1,9 2015-12-01
1,8 2015-04-01
1,7 2014-09-02
1,6 2013-11-06
1,5 2013-02-26
1.4 2012-03-23
1,3 2011-03-23
1.2 2010-05-17
1,1 2009-07-29
1,0 2008-09-03

Настройка Django Admin

Все, что вам нужно для начала работы с администратором Django, уже настроено в макете проекта Django по умолчанию. Это включает:

# settings.py

# `django.contrib.admin` and its dependancies.
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    ...,
]

MIDDLEWARE = [
    ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    ...
]

TEMPLATES = [
    {
        ...,
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                ...
            ],
        },
    },
]
 

Будьте осторожны с urls.py который немного отличается в Django> = 1.9, чем в более старых версиях.

1,9

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

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

1,9

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

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

Версия с include будет по-прежнему работать в Django 1.9, но устарела и будет удалена в будущем.

Если это еще не сделано, вы должны применить базовые миграции:

$ python manage.py migrate
 

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

$ python manage.py createsuperuser
 

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

$ python manage.py runserver
 

Посетите страницу администратора по адресу http://127.0.0.1:8000/admin/.

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

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

Это делается в подмодуле admin . Если ваше приложение было создано с помощью manage.py startapp , файл admin.py должен уже admin.py в вашем модуле приложения. В противном случае создайте его.

#myapp/admin.py
from django.contrib import admin
from myproject.myapp.models import MyModel

admin.site.register(MyModel)
 

Все параметры определены в подклассе ModelAdmin. некоторые варианты:

class MyCustomAdmin(admin.ModelAdmin):
    list_display = ('name','age','email')  # fields to display in the listing
    empty_value_display = '-empty-'        # display value when empty 
    list_filter = ('name', 'company')      # enable results filtering
    list_per_page = 25                     # number of items per page 
    ordering = ['-pub_date', 'name']       # Default results ordering

# and register it 
admin.site.register(MyModel, MyCustomAdmin)
 

Более краткий способ регистрации модели — использовать декоратор admin.register :

@admin.register(MyModel)
class MyCustomAdmin(admin.ModelAdmin)
    ...
 

Настроить django User Admin Model

from django.contrib.auth.models import User    
class UserAdmin(admin.ModelAdmin):
    list_display = ('email', 'first_name', 'last_name')
    list_filter = ('is_staff', 'is_superuser')
    
admin.site.unregister(User) 
admin.site.register(User, UserAdmin)
 

Нам нужно отменить регистрацию до регистрации пользовательского UserAdmin, потому что в django User Model Admin уже зарегистрирован. Поэтому нам нужно сначала отменить регистрацию модели пользователя в нашем admin.py, тогда мы можем зарегистрировать модель пользователя с пользовательским ModelAdmin

Удаление модели из страниц администратора

Django Admin поставляется с некоторыми моделями, зарегистрированными по умолчанию. В некоторых случаях вы можете удалить модель из страниц администратора.

Это делается в подмодуле admin . Если ваше приложение было создано с помощью manage.py startapp , файл admin.py должен быть уже установлен в вашем модуле приложения. В противном случае создайте его.

#myapp/admin.py
from django.contrib import admin
from django.contrib.auth.models import User

admin.site.unregister(User)
 

Что нужно знать, чтобы управлять пользователями в Django Admin

Перевод статьи Haki Benita: What You Need to Know to Manage Users in Django Admin

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

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

Знаете ли вы, что сотрудники, которые управляют другими пользователями в Django Admin, могут редактировать свои собственные разрешения? Знаете ли вы, что они также могут стать суперпользователями? В админке Django нет ничего, что могло бы этому помешать, так что это решать вам!

К концу этого урока вы узнаете, как:

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

Модель Permissions (Разрешения)

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

Django поставляется со встроенной системой аутентификации. Система аутентификации включает пользователей, группы и разрешения.

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

  1. add: Пользователи с этим разрешением могут добавить экземпляр модели.
  2. delete: Пользователи с этим разрешением могут удалить экземпляр модели.
  3. change: Пользователи с этим разрешением могут обновить экземпляр модели.
  4. view: Пользователи с этим разрешением могут просматривать экземпляры этой модели. Это разрешение было очень ожидаемым, и, наконец, оно было добавлено в Django 2.1.

Имена разрешений следуют особому соглашению об именах: <app>.<action>_<modelname>.

Давайте рассмотрим это подробнее:

  • <app> это имя приложения. Например модель User импортируется из auth (django.contrib.auth).
  • <action> является одним из действий указаных выше (adddeletechange, или view).
  • <modelname> это название модели, все строчные буквы.

Знание этого соглашения об именах поможет вам легче управлять разрешениями. Например, имя разрешения на изменение пользователя — auth.change_user.

Как проверяются права

Модель permissions предоставляется пользователям или группам. Чтобы проверить, есть ли у пользователя определенные разрешения, вы можете сделать следующее:

>>> from django.contrib.auth.models import User
>>> u = User.objects.create_user(username='haki')
>>> u.has_perm('auth.change_user')
False

Стоит отметить, что .has_perm() всегда будет возвращать True для активного суперпользователя, даже если разрешение на самом деле не существует:

>>> from django.contrib.auth.models import User
>>> superuser = User.objects.create_superuser(
...     username='superhaki',
...     email='[email protected]',
...     password='secret',
)
>>> superuser.has_perm('does.not.exist')
True

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

Как применяются права

Модели Django сами обычно не используют разрешения. По умолчанию единственные права доступа — это права для Django Admin.

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

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

from django.core.exceptions import PermissionDenied

def users_list_view(request):
    if not request.user.has_perm('auth.view_user'):
        raise PermissionDenied()

Если пользователь, сделавший запрос, вошел в систему и прошел проверку подлинности, то request.user будет содержать экземпляр User. Если пользователь не вошел в систему, то request.user будет экземпляром AnonymousUser. Это специальный объект, используемый Django для обозначения неаутентифицированного пользователя. Использование has_perm в AnonymousUser всегда возвращает False.

Если пользователь, отправляющий запрос, не имеет разрешения view_user, вы должны создать исключение PermissionDenied, и клиенту должен вернуться ответ со статусом 403.

Чтобы упростить применение разрешений в представлениях, Django предоставляет сокращенный декоратор под названием permission_required, который делает то же самое:

from django.contrib.auth.decorators import permission_required

@permission_required('auth.view_user')
def users_list_view(request):
    pass

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

{% if perms.auth.delete_user %}
<button>Delete user!</button>
{% endif %}

Некоторые популярные сторонние приложения, такие как Django rest framework, также предоставляют полезную интеграцию с разрешениями модели Django.

Django Admin и модель Permissions

Django admin имеет очень тесную интеграцию со встроенной системой аутентификации, в частности, с моделью permissions. Django admin «из коробки» использует модель permissions:

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

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

Реализация пользовательских бизнес-ролей в Django Admin

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

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

Setup: Пользовательская регистрация модели User

Чтобы расширить страницу администратора для модели User, вам нужно отменить текущую регистрацию администратора модели, предоставленного Django, и зарегистрировать собственную:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

# Unregister the provided model admin
admin.site.unregister(User)

# Register out own model admin, based on the default UserAdmin
@admin.register(User)
class CustomUserAdmin(UserAdmin):
    pass

CustomUserAdmin расширяет UserAdmin в Django. На этом этапе, если вы войдете в систему Django Admin по адресу http://127.0.0.1:8000/admin/auth/user, вы должны увидеть, что страница администратора пользователей не изменилась:

Запрет на обновление полей

Необслуживаемые формы администратора — главный кандидат на ужасные ошибки. Пользователь может легко обновить экземпляр модели через Django Admin, чего приложение не ожидает. В большинстве случаев пользователь даже не заметит, что что-то не так. Такие ошибки обычно очень трудно отследить и исправить.

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

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

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    readonly_fields = [
        'date_joined',
    ]

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

Но что, если вы хотите запретить обновление поля только некоторым пользователям?

Условный запрет на обновление полей

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

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

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        is_superuser = request.user.is_superuser

        if not is_superuser:
            form.base_fields['username'].disabled = True

        return form

Давайте разберем что тут было сделано:

  • Чтобы внести коррективы в форму, нужно переопределить get_form(). Эта функция используется Django для создания формы изменения по умолчанию для модели.
  • Чтобы условно отключить поле, сначала нужно получить форму по умолчанию, созданную Django, а затем, если пользователь не является суперпользователем, отключить поле имени пользователя.

Теперь, когда не-суперпользователь пытается отредактировать пользователя, поле username будет отключено. Любая попытка изменить username через Django Admin потерпит неудачу. Когда суперпользователь пытается отредактировать пользователя, поле username будет редактируемым и будет вести себя как положено.

Запретить не суперпользователям предоставлять права суперпользователя

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

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

from typing import Set

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        is_superuser = request.user.is_superuser
        disabled_fields = set()  # type: Set[str]

        if not is_superuser:
            disabled_fields |= {
                'username',
                'is_superuser',
            }

        for f in disabled_fields:
            if f in form.base_fields:
                form.base_fields[f].disabled = True

        return form

В дополнение к предыдущему примеру тут сделаны следующие дополнения:

  1. Инициализирован пустой набор disabled_fields, который будет содержать поля для отключения. set — это структура данных, которая содержит уникальные значения. В этом случае имеет смысл использовать set, потому что вам нужно отключить поле только один раз. Оператор |= используется для выполнения обновления на месте OR (ИЛИ). Для получения дополнительной информации о set, почитайте это Sets in Python.
  2. Затем, если пользователь является суперпользователем, было добавлено в set два поля (username из предыдущего примера и is_superuser). Они будут препятствовать тому, чтобы не-суперпользователи становились суперпользователями.
  3. Наконец, далее перебираются все поля в set, и помечаются как отключенные.

Django User Admin Двухступенчатая форма

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

Этот двухэтапный процесс уникален для модели User. Чтобы приспособиться к этому уникальному процессу, вы должны убедиться, что поле существует, прежде чем попытаться его отключить. В противном случае вы можете получить KeyError.

Предоставление разрешений только через использования групп

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

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

from typing import Set

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        is_superuser = request.user.is_superuser
        disabled_fields = set()  # type: Set[str]

        if not is_superuser:
            disabled_fields |= {
                'username',
                'is_superuser',
                'user_permissions',
            }

        for f in disabled_fields:
            if f in form.base_fields:
                form.base_fields[f].disabled = True

        return form

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

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

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

from typing import Set

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        is_superuser = request.user.is_superuser
        disabled_fields = set()  # type: Set[str]

        if not is_superuser:
            disabled_fields |= {
                'username',
                'is_superuser',
                'user_permissions',
            }

        # Prevent non-superusers from editing their own permissions
        if (
            not is_superuser
            and obj is not None
            and obj == request.user
        ):
            disabled_fields |= {
                'is_staff',
                'is_superuser',
                'groups',
                'user_permissions',
            }

        for f in disabled_fields:
            if f in form.base_fields:
                form.base_fields[f].disabled = True

        return form

Аргумент obj является экземпляром объекта, с которым вы сейчас работаете:

  • Когда obj имеет значение None, форма используется для создания нового пользователя.
  • Когда obj не None, форма используется для редактирования существующего пользователя.

Чтобы проверить, работает ли пользователь, выполняющий запрос, с самим собой, нужно сравнить request.user с obj. Поскольку это пользователь admin, obj является экземпляром User или None. Когда пользователь, делающий запрос, request.user, равен obj, это означает, что пользователь обновляет самого себя. В этом случае мы отключаем все конфиденциальные поля, которые можно использовать для получения разрешений.

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

Переопределение разрешений

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

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

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

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    def has_delete_permission(self, request, obj=None):
        return False

Как и в случае с get_form(), obj — это экземпляр, с которым вы сейчас работаете:

  • Когда obj имеет значение None, пользователь запрашивает представление списка.
  • Когда obj не None, пользователь запрашивает представление изменения конкретного экземпляра.

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

  • Предотвращение изменений в рабочее время
  • Реализация разрешений на уровне объектов

Ограничение доступа к настраиваемым действиям

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

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

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    actions = [
        'activate_users',
    ]

    def activate_users(self, request, queryset):
        cnt = queryset.filter(is_active=False).update(is_active=True)
        self.message_user(request, 'Activated {} users.'.format(cnt))
    activate_users.short_description = 'Activate Users'  # type: ignore

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

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

Django admin использует внутреннюю функцию для получения действий. Чтобы скрыть activate_users() от пользователей без разрешения на изменение, переопределите get_actions():

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    actions = [
        'activate_users',
    ]

    def activate_users(self, request, queryset):
        assert request.user.has_perm('auth.change_user')
        cnt = queryset.filter(is_active=False).update(is_active=True)
        self.message_user(request, 'Activated {} users.'.format(cnt))
    activate_users.short_description = 'Activate Users'  # type: ignore

    def get_actions(self, request):
        actions = super().get_actions(request)
        if not request.user.has_perm('auth.change_user'):
            del actions['activate_users']
        return actions

get_actions() возвращает OrderedDict. Ключ — это имя действия, а значение — это функция действия. Чтобы скорректировать возвращаемое значение, нужно переопределить функцию, выбираете исходное значение и, в зависимости от прав пользователя, удалить настраиваемое действие activate_users из dict.

Для сотрудников, у которых нет прав на change_user(), действие activate_users не будет отображаться в раскрывающемся списке действий.

Заключение

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

В этом руководстве вы защитили свою систему, внеся следующие изменения в Django Admin:

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

Была ли вам полезна эта статья?

[5 / 5]

Как добавить пользовательские кнопки в Django Admin

В этой статье «шпаргалке» рассмотрено добавление пользовательских кнопок в интерфейс Django Admin. В первой части рассказано как добавить одно кнопку на страницу списка выбранной модели — list view. Например кнопку импорта чего либо. Во второй части рассказано как добавить пользовательские кнопки действий (actions) для каждой выбранной записи отдельно с дополнительными формами.


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

Для этого нам нужно будет внести изменения в файл admin.py и добавить дополнительный шаблон админки для соответствующей модели.

Начнем с файла шаблона. Наш шаблон будет основан на стандартном шаблоне, мы просто внесем в него небольшое изменение. В папке соответствующего приложения добавим каталоги: xxx/templates/admin/model_change_list.html.

В этот шаблон добавим следующие изменения.

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

{% block object-tools %}
  <form action="import/" method="POST">
    {% csrf_token %}
    <input type="submit" value="Импорт" />
  </form>
    {{ block.super }}
{% endblock %}

В файле admin.py добавим указание на файл этот шаблон. Добавим функцию для регистрации нового URL get_urls. В нее добавим маршрут импорта с указанием на функцию импорта. И далее добавим саму функцию, импорта:

from django.contrib import admin
from django.http import HttpResponseRedirect
from django.conf.urls import url

from monitor.models import LoginMonitor
from monitor.import_custom import ImportCustom

@admin.register(LoginMonitor)<br>
class LoginMonitorAdmin(admin.ModelAdmin):<br>
    change_list_template = "admin/monitor_change_list.html"

    def get_urls(self):
        urls = super(LoginMonitorAdmin, self).get_urls()
	custom_urls = [
	    url('^import/$', self.process_import, name='process_import'),]
	return custom_urls + urls
    def process_import_btmp(self, request):
	import_custom = ImportCustom()
	count = import_custom.import_data()
	self.message_user(request, f"создано {count} новых записей")
	return HttpResponseRedirect("../")

Все, для добавление новой кнопки этого достаточно.


Далее будет перевод старой, но все еще актуальной статьи: Haki Benita — How to Add Custom Action Buttons to Django Admin


В последнем посте мы представили шаблон, который мы часто используем в наших моделях Django. Мы использовали приложение по управлению банковского счета с моделями Action и Action, чтобы продемонстрировать, как мы решаем общие проблемы, такие как параллелизм и проверка. У банковского счета было две операции, которые мы хотели выставить в интерфейсе администратора — deposit (добавления на счет) и withdraw (снятие со счета).

Мы собираемся добавить кнопки в интерфейсе администратора Django для ввода и вывода денег со счета, и мы сделаем это менее чем за 100 строк кода!

Как это будет выглядеть в конце?

Django Admin interface with custom action buttons
Источник: https://hakibenita.com/images/01-how-to-add-custom-action-buttons-to-django-admin.png

Почему бы не использовать существующие action в интерфейсе администратора?

Встроенные action в интерфейса администратора работают с набором запросов queryset. Они скрыты в выпадающем меню на верхней панели инструментов и в основном полезны для выполнения массовых операций. Хорошим примером является действие по умолчанию. Вы отмечаете несколько строк и выбираете «удалить строки» из выпадающего меню. Это не очень быстро и не всегда подходит для некоторых случаев использования.

Django built in actions
Источник: https://hakibenita.com/images/02-how-to-add-custom-action-buttons-to-django-admin.png

Другим недостатком является то, что действия не доступны в detail view. Чтобы добавить кнопки в подробный вид, вам нужно переопределить шаблон.

Формы

Прежде всего, нам нужно получить дополнительные данные от пользователя для выполнения действия. Естественно для этого, нам нужна форма. Нам нужна одна форма для deposit и одна форма для withdraw.

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

Все наши actions имеют общие аргументы, такие как comment и send_email. Actions также обрабатывают успех и неудачу аналогичным образом.

Давайте начнем с базовой формы для обработки общего action:

# forms.py

from django import forms
from common.utils import send_email

from . import errors

class AccountActionForm(forms.Form):
    comment = forms.CharField(
        required=False,
        widget=forms.Textarea,
    )
    send_email = forms.BooleanField(
        required=False,
    )

    @property
    def email_subject_template(self):
        return 'email/account/notification_subject.txt'

    @property
    def email_body_template(self):
        raise NotImplementedError()

    def form_action(self, account, user):
        raise NotImplementedError()

    def save(self, account, user):
        try:
            account, action = self.form_action(account, user)
        except errors.Error as e:
            error_message = str(e)
            self.add_error(None, error_message)
            raise

        if self.cleaned_data.get('send_email', False):
            send_email(
                to=[account.user.email],
                subject_template=self.email_subject_template,
                body_template=self.email_body_template,
                context={
                    "account": account,
                    "action": action,
                }
            )

    return account, action

  • Каждое action имеет комментарий comment и возможность отправить уведомление, если действие выполнено успешно.
  • Фактическая операция выполняется при сохранении формы. Это похоже на то, как работает ModelForm.
  • В целях ведения журнала и аудита вызывающая сторона должна предоставить пользователя, выполняющего action.
  • Обязательные свойства, которые не реализованы производными формами, вызовут NotImplementedError. Таким образом, мы гарантируем, что разработчик получит информативное сообщение об ошибке, если он забудет что-то реализовать.
  • Ошибки обрабатываются на уровне базового класса исключений. Наши модели определяют базовый класс ошибок, поэтому мы можем легко перехватить все (и только) исключения, связанные с аккаунтом, и обработать их соответствующим образом.

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

# forms.py
from django.utils import timezone

from .models import Account, Action

class WithdrawForm(AccountActionForm):
    amount = forms.IntegerField(
        min_value=Account.MIN_WITHDRAW,
        max_value=Account.MAX_WITHDRAW,
        required=True,
        help_text='How much to withdraw?',
    )

    email_body_template = 'email/account/withdraw.txt'

    field_order = (
        'amount',
        'comment',
        'send_email',
    )

    def form_action(self, account, user):
        return Account.withdraw(
            id=account.pk,
            user=account.user,
            amount=self.cleaned_data['amount'],
            withdrawn_by=user,
            comment=self.cleaned_data['comment'],
            asof=timezone.now(),
        )

  • Мы расширили базу AccountActionForm и добавили поле amount с соответствующими проверками.
  • Мы заполнили необходимые атрибуты, email_body_template.
  • Мы реализовали action формы, используя classmethod из предыдущего поста. Модель заботится о блокировке записи, обновлении любых вычисляемых полей и добавлении соответствующих действий в журнал.

Следующим шагом является добавление deposit. Для deposit требуются поля amount, reference и reference_type:

# forms.py

class DepositForm(AccountActionForm):
    amount = forms.IntegerField(
        min_value=Account.MIN_DEPOSIT,
        max_value=Account.MAX_DEPOSIT,
        required=True,
        help_text='How much to deposit?',
    )
    reference_type = forms.ChoiceField(
        required=True,
        choices=Action.REFERENCE_TYPE_CHOICES,
    )
    reference = forms.CharField(
        required=False,
    )

    email_body_template = 'email/account/deposit.txt'

    field_order = (
        'amount',
        'reference_type',
        'reference',
        'comment',
        'send_email',
    )

    def form_action(self, account, user):
        return Account.deposit(
            id=account.pk,
            user=account.user,
            amount=self.cleaned_data['amount'],
            deposited_by=user,
            reference=self.cleaned_data['reference'],
            reference_type=self.cleaned_data['reference_type'],
            comment=self.cleaned_data['comment'],
            asof=timezone.now(),
        )


На данный момент мы получили необходимые формы для принятия, проверки и оформления deposit и withdraw. Следующим шагом является его интеграция в представление списка администратора Django.


Admin

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

# admin.py
from django.contrib import admin

from .models import Account

@admin.register(Account)
class AccountAdmin(admin.ModelAdmin):
    date_heirarchy = (
        'modified',
    )
    list_display = (
        'id',
        'user',
        'modified',
        'balance',
        'account_actions',
    )
    readonly_fields = (
        'id',
        'user',
        'modified',
        'balance',
        'account_actions',
    )
    list_select_related = (
        'user',
    )

    def account_actions(self, obj):
        # TODO: Render action buttons


Примечание: мы можем сделать просмотр списка намного лучше, добавив ссылку на пользователя и actions учетной записи. Мы можем добавить несколько полей поиска и многое другое. Ранее я писал о проблемах производительности в интерфейсе администратора при масштабировании приложения Django для сотен тысяч пользователей. Там есть несколько приятных трюков, которые могут сделать даже этот простой вид намного приятнее.

Добавление кнопок Action

Мы хотим добавить кнопки action для каждой учетной записи и сделать так, чтобы они ссылались на страницу с формой. В Django есть функция для регистрации URL get_urls в виде списка. Давайте использовать эту функцию, чтобы добавить маршруты для наших пользовательских действий:

# admin.py

from django.utils.html import format_html
from django.core.urlresolvers import reverse

class AccountAdmin(admin.ModelAdmin):

    # ...

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            url(
                r'^(?P<account_id>.+)/deposit/$',
                self.admin_site.admin_view(self.process_deposit),
                name='account-deposit',
            ),
            url(
                r'^(?P<account_id>.+)/withdraw/$',
                self.admin_site.admin_view(self.process_withdraw),
                name='account-withdraw',
            ),
        ]
        return custom_urls + urls

    def account_actions(self, obj):
        return format_html(
            '<a href="{}">Deposit</a> '
            '<a href="{}">Withdraw</a>',
            reverse('admin:account-deposit', args=[obj.pk]),
            reverse('admin:account-withdraw', args=[obj.pk]),
        )
    account_actions.short_description = 'Account Actions'
    account_actions.allow_tags = True

    def process_deposit(self):
        # TODO

    def process_withdraw(self):
        # TODO

  1. Мы зарегистрировали два URL, один для deposit и один для withdraw.
  2. Мы сослались на каждый маршрут на соответствующие функции process_deposit и process_withdraw. Эти функции отобразят промежуточную страницу с соответствующей формой и выполнят операцию.
  3. Мы добавили настраиваемое поле account_actions, чтобы отображать кнопки для каждого действия. Преимущество использования «обычного» поля администратора, такого как account_actions, заключается в том, что оно доступно как в подробностях (detail view), так и в виде списка (list view).

Давайте перейдем к реализации функций для обработки actions:

# admin.py

from django.http import HttpResponseRedirect
from django.template.response import TemplateResponse

from .forms import DepositForm, WithdrawForm

class AccountAdmin(admin.ModelAdmin):

   # ...

   def process_deposit(self, request, account_id, *args, **kwargs):
        return self.process_action(
            request=request,
            account_id=account_id,
            action_form=DepositForm,
            action_title='Deposit',
        )

   def process_withdraw(self, request, account_id, *args, **kwargs):
        return self.process_action(
            request=request,
            account_id=account_id,
            action_form=WithdrawForm,
            action_title='Withdraw',
        )

   def process_action(
        self,
        request,
        account_id,
        action_form,
        action_title
   ):
        account = self.get_object(request, account_id)

        if request.method != 'POST':
            form = action_form()

        else:
            form = action_form(request.POST)
            if form.is_valid():
                try:
                    form.save(account, request.user)
                except errors.Error as e:
                    # If save() raised, the form will a have a non
                    # field error containing an informative message.
                    pass
                else:
                    self.message_user(request, 'Success')
                    url = reverse(
                        'admin:account_account_change',
                       args=[account.pk],
                        current_app=self.admin_site.name,
                    )
                    return HttpResponseRedirect(url)

        context = self.admin_site.each_context(request)
        context['opts'] = self.model._meta
        context['form'] = form
        context['account'] = account
        context['title'] = action_title

        return TemplateResponse(
            request,
            'admin/account/account_action.html',
            context,
        )


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

process_action обрабатывает отправку формы для обоих действий. Функция принимает форму, название действия и идентификатор учетной записи. process_withdraw и process_deposit, используются для установки соответствующего контекста для каждой операции.

Для завершения процесса нам нужен template для промежуточной страницы, который содержит форму действия. Мы собираемся основывать наш шаблон на существующем шаблоне, используемом Django Admin:

<!-- templates/admin/account/account_action.html -->

{% extends "admin/change_form.html" %}
{% load i18n admin_static admin_modify %}

{% block content %}

<div>

  <form action="" method="POST">

    {% csrf_token %}
    {% if form.non_field_errors|length > 0 %}
      <p>
          "Please correct the errors below."
      </p>
      {{ form.non_field_errors }}
    {% endif %}

    <fieldset>
      {% for field in form %}
        <div>
          {{ field.errors }}
          {{ field.label_tag }}
          {{ field }}
          {% if field.field.help_text %}
          <p>
            {{ field.field.help_text|safe }}
          </p>
          {% endif %}
        </div>
      {% endfor %}
    </fieldset>

    <div>
      <input type="submit" value="Submit">
    </div>

  </form>
</div>

{% endblock %}


И это все!

Теперь наши сотрудники могут легко вносить и снимать средства прямо из интерфейса администратора. Не нужно создавать дорогую панель инструментов.

Я обещал, что мы сделаем это в 100 строк, и мы сделали это за меньше количество!


Заключение

Большая часть реализации взята из превосходного (превосходного!) Пакета django-import-export. Это сэкономило нам часы «Вы можете просто отправить мне данные в Excel?» и мы любим это за это. Если вы не знакомы с этим, вы должны обязательно проверить это.

Была ли вам полезна эта статья?

[5 / 2.4]

Расширяем возможности приложения администрирования Django

Три способа доработки этого мощного приложения для соответствия вашим нуждам

Лиза Дэли
Опубликовано 04.03.2011

Приложение администрирования Django

Платформа Django предлагает разработчикам множество функциональности: зрелую стандартную библиотеку, активное сообщество пользователей и все преимущества языка Python. В то время как другие инфраструктуры разработки Web-приложений могут предложить то же самое, уникальным достоинством Django является ее встроенное приложение администрирования — admin.

Приложение администрирования предоставляет «из коробки» расширенную функциональность для создания, чтения, обновления и удаления данных (Create-Read-Update-Delete или CRUD), избавляя разработчиков от часов повторяющейся работы. Это является важным как при разработке Web-приложений, потому что с его помощью программисты могут быстро изучать свои модели данных, так и при развертывании приложений, потому что не имеющие отношения к технике конечные пользователи могут пользоваться приложением администрирования для добавления и редактирования содержимого сайта.

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

Краткий обзор приложения администрирования

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

Листинг 1. Включаем приложение администрирования в urls.py
from django.conf.urls.defaults import *

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    # Uncomment the next line to enable the admin:
    (r'^admin/(.*)', admin.site.root),
)
Версии ПО, используемые в этой статье
  • Django V1.0.2
  • SQLite V3
  • Python V2.4–2.6 (Django пока не поддерживает Python 3)
  • IPython (для работы в консоли)

Механизм объектно-ориентированного отображения (Object-Relational Mapper или ORM) Django
поддерживает множество баз данных, среди которых
проще всех в установке sqlite3. Кроме того, sqlite3 поставляется в комплекте со многими ОС.
Примеры из этой статьи должны работать с любой базой данных.
С полным списком баз данных, поддерживаемых Django, можно ознакомиться в разделе
Ресурсы.

Django предоставляет удобный способ настройки рабочего окружения с помощью команды
python manage.py shell.
Во всех примерах кода, приводимых в этой статье, предполагается, что окружение настраивается именно таким образом.

В терминах Django, в этой статье предполагается следующее:

  • Проект Django называется more_with_admin.
  • В проекте more_with_admin имеется приложение с именем
    examples.

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

Также необходимо добавить приложение
django.contrib.admin в кортеж settings.INSTALLED_APPS.

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

Приложение администрирования живет внутри пакета
Django. Если вы его установили с помощью
setuptools, приложение администрирования должно находиться в директории site-packages/django/contrib/admin.
Ниже приводится пример создания в директории проекта символической ссылки, указывающей на исходный код приложения администрирования Django.
Вы можете воспользоваться этой ссылкой, изменив ее в соответствии с вашей операционной системой и местонахождением пакета Django.

$ ln -s
/path/to/Python/install/site-packages/django/contrib/admin admin-source

Метод admin.autodiscover()
пробегается по всем приложениям, указанным в кортеже settings.INSTALLED_APPS
и ищет файл с именем admin.py. Он обычно находится на верхнем уровне директории приложения,
на одном уровне с models.py.

Приложению examples нужен файл models.py, показанный в листинге 2.
Соответствующий файл admin.py приведен ниже.

Листинг 2. Пример файла models.py
для этого приложения
from django.db import models

class Document(models.Model):
    '''
    документ - это запись в блоге или на wiki-страничке, 
    имеющая некоторое текстовое содержимое
    '''
    name = models.CharField(max_length=255)
    text = models.TextField()
    
    def __unicode__(self):
        return self.name

class Comment(models.Model):
    '''комментарий  - это некоторый текст, относящийся  к данному документу'''
    document = models.ForeignKey(Document, related_name='comments')
    text = models.TextField()

Теперь можно запустить сервер разработки Django и взглянуть на приложение администрирования:

python manage.py runserver

По умолчанию приложение администрирования доступно по адресу
http://localhost:8000/admin/.
Зарегистрировавшись, вы увидите главный экран администратора, показанный на рисунке 1.

Рисунок 1.
Главный экран администратора Django
Изменение кода в admin.py

В отличие от остальных файлов приложения Django,
если вы при работающем Web-сервере разработки Django вносите изменения в admin.py,
то для вступления изменений в силу, возможно, придется вручную перезапустить сервер.

Заметьте, что модели приложения еще недоступны, потому что мы не создали файл admin.py.
В листинге 3 показан код, который даст возможность работать с моделями через приложение администрирования.

Листинг 3. Пример файла
admin.py
from django.contrib import admin
from more_with_admin.examples import models

class DocumentAdmin(admin.ModelAdmin):
    pass

class CommentAdmin(admin.ModelAdmin):
    pass

admin.site.register(models.Document, DocumentAdmin)
admin.site.register(models.Comment, CommentAdmin)

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

Рисунок 2.
Администратор Django готов работать с пользовательскими моделями данных

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

Имена директорий в папках приложения администрирования

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

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

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

Сначала отредактируем файл settings.py проекта,
указав в нем директорию, в которой Django должен искать шаблоны (листинг 4).

Листинг 4. Добавляем в settings.py директории с шаблонами
TEMPLATE_DIRS = (
    "/path/to/project/more_with_admin/templates",
    "/path/to/project/more_with_admin/examples/templates",
)

Затем создадим в проекте следующие директории:

$ mkdir templates/admin/examples/document/
$ mkdir templates/admin/examples/comment/

Приложение администрирования Django
сначала попытается найти шаблоны в директории с именем, совпадающим с названием

вашего приложения (здесь examples),
затем с названием моделей
(document и comment)
и только потом, в случае неудачи, будет использовать системные шаблоны для отображения страницы.

Переопределяем страницу добавления/удаления экземпляра модели

Для добавления и редактирования экземпляров модели приложение администрирования использует страницу
change_form.html.
Для начала создадим
в директории
templates/admin/examples/document/
страницу с именем
change_form.html
и поместим в нее следующую строку для наследования
шаблона Django: {% extends "admin/change_form.html" %}.

Теперь все готово для доработки приложения.
Уделите некоторое время знакомству с содержимым реального шаблона admin/change_form.html.
Он довольно хорошо организован в блоки, которые можно переопределять,
но в некоторых случаях доработка может потребовать «оптового» копирования блоков.
Тем не менее, переопределение основанных на блоках шаблонов
всегда предпочтительнее копирования страницы целиком.

Какого рода доработку можно сделать на странице добавления/редактирования?
Допустим, мы хотим для каждого документа
добавить предварительный просмотр пяти последних комментариев.

Сначала создадим тестовые данные(листинг 5).

Листинг 5. Создаем с помощью оболочки Django
экземпляр модели Document
с несколькими комментариями
$ python manage.py shell
In [1]: from examples import models
In [2]: d = models.Document.objects.create(name='Test document', 
                                           text='This is a test document.')
In [3]: for c in range(0, 10):
   ...:     models.Comment.objects.create(text='Comment number %s' % c, document=d)

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

Рисунок 3.
Стандартная страница добавления/редактирования для
модели Document

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

Листинг 6.
Добавляем модель комментария к модели документов в приложении администрирования
from django.contrib import admin
from more_with_admin.examples import models

class CommentInline(admin.TabularInline):
    model = models.Comment

class DocumentAdmin(admin.ModelAdmin):
    inlines = [CommentInline,]

class CommentAdmin(admin.ModelAdmin):
    pass

admin.site.register(models.Document, DocumentAdmin)
admin.site.register(models.Comment, CommentAdmin)

На рисунке 4 показан новый вид страницы добавления/редактирования после
добавления элемента управления TabularInline.

Рисунок 4.
Страница добавления/удаления документа после добавления модели комментария
в виде класса
Inline

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

В таком случае имеется два подхода.
Первый подход – отредактировать HTML-виджеты, ассоциированные с классами
inline,
с помощью предоставляемого Django интерфейса администрирования виджетов.
Виджеты в документации Django описаны весьма подробно.
Другой подход — модифицировать шаблон добавления/редактирования напрямую.
Этот подход наиболее полезен, если вы вообще не собираетесь использовать специфическую функциональность администратора.

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

Переменные, предоставляемые приложением администрирования
Django

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

Таблица 1.
Переменные, необходимые для доработки шаблона приложения администрирования
ПеременнаяОписание
object_idЭто первичный ключ для редактируемого объекта.
Если вы дорабатываете страницу экземпляра какой-либо одной модели (например, документа),
это все, что вам понадобится.
content_type_idЕсли вы переопределяете страницы, работающие с множеством моделей,
используйте эту переменную, чтобы опрашивать инфраструктуру ContentTypes
для получения имени модели. Больше информации о типах содержимого можно получить в разделе Ресурсы.

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

Чтобы вывести комментарии, относящиеся к документу, необходим код, который нельзя вводить непосредственно в шаблон Django. Для таких случаев наилучшим решением является использование тэга шаблона. Сначала создадим директорию тэгов шаблонов и файл __init__.py в ней:

$ mkdir examples/templatetags/
$ touch examples/templatetags/__init__.py

Создадим новый файл с именем examples/templatetags/example_tags.py
и добавим в него приведенный ниже код (листинг 7).

Листинг 7. Тэг шаблона для извлечения комментариев к документу с заданным ID
from django import template
from examples import models

register = template.Library()

@register.inclusion_tag('comments.html')
def display_comments(document_id):
    document = models.Document.objects.get(id__exact=document_id)
    comments = models.Comment.objects.filter(document=document)[0:5]
    return { 'comments': comments }

Так как здесь используется тэг включения шаблона, необходимо создать соответствующий шаблон: comments.html. Отредактируем файл examples/templates/comments.html file и поместим в него код, показанный в листинге 8.

Листинг 8. Шаблон для предварительного просмотра комментариев
{% for comment in comments %}
<blockquote>{{ comment.text }}</blockquote>
{% endfor %}

Теперь пришло время добавить это на страницу приложения администрирования.
Закомментируйте в admin.py ссылки на
CommentInline
и сделайте в вашей локальной версии шаблона change_form.html изменения,
показанные в листинге 9.

Листинг 9. Включение тэга шаблона в страницу добавления/редактирования
{% extends "admin/change_form.html" %}

{% load example_tags %}

{% block after_field_sets %}
  {% if object_id %}{% display_comments object_id %}{% endif %}
  {% endblock %}

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

На рисунке 5 показана обновленная форма.

Рисунок 5.
Страница добавления/редактирования документа после добавления
на нее собственного тэга шаблона

Модифицируем поведение приложения администрирования

Как видите, одним только переопределением шаблонов можно добиться довольно многого.
Но что, если мы хотим поменять само поведение приложения администрирования?
Это можно сделать, подправив исходный код, но тогда вы будете ограничены только той версией Django,
которую будете использовать на момент внесения исправлений.

Переопределяем методы в
AdminModel

По умолчанию нажатие кнопки
Save
в приложении администрирования возвращает пользователя
на страницу списочного отображения экземпляров модели. Обычно это всех устраивает,
но что, если мы хотим переходить сразу на страницу
предварительного просмотра объекта, находящуюся вне приложения администрирования?
Это распространенное поведение в системах управления содержимым
(content management system или CMS).

Метод

В
листинге 10
предполагается, что класс
Document
был изменен и теперь включает в себя метод
get_absolute_url(), который является рекомендуемым способом
определения моделями Django своего канонического представления.
Если метод определен, в администраторе Django на каждой странице этой модели
также появляется полезная кнопка View on site.

Большая часть функциональности приложения администрирования реализована в классе
admin.ModelAdmin.
От этого класса наследуются объекты в admin.py.
В нем имеется очень много публичных методов, которые можно переопределять.
Определение этого класса можно посмотреть в файле admin-source/options.py.

Есть два способа поменять поведение кнопки
Save:
можно переопределить метод
admin.ModelAdmin.response_add,
отвечающий за само перенаправление после сохранения объекта,
а также можно переопределить метод
admin.ModelAdmin.change_view.
Последний способ немного проще.

Листинг 10.
Переопределяем страницу, на которую перенаправляются пользователи
после сохранения документа
class DocumentAdmin(admin.ModelAdmin):

    def change_view(self, request, object_id, extra_context=None):

        result = super(DocumentAdmin, self).change_view(request, object_id, extra_context)

        document = models.Document.objects.get(id__exact=object_id)
        
        if not request.POST.has_key('_addanother') and 
              not request.POST.has_key('_continue'):
            result['Location'] = document.get_absolute_url()
        return result

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

Добавление функциональности в приложение администрирования с помощью сигналов

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

В приложении администрирования имеется функциональность, которую разработчики
желают поменять особенно часто – это управление пользователями с помощью класса
django.contrib.auth.models.User.
Часто приложение администрирования является единственным местом,
где добавляются или модифицируются пользователи
Django,
что делает сложной доработку под себя этого полезного класса.

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

В листинге 11 демонстрируется, как легко добавить функцию,
выполняющуюся при каждом сохранении экземпляра класса
User.
Сигналы обычно добавляют в models.py.

Листинг 11.
Использование сигналов Django
для уведомления о создании новых пользователей
from django.db import models
from django.db.models import signals
from django.contrib.auth.models import User
from django.core.mail import send_mail

class Document(models.Model):
    [...]

class Comment(models.Model):
    [...]

def notify_admin(sender, instance, created, **kwargs):
    '''Оповещает администратора о добавлении нового пользователя.'''
    if created:
       subject = 'New user created'
       message = 'User %s was added' % instance.username
       from_addr = '[email protected]'
       recipient_list = ('[email protected]',)
       send_mail(subject, message, from_addr, recipient_list)        

signals.post_save.connect(notify_admin, sender=User)

Сигнал
post_save
предоставляется
Django,
он генерируется каждый раз при создании или сохранении экземпляра модели.
Метод connect()
здесь принимает два аргумента:
функцию обратного вызова (notify_admin)
и аргумент sender,
который сообщает о том, что эту функцию следует вызывать только при
сохранении экземпляров модели
User.

Внутрь функции обратного вызова сигнал
post_save
передает отправителя (класс модели),
экземпляр этой модели и булево значение, обозначающее, был ли этот экземпляр только что создан.
В этом примере метод посылает электронное сообщение только при создании нового экземпляра модели
User;
в противном случае не делается ничего.

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

Более глубокие изменения: добавляем права строкового уровня

Почему ?

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

Если задать только
null=True или вообще ничего, то
приложение администрирования Django перед сохранением заставит пользователя вручную выбрать значение
«added by»,
хотя вместо этого мы хотим, чтобы при сохранении по умолчанию выбирался текущий пользователь.

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

В ряде случаев хочется разрешить пользователям изменять только какие-либо специфичные объекты. Такие права часто называют правами строкового уровня, так как они отражают способность изменять только некоторые строки в таблице базы данных вместо права изменять любые записи в таблице без ограничений. Например, в приложении examples можно разрешить пользователям видеть только их собственные документы.

Сначала, как показано в листинге 12, добавим в models.py атрибут, в котором будет храниться имя создателя экземпляра модели Document.

Листинг 12. Добавляем в models.py информацию о пользователе, создавшем
каждый экземпляр модели Document
from django.db import models
from django.db.models import signals
from django.contrib.auth.models import User
from django.core.mail import send_mail
    
class Document(models.Model):
    name = models.CharField(max_length=255)
    text = models.TextField()
    added_by = models.ForeignKey(User, 
      null=True, blank=True)

    def get_absolute_url(self):
        return 'http://example.com/preview/document/%d/' % self.id

    def __unicode__(self):
        return self.name
[...]

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

Поменяем метод save_model()
в файле admin.py так, как показано в листинге 13.

Листинг 13.
Переопределяем метод в DocumentAdmin
для сохранения текущего пользователя в базу данных при создании экземпляра модели
from django.contrib import admin

class DocumentAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if getattr(obj, 'added_by', None) is None:
            obj.added_by = request.user
        obj.last_modified_by = request.user
        obj.save()

[...]

Если атрибут added_by равен None,
значит это новая запись, которая раньше не сохранялась.
(Также можно проверять, что change равно false,
это обозначает, что запись добавляется, но проверка пустоты поля added_by
обеспечивает, что будут заполняться и записи, которые были добавлены не из приложения администрирования.)

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

Переопределим метод
queryset()
так, как показано в листинге 14,
чтобы ограничить список только документами, созданными текущим пользователем.
Суперпользователи могут видеть все документы.

Листинг 14.
Переопределяем результат запроса, возвращаемый списочными страницами
from django.contrib import admin
from more_with_admin.examples import models

class DocumentAdmin(admin.ModelAdmin):
   
    def queryset(self, request):
        qs = super(DocumentAdmin, self).queryset(request)

        # если это суперпользователь - показываем все документы
        if request.user.is_superuser:
            return qs
        
        return qs.filter(added_by=request.user)
[...]

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

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

Заключение

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

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

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

В Django версии 1.1 в приложении администрирования будут добавлены две часто запрашиваемые новые возможности:
возможность линейного (inline) редактирования полей на страницах списочного просмотра
и действия администратора (admin
actions), которые позволяют обновлять за один раз множество объектов.
Оба добавления устранят необходимость писать эту функциональность с нуля
при расширении и доработке приложения

Ресурсы для скачивания
Похожие темы
  • Оригинал статьи: Doing more with the Django admin

    (EN).

  • Разработчикам, которые только начинают знакомиться с Django или приложением администрирования,
    следует начать с
    руководства Django (EN).
  • Главная страница документации приложения администрирования
    и
    исходный код приложения администрирования
    являются самым лучшим и полным справочником
    по этому приложению (EN).
  • Ознакомьтесь со
    списком сигналов, предоставляемых
    Django,
    и
    документацией по созданию собственных сигналов (EN).
  • Узнайте о двух новых возможностях приложения администрирования в Django
    версии 1.1: действиях администратора
    и редактируемых списках (EN).
  • В этой статье демонстрировалось редактирование
    страниц, специфичных для одной модели.
    Если вам нужно редактировать страницы,
    относящиеся к нескольким моделям, ознакомьтесь с
    имеющейся в Django
    инфраструктурой contenttypes (EN).
  • В документации Django
    содержится
    полный список баз данных,
    поддерживаемых
    Django.
    Начиная с версии 1.0, в Django также появилась возможность добавлять поддержку новых баз данных (EN).
  • Узнайте больше об изменении

    механизма перенаправления запросов в приложении администрирования
    (EN).

  • Многие дистрибутивы Linux®, а также Mac OS® X имеют в своем комплекте SQLite,
    однако если его нет в вашей системе, вы можете загрузить его
    с сайта проекта SQLite (EN).
  • SQLite V3: Начиная с версии 2.5,
    в Python появилась поддержка SQLite 3 без необходимости в дополнительных драйверах.
    В ранних версиях Python для этого приходилось загружать пакет
    pysqlite (EN).
  • Интервью и дискуссии разработчиков в
    подкастах developerWorks (EN).
  • Следите за developerWorks в Twitter (EN).
  • Разработайте ваш следующий проект с помощью
    пробного ПО от IBM,
    доступного для загрузки и на DVD.(EN)
  • Загрузите
    ознакомительные версии продуктов IBM
    или поработайте
    с онлайновой пробной версией IBM SOA Sandbox и получите практический опыт с инструментами разработки и связующим ПО от
    DB2®, Lotus®, Rational®, Tivoli® и WebSphere®.(EN)

Улучшаем админку / Хабр

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

И тут на помощь приходит django-admin-tools. С этим приложением минут за 20 можно получить «приборную панель» с произвольной группировкой приложений/моделей, вкладками, любым числом колонок, различными блоками, которые каждый пользователь сможет расставить, как ему удобнее, скрывать и сворачивать по желанию, закладками, настраиваемым меню и удобным способом добавления во все это хозяйство всего, чего только можно придумать.

Вот так, например, сейчас выглядит админка к сайту НадоВместе:


(это только часть, вот скриншот целиком)

Разберемся поподробнее.

Установка

1. pip install -e hg+http://bitbucket.org/izi/django-admin-tools/#egg=django-admin-tools
Ставим дев-версию, т.к. я фанат дев-версий там много новых вкусных штук: например, упрощен API и добавлены группы. Если не установлен mercurial, то можно скачать последнюю ревизию архивом, распаковать и запустить python setup.py install.

2. Добавляем admin_tools в INSTALLED_APPS (обязательно до django.contrib.admin):

INSTALLED_APPS = (
    'admin_tools',
    'admin_tools.theming',
    'admin_tools.menu',
    'admin_tools.dashboard',    
    # ...
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.admin'
    # ... и другие приложения ...
)

3. python manage.py syncdb

4. подключаем в urls.py:

urlpatterns = patterns('',
    url(r'^admin_tools/', include('admin_tools.urls')),
    #... и т.д. ...
)

5. копируем медиа-файлы (js, css и картинки) в MEDIA_ROOT проекта. Что-то вроде этого — вы ведь используете virtualenv?

cp -r /home/kmike/envs/nadovmeste/src/django-admin-tools/admin_tools/media/admin_tools /path/to/yourproject/media/

Можно вместо копирования сделать симлинк или использовать django-static-files.

Все, можно зайти в админку и удивиться страшной пятнистой шапке тому, как все поменялось. Установка, как видите, вполне обычная, никаких джанговских файлов заменять не нужно (как в grappelli было когда-то).

Блоки

Самая полезная штука в django-admin-tools — это, конечно, блоки. Вы можете настроить, какие блоки и как показывать на заглавной странице, писать свои блоки и брать готовые.

1. Создаем заготовку для «приборной панели»:

python manage.py customdashboard

После этого в корне проекта появится файл dashboard.py с заготовкой. Можно его, в принципе, и руками написать.

В файле будет содержаться 2 класса: CustomIndexDashboard и CustomAppIndexDashboard — для главной страницы админки и страницы отдельного приложения. Нас тут будет интересовать класс CustomIndexDashboard.

2. Указываем в settings.py, что будем использовать свою «приборную панель» на заглавной странице админки:

ADMIN_TOOLS_INDEX_DASHBOARD = 'yourproject.dashboard.CustomIndexDashboard'

3. Для примера: объединим в одном блоке стандартные джанговские модели из auth и свои данные о профайлах, назвав при этом блок по-русски:

from admin_tools.dashboard import modules, Dashboard

class CustomIndexDashboard(Dashboard):

    def __init__(self, **kwargs):
        Dashboard.__init__(self, **kwargs)
        self.children.append(
            modules.ModelList(
                title = u'Пользователи',
                models=(
                    'django.contrib.auth.*',
                    'my_accounts.models.Profile',
                ),
            )
        )

В списке моделей указываются полные пути к моделям, которые требуется подключить. Все модели, которые перечислены в models, должны быть зарегистрированы в джанговской админке как обычно. Если моделей несколько, то можно их все не перечислять, т.к. есть поддержка *. Если вы включили кучу моделей через * и нужно из них убрать несколько, то есть симметричный параметру models параметр exclude со списком моделей, которые показывать не нужно (там тоже есть поддержка *).

Стандартные блоки

django-admin-tools включает в стандартную поставку несколько готовых блоков для приборной панели. Детальную информацию о них можно найти в документации. Тут будет просто краткий обзор + описание замечательного modules.Group, которого не было в документации на момент написания статьи.

Импортировать их следует так: from admin_tools.dashboard import modules

1. modules.ModelList — как мне кажется, это самый основной и полезный блок. Позволяет группировать произвольные модели в рамках одного блока.

2. modules.Group — еще один супер-полезный блок. Позволяет группировать любые другие блоки внутри себя. Блоки могут или располагаться друг над другом, или в виде «аккордеона», или во вкладках. Очень удобно, например, для графиков, или для отделения основных и часто используемых разделов от побочных.

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

        self.children.append(modules.Group(
            title=u"Статистика",
            display="tabs",
            children=[
                nadovmeste_modules.Overview(),
                nadovmeste_modules.Subscribers(),
                nadovmeste_modules.Finances(),
                nadovmeste_modules.Users(),
            ]
        ))

В списке children можно указывать любые другие блоки, в.т.ч. разных типов. В примере тут не стандартные модули из admin_tools.dashboard.modules, а свои (о том, как их делать — позже).

Поддержки вложенных групп пока нет (а если точнее, то сейчас js при этом работает неправильно).

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

4. modules.AppList — по сути, аналог главной страницы стандартной джанговской админки. Список приложений и моделей в них. Скажу по секрету, тут есть еще не документированный параметр models, который абсолютно аналогичен этому параметру в modules.ModelList — с той разницей, что потом модели будут сгруппированы по приложениям. Этот блок полезен, если хочется добавить все по-быстрому, или повторить обычную джанговскую админку — в остальных случаях, как мне кажется, лучше подходит ModelList. Хотя может это дело вкуса.

5. modules.RecentActions — список последних действий, как в стандартной джанговской админке. Не знаю, зачем он нужен 🙂

6. modules.Feed — позволяет показывать ленты RSS в админке.

Пишем свои блоки

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

1. Наследуемся от admin_tools.dashboard.modules.DashboardModule:

class MyModule(modules.DashboardModule):
    def is_empty(self):
        return self.message == ''

    def __init__(self, **kwargs):
        super(MyModule, self).__init__(**kwargs)
        self.template = 'my_blocks/hello.html'
        self.message = kwargs.get('message', '')

2. Делаем шаблон templates/my_blocks/hello.html

{% extends "admin_tools/dashboard/module.html" %}
{% block module_content %}
    <h5>{{ module.message  }}</h5>
{% endblock %}

Как видите, объект модуля передается в шаблон. Это означает, что можно передавать любые данные через его атрибуты (что мы и сделали в примере с message).

3. Подключаем блок в dashboard.py

self.children.append(MyModule(title=u"Приветствие", message = u'Привет!'))

Все, готово. Думаю, теперь понятно, как делать любые более сложные штуки, рисовать в блоках графики и тд. Готовим данные, делаем шаблон. Если в контексте шаблона нужен request, то переопределяйте метод init_with_context (по ссылке — пример).

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

Да, еще, если нужно что-то просто дописать сверху или снизу стандартного блока, то можно свой блок/шаблон не делать, а воспользоваться атрибутами модуля pre_content и post_content.

Внешний вид

Люди достаточно осторожно подошли к дизайнерству, и новые элементы смотрятся вполне органично рядом со стандартными джанговскими. Но если вам тоже не нравится ненужный заголовок и кошмарная пятнистая стандартная шапка из django-admin-tools, то их проще всего убрать с помощью css. Хорошо бы еще логотип в шапку добавить. Заодно и с тем, как делать темы, разберемся.

1. Делаем css-файл со своей темой. Для примера можно посмотреть тему, которая используется в нашей админке, еще пример есть в стандартной поставке.

2. Подключаем файл с темой: в settings.py добавляем настройку

ADMIN_TOOLS_THEMING_CSS = 'css/theming.css' # путь относительно MEDIA_ROOT
Что дальше

В статье нет ничего про меню, закладки, настройку собственно приборных панелей, про панели для отдельных приложений. Обо всем этом можно почитать в документации. Если хотите помочь проекту, подключившись к разработке — welcome. Если что не работает в django-admin-tools, то это я все сломал, если что-то сделано круто — напишите весточку David Jean Louis.

Небольшие хитрости

Если вы обновили модули в своей приборной панели (добавили, удалили, поменяли местами), и после этого все куда-то уехало, то удалите записи из DashboardPreferences.

Статистика на скриншоте — с тестового сервера, реальные данные nadovmeste.ru не «спалил». Если интересно, то в следующей статье расскажу, как заполнять базу большим количеством тестовых данных, и как строк за 5 кода (включая шаблон) получать любые графики со статистикой (как, например, на скриншоте — график со статистикой регистраций пользователей по дням).

Да, спасибо obiwanus и leoglu за ценные замечания на этапе подготовки статьи.

Административный сайт Django | Документация Django

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

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

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

Обзор¶

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

Если вы не используете шаблон проекта по умолчанию, следующие требования:

  1. Добавить 'django.contrib.admin ' и его зависимости —
    django.contrib.auth , django.contrib.contenttypes ,
    django.contrib.messages и django.contrib.sessions — на ваш
    INSTALLED_APPS Настройка .

  2. Настроить DjangoTemplates
    backend в настройках TEMPLATES с
    django.template.context_processors.request ,
    django.contrib.auth.context_processors.auth и
    джанго.contrib.messages.context_processors.messages в
    параметр 'context_processors' из OPTIONS .

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

    django.template.context_processors.request был добавлен как
    требование в опции 'context_processors' для поддержки нового
    AdminSite.enable_nav_sidebar .

  3. Если вы настроили настройку MIDDLEWARE ,
    django.contrib.auth.middleware.AuthenticationMiddleware и
    джанго.contrib.messages.middleware.MessageMiddleware должен быть
    включены.

  4. Подключите URL-адреса администратора к вашему URLconf.

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

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

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

Другие темы¶

См. Также

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

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

ModelAdmin объектов¶

класс ModelAdmin

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

 от администратора импорта django.contrib
from myproject.myapp.models import Автор

класс AuthorAdmin (admin.ModelAdmin):
    проходить
admin.site.register (Автор, АвторAdmin)
 

Вам вообще нужен объект ModelAdmin ?

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

 от администратора импорта django.contrib
from myproject.myapp.models import Автор

admin.site.register (Автор)
 

.

django-admin и manage.py | Документация Django

django-admin — это утилита командной строки Django для административных задач.
Этот документ описывает все, что он может делать.

Кроме того, в каждом проекте Django автоматически создается manage.py . Это
делает то же самое, что и django-admin , но также устанавливает
DJANGO_SETTINGS_MODULE переменной среды, чтобы она указывала на ваш
файл проекта settings.py .

Скрипт django-admin должен находиться в вашем системном пути, если вы установили
Django через pip .Если это не на вашем пути, убедитесь, что у вас есть виртуальный
среда активирована.

Как правило, при работе с одним проектом Django проще использовать
manage.py , чем django-admin . Если вам нужно переключиться между несколькими
Файлы настроек Django, используйте django-admin с
DJANGO_SETTINGS_MODULE или --settings в командной строке
вариант.

Примеры командной строки в этом документе используют django-admin для
быть последовательным, но любой пример может использовать manage.py или python -m django
так же, как и.

Использование¶

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

Получение помощи во время выполнения¶

django-admin help

Запустите django-admin help , чтобы отобразить информацию об использовании и список
команды, предоставляемые каждым приложением.

Запустите django-admin help - команды для отображения списка всех доступных
команды.

Запустите django-admin help , чтобы отобразить описание данного
команду и список ее доступных опций.

Названия приложений¶

Многие команды принимают список «имен приложений». «Имя приложения» — это базовое имя
пакет, содержащий ваши модели. Например, если ваш INSTALLED_APPS
содержит строку 'mysite.blog' , имя приложения — blog .

Определение версии¶

django-admin версия

Запустите django-admin version , чтобы отобразить текущую версию Django.

Вывод соответствует схеме, описанной в PEP 440 :

Отображение вывода отладки¶

Используйте --verbosity , чтобы указать количество уведомлений и отладки
информация, которую django-admin выводит на консоль.

Доступные команды¶

чек

django-admin check [app_label [app_label...]]

Использует структуру проверки системы для проверки всего
Проект Django для общих проблем.

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

 django-admin проверить auth admin myapp
 

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

- тег TAGS , -t TAGS

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

 django-admin check --tag models --tag compatibility
 
- база данных база данных

Новое в Django 3.1.

Указывает базу данных для запуска проверок, требующих доступа к базе данных:

 django-admin check --database default --database other
 

По умолчанию эти проверки не запускаются.

--list-tags

Выводит список всех доступных тегов.

- развернуть

.

Администратор Django — Python Django Tutorials

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

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

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

Доступ к сайту администратора Django

Когда вы запускали startproject в главе 2, Django создал и настроил для вас сайт администратора по умолчанию. Все, что вам нужно сделать сейчас, это создать пользователя-администратора (суперпользователя) для входа на сайт администратора.Чтобы создать пользователя с правами администратора, выполните следующую команду из виртуальной среды:

  python manage.py создает суперпользователя  

Введите желаемое имя пользователя и нажмите ввод:

  Имя пользователя: admin  

Django запросит у вас адрес электронной почты:

  Адрес электронной почты: [email protected]  

Последний шаг — ввести пароль. Введите пароль дважды, второй раз для подтверждения пароля:

  Пароль: **********
Пароль еще раз): *********
Суперпользователь успешно создан. 

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

Сначала убедитесь, что сервер разработки запущен, затем откройте веб-браузер по адресу http://127.0.0.1:8000/admin/ . Вы должны увидеть экран входа в систему администратора (рис. 7-1).

Рисунок 7-1: Экран входа администратора в Django.

Войдите в систему, используя созданную вами учетную запись суперпользователя. После входа в систему вы должны увидеть страницу индекса администратора Django (рис. 7-2).

Рисунок 7-2: Индексная страница администратора Django.

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

Регистрация моделей с помощью администратора

Сейчас здесь мало что происходит, потому что мы не зарегистрировали модели нашего приложения — Venue , MyClubUser и Event — у администратора.Регистрация и настройка модели для администратора выполняется путем добавления моделей в файл admin.py приложения events (изменения выделены жирным шрифтом):

  # \ myclub_root \ events \ admin.py

1 от администратора импорта django.contrib
  2 из .models import Venue, MyClubUser, Event
3
4 admin.site.register (Место проведения)
5 admin.site.register (MyClubUser)
6 admin.site.register (Событие)   

Мы добавили четыре строки кода в наш файл admin.py :

  • Строка 2 .Импортируйте модели Venue , MyClubUser и Event .
  • Строка 4 . Зарегистрируйте модель Venue у администратора.
  • Строка 5 . Зарегистрируйте модель MyClubUser у администратора.
  • Строка 6 . Зарегистрируйте модель Event у администратора.

Сохраните файл, обновите страницу в браузере, и ваша индексная страница администратора должна выглядеть, как показано на рисунке 7-3. Вы можете видеть, что теперь есть группа Events в группе Authentication and Authorization .

Рисунок 7-3: После регистрации модели Venue , MyClubUser и Event отображаются в панели администратора.

Когда вы регистрируете модель у администратора, вы можете использовать админку для добавления, редактирования и удаления записей модели. Теперь мы зарегистрировали модели Event , MyClubUser и Venue с помощью администратора, мы можем использовать его для управления объектами, пользователями и событиями нашего клуба.

Администратор

Django разработан, чтобы быть простым и интуитивно понятным для нетехнических пользователей.Каждая модель, зарегистрированная у администратора, имеет список изменений и форму редактирования . Если вы нажмете Venues в индексе администратора, откроется список изменений мест (рисунок 7.4). Ваш список мест может быть пуст — я добавил несколько записей, чтобы вы могли видеть список изменений по умолчанию для модели.

Рисунок 7-4: Список изменений Venues. Нажмите «Добавить место», чтобы добавить новое место.

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

Создание дополнительных полей

Введите название места, адрес и почтовый индекс в пустой форме, но оставьте поля Контактный телефон, Интернет-адрес и адрес электронной почты пустыми. Щелкните «Сохранить». Ваш экран должен выглядеть примерно так, как показано на рисунке 7.5. Эта ошибка возникла из-за того, что по умолчанию все поля модели являются обязательными.

Рисунок 7-5: По умолчанию все поля обязательны при добавлении записей в админке.

Это не всегда то, что вам нужно. Например, у заведения может не быть веб-адреса, а у места проведения может быть адрес электронной почты или номер телефона, но не оба сразу. Чтобы исправить эту ошибку, нам необходимо обновить модель Venue (изменения выделены жирным шрифтом):

  # \ myclub_root \ events \ models.py

Заведение 1 класса (модели. Модель):
2 name = models.CharField ('Название объекта', max_length = 120)
3 адреса = модели.CharField (max_length = 300)
4 zip_code = models.CharField ('Почтовый индекс', max_length = 12)
5 phone = models.CharField ('Контактный телефон', max_length = 20 , blank = True )
6 web = models.URLField ('Веб-адрес' , пусто = True )
7 email_address = models.EmailField ('Адрес электронной почты' , пусто = True )
8
9 def __str __ (сам):
10 вернуть self.name  

Вы можете видеть в строках 5, 6 и 7 Я установил для параметра поля blank значение True .По умолчанию False , что делает поле обязательным.

Поскольку мы изменили модель, нам необходимо обновить базу данных. Сначала запустите makemigrations :

  (env_myclub) ... \ myclub_root> python manage.py makemigrations
Миграции для "событий":
  события \ миграции \ 0003_auto_20200523_0740.py
    - Изменить поле email_address на месте проведения
    - Изменить полевой телефон на месте проведения
    - Изменить полевую сеть на объекте  

Затем запустите команду migrate , чтобы перенести изменения в базу данных:

  (env_myclub)... \ myclub_root> python manage.py migrate
Выполняемые операции:
Применить все миграции: admin, auth, contenttypes, events, sessions
Выполняемые миграции:
Применение событий. 0003_auto_20200523_0740 ... OK  

Перезагрузите сервер разработки и войдите в систему с правами администратора. Щелкните ссылку «Добавить» рядом со списком Venues , чтобы открыть форму редактирования (рис. 7-6).

Рисунок 7-6: Форма редактирования места проведения с дополнительными полями.

Первое, что вы должны заметить, это то, что имена полей «Контактный телефон», «Веб-адрес» и «Электронный адрес» больше не выделяются жирным шрифтом.Это означает, что эти поля больше не требуются. Введите некоторую информацию для названия места, адреса и почтового индекса и нажмите «Сохранить». У вас не должно возникнуть проблем с вводом нового места проведения с пустыми полями. Django отобразит сообщение об успешном завершении и вернется в режим просмотра списка изменений места проведения.

Настройка списка изменений объекта

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

  1. Отображение названий заведений в алфавитном порядке для облегчения просмотра.
  2. Добавьте адрес места проведения и номер телефона в список, чтобы упростить доступ к основной контактной информации; и
  3. Добавьте возможности поиска по имени и адресу, чтобы, когда список мест проведения стал больше, было легче найти конкретное место.

В Django каждая модель представлена ​​в интерфейсе администратора классом ModelAdmin . Чтобы настроить отображение модели в админке, вы можете установить несколько параметров в настраиваемом подклассе ModelAdmin . Откройте свой admin.py и добавьте собственный класс VenueAdmin (изменения выделены жирным шрифтом):

  # \ myclub_root \ events \ admin.py

1 от администратора импорта django.contrib
2 из .models import Venue, MyClubUser, Event
3
4
  5 @ admin.register (Место проведения)
6 класс VenueAdmin (admin.ModelAdmin):
7 list_display = ('имя', 'адрес', 'телефон')
8 заказ = ('имя',)
9 search_fields = ('имя', 'адрес') 
10
11
  12 # admin.site.register (Место проведения) 
13 admin.site.register (MyClubUser)
14 админ.site.register (Событие)  

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

  • Строка 5 . Мы используем декоратор register для регистрации нового класса у администратора. Декоратор регистра функционально эквивалентен методу регистра . Я использую здесь декоратор, потому что в большинстве книг и онлайн-руководств используется метод register , и я хотел дать вам пример альтернативного способа регистрации ваших пользовательских подклассов ModelAdmin .Если вы хотите использовать метод регистрации, удалите строку 5 и замените строку 12 на admin.site.register (Venue, VenueAdmin) .
  • Строка 6 — это объявление класса VenueAdmin , который является подклассом класса admin.ModelAdmin .
  • Строка 7 устанавливает опцию list_display для отображения названия места, адреса и номера телефона в списке изменений места проведения.
  • Строка 8 устанавливает порядок сортировки по умолчанию для названия места проведения.Поскольку упорядочивает , это кортеж из 1 (одноэлементный), не забудьте запятую в конце! СОВЕТ: Если вы хотите, чтобы сортировка по умолчанию была в обратном порядке, вы можете использовать ordering = ('- ',) . В этом примере, если вы хотите отсортировать в обратном порядке по названию места проведения, это будет ordering = ('-name',) .
  • Строка 9 устанавливает в полях поиска по умолчанию название и адрес места проведения.
  • Строка 12 . Поскольку мы используем декоратор register , строка 12 не нужна, поэтому я закомментировал ее.

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

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

Глядя на ваш индивидуальный список изменений места проведения, вы заметите, что:

  1. Заведения перечислены в алфавитном порядке.
  2. В списке указаны адрес и номер телефона каждого места проведения, а также название места проведения; и
  3. На страницу списка изменений добавлена ​​панель поиска.Django будет выполнять поиск без учета регистра в полях названия места проведения и адреса для любого термина, который вы вводите в поле поиска. Чтобы снова отобразить все записи, найдите пустую строку.

Настройка списка изменений событий и формы

Теперь мы внесем некоторые изменения в список и форму изменения событий, чтобы сделать его более удобным для пользователя. Вернитесь в индекс администратора, щелкнув Администрирование Django в верхнем меню, затем щелкните ссылку «Добавить» справа от списка событий , чтобы открыть форму редактирования события (рис. 7-8).

Форма редактирования события должна быть достаточно простой, чтобы ей было легко следовать. Обратите внимание, как в поле «Место проведения» автоматически отображается раскрывающийся список всех мест, записанных в базе данных. Django создал эту ссылку для вас, когда вы создали связь между моделью Event и соответствующими записями в модели Venues . Также обратите внимание, что вы можете создать новое место проведения из формы редактирования мероприятия, щелкнув зеленый крестик рядом с полем.

Рисунок 7-8: Форма изменения события автоматически связывается с записями о месте проведения в базе данных через отношения модели.Чтобы добавить новое место из формы изменения мероприятия, щелкните зеленый крестик.

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

  1. Свяжите поле диспетчера событий с базой данных пользователей, чтобы можно было выбрать сотрудника.
  2. Удалить список участников из формы.
  3. Измените порядок полей в форме, включая указание названия мероприятия и места проведения в одной строке.

Мы также хотим внести следующие изменения в список изменений событий:

  1. Измените список изменений событий для отображения дополнительных столбцов; и
  2. Добавить фильтр по дате и фильтр по параметрам места проведения в список изменений событий.

Обновление модели событий

Чтобы связать модель Event с пользовательской базой данных, нам нужно внести некоторые изменения в класс модели (изменения выделены жирным шрифтом):

  # \ myclub_root \ events \ models.py

1 из моделей импорта django.db
  2 из django.contrib.auth.models импортировать пользователя 
3
4 # ...
5
Событие 6 класса (models.Model):
7 name = models.CharField ('Имя события', max_length = 120)
8 event_date = models.DateTimeField ('Дата события')
9 место проведения = модели.ForeignKey (Venue, blank = True, null = True, on_delete = models.CASCADE)
  10 manager = models.ForeignKey (User, blank = True, null = True, on_delete = models.SET_NULL) 
11 участников = models.ManyToManyField (MyClubUser, blank = True)
12 description = models.TextField (blank = True)
13
14 def __str __ (сам):
15 вернуть self.name  

В строке 2 мы импортировали модель User из django.contrib.auth.models . В строке 10 мы изменили поле manager на поле ForeignKey , которое связано с моделью User .Для параметра on_delete установлено значение SET_NULL , поэтому, если пользователь удален, для всех событий, которыми он управлял, будет установлен идентификатор своего менеджера NULL .

После изменения класса модели создайте и запустите миграцию.

Сначала удалите все записи событий!

Убедитесь, что у вас нет записей о событиях в базе данных, иначе миграция не удастся!

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

  (env_myclub) ... \ myclub_root> python manage.py makemigrations
Миграции для "событий":
события \ миграции \ 0004_auto_20200523_0751.py
    - Сменить полевого менеджера на мероприятии
    
(env_myclub) ... \ myclub_root> python manage.py migrate
Выполняемые операции:
Применить все миграции: admin, auth, contenttypes, events, sessions
Выполняемые миграции:
Применение событий. 0004_auto_20200523_0751 ... OK  

Изменение списка изменений событий и формы редактирования

Чтобы настроить администратора для модели Event , мы изменим admin.py и добавьте подкласс ModelAdmin , как мы это сделали с моделью Venue (изменения выделены жирным шрифтом):

  # \ myclub_root \ events \ admin.py

1 от администратора импорта django.contrib
2 из .models import Venue, MyClubUser, Event
3
4
5 @ admin.register (Место проведения)
6 класс VenueAdmin (admin.ModelAdmin):
7 list_display = ('имя', 'адрес', 'телефон')
8 заказ = ('имя',)
9 search_fields = ('имя', 'адрес')
10
11
  12 @ admin.register (Событие)
13 класс EventAdmin (admin.ModelAdmin):
14 полей = (('имя', 'место встречи'), 'дата_события', 'описание', 'менеджер')
15 list_display = ('имя', 'дата_события', 'место проведения')
16 list_filter = ('дата_события', 'место проведения')
17 заказ = ('-дата_события',) 
18
19 # admin.site.register (Место проведения)
20 admin.site.register (MyClubUser)
  21 # admin.site.register (Событие)   

Новый класс EventAdmin в основном совпадает с классом VenueAdmin с двумя заметными отличиями:

  • Строка 14 .Поля Опция перечисляет все поля для отображения в форме редактирования в том порядке, в котором они должны отображаться. Если два или более поля указаны в скобках, они сгруппированы вместе в одной строке. Обратите внимание, что поля посетителей нет в списке полей. Чтобы скрыть поле в форме администратора, вы просто не включаете его в список полей. Но будьте осторожны — вы не можете скрыть обязательные поля; иначе форма не сохранится!
  • Строка 16 . Параметр list_filter — это набор полей для добавления фильтров «Фильтровать по…» на правую боковую панель списка изменений модели.

На рис. 7-9 показан результат настроек в форме редактирования, а на рис. 7-10 — итоговый список изменений.

Рисунок 7-9: Индивидуальная форма редактирования события.

Рисунок 7-10: Пользовательский список изменений событий.

Группирование информации с помощью наборов полей

В более крупных и сложных формах легче управлять формой, если поля формы расположены в группах. Это достигается с помощью опции fieldsets .Преимущество опции fieldsets заключается в том, что она предоставляет несколько дополнительных опций, которые позволяют дополнительно настраивать форму редактирования модели. Для демонстрации внесем некоторые изменения в класс EventAdmin (изменения выделены жирным шрифтом):

  # \ myclub_root \ events \ admin.py

# ...

1 @ admin.register (Событие)
2 класс EventAdmin (admin.ModelAdmin):
  3   #  fields = (('имя', 'место проведения'), 'дата_события', 'описание', 'менеджер')
4 list_display = ('имя', 'дата_события', 'место проведения')
5 list_filter = ('дата_события', 'место проведения')
6 заказ = ('-дата_события',)
  7 наборов полей = (
8 ('Требуемая информация', {
9 'description': «Эти поля необходимы для каждого события.",
10 'полей': (('название', 'место встречи'), 'дата_события')
11}),
12 ('Дополнительная информация', {
13 'классов': ('коллапс',),
14 'полей': ('описание', 'менеджер')
15}),
16)   

Рассмотрим изменения подробнее:

  • Строка 3 . Я закомментировал опцию fields для класса. Это связано с тем, что параметры отображения полей формы и макета теперь определены в параметре fieldsets .
  • Строки с 7 по 16 — это новый набор полей . Набор полей — это список из двух кортежей, каждый из которых представляет группу полей в форме редактирования. Каждый кортеж из двух элементов включает имя группы и словарь параметров полей:
    • Строка 8 . Первый набор полей называется «Требуемая информация».
    • Строка 9 . Первый вариант устанавливает описание группы.
    • Строка 10 . Это имеет тот же эффект, что и вариант полей, который мы закомментировали: имя и место проведения указаны в одной строке, а event_date добавляется для завершения группы «Требуемая информация».
    • Строка 12 . Второй набор полей называется «Дополнительная информация».
    • Строка 13 . Добавляет collapse класс в набор полей. Это применит стиль аккордеона JavaScipt, чтобы свернуть набор полей при первом отображении формы.
    • Строка 14 . Остальные два поля формы — описание и менеджер — отображаются как часть группы «Дополнительная информация».

Сохраните admin.py и перезагрузите админку, и вы увидите, что форма редактирования события выглядит как на рис. 7-11. Обратите внимание на имена обязательных и дополнительных групп, описание требуемой группы и скрытые дополнительные поля при загрузке формы. Нажмите «Показать» рядом с заголовком необязательной информации, и появятся дополнительные поля.

Рисунок 7-11: Форма редактирования события с установленными параметрами набора полей.

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

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

Другие варианты администратора, которые вы хотите проверить:

  • иерархия_даты . Предоставляет развернутую информацию для поля на основе даты.
  • пустое_значение_дисплей . Изменяет способ отображения пустых значений.
  • за исключением . Исключает поле или поля из формы
  • filter_horizontal . Добавляет горизонтальный фильтр JavaScript для полей типа «многие ко многим». Если вы хотите увидеть горизонтальный фильтр в действии, см. Разрешения и группы пользователей в следующем разделе.
  • list_editable . Делает поля списка изменений редактируемыми.
  • readonly_fields . Устанавливает перечисленные поля формы только для чтения.Очень удобно для полей с отметками времени и других полей, которые вы хотите видеть, но не редактировать.

Управление пользователями в админке

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

  • Добавление и удаление пользователей
  • Редактировать существующих пользователей
  • Сброс паролей пользователей
  • Назначить пользователю статус персонала и / или суперпользователя
  • Добавить или удалить разрешения для пользователей
  • Создание групп пользователей; и
  • Добавить пользователей в группу

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

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

Вернитесь на главную страницу администратора и щелкните Пользователи , чтобы открыть список изменений пользователя (рис. 7-12). Щелкните имя пользователя, чтобы открыть экран редактирования пользователя.

Рисунок 7-12: Выберите нового пользователя из списка изменений пользователя, чтобы отредактировать данные пользователя.

В верхней части экрана редактирования пользователя вы увидите параметры для редактирования пароля пользователя и личной информации. Прокрутите вниз до раздела Permissions и убедитесь, что «Статус персонала» отмечен, а «Статус суперпользователя» не отмечен (Рисунок 7-13).

Рисунок 7-13: Создайте обычного пользователя-администратора (не суперпользователя), убедившись, что он активен и имеет статус персонала, но не имеет статуса суперпользователя.

То, что мы здесь создали, считается обычным администратором. Обычные пользователи-администраторы (активные сотрудники, не являющиеся суперпользователями) получают административный доступ через назначенные разрешения. Каждый объект, редактируемый через интерфейс администратора (например, события и места проведения), имеет четыре разрешения: разрешение на создание, разрешение на просмотр, разрешение на редактирование и разрешение на удаление.

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

Мы сделаем это сейчас — мы создадим штатного пользователя, у которого будет разрешение на добавление и редактирование событий, но не на их удаление. Прокрутите страницу редактирования вниз до панели Права доступа пользователей и добавьте следующие разрешения с помощью горизонтального фильтра (рис. 7-14):

  событий | событие | Можно добавить событие
события | событие | Может изменить событие  

Рисунок 7-14: Добавьте разрешения пользователю, выбрав его в горизонтальном фильтре и добавив в список.Сделайте множественный выбор, удерживая клавишу CTRL (Command на Mac).

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

Рисунок 7-15: Настройки разрешений нового пользователя ограничивают их административный доступ к приложению событий. Если вы откроете мероприятие, вы также заметите, что кнопка удаления скрыта, поскольку у них нет разрешения на удаление.

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

Давайте создадим группу «Администратор мероприятия». Сначала вам нужно будет выйти из системы как штатный пользователь и снова войти в систему как суперпользователь.

Создание группы аналогично созданию пользователя: перейдите на страницу указателя администратора, нажмите зеленую кнопку Добавить справа от списка Группы и назовите новую группу «Администратор событий».Затем добавьте разрешения из горизонтального фильтра и сохраните новую группу (рис. 7-16).

Рисунок 7-16: Создайте группу пользователей и добавьте событие, добавьте и измените права доступа к группе с помощью горизонтального фильтра. Сделайте множественный выбор, удерживая клавишу CTRL (клавиша Command на Mac).

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

Рисунок 7-17: При добавлении пользователя в группу пользователю назначаются все разрешения группы.

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

Смена пароля

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

Так как же сбросить пароль, если пользователь его забыл?

Конфигурация администратора по умолчанию позволяет только администратору или лицу, имеющему разрешение на редактирование пользователей, сбрасывать пароль, используя ссылку формы сброса пароля в форме редактирования пользователя (рис. 7-18).

Рисунок 7-18: Стандартный способ сброса пароля пользователя.

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

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

К счастью, Django имеет встроенную функцию сброса пароля; нам просто нужно включить его.Внесите следующие изменения в ваш сайт urls.py файл (изменения выделены жирным шрифтом):

  # \ myclub_root \ myclub_site \ urls.py

1 от администратора импорта django.contrib
2 из django.urls import include, path
  3 из django.contrib.auth импортировать просмотры как auth_views 
4
5 шаблонов URL = [
6 путь ('admin /', admin.site.urls),
  7 путь (
8 'admin / password_reset /',
9 auth_views.PasswordResetView.as_view (),
10 name = 'admin_password_reset',
11),
12 путь (
13 'admin / password_reset / done /',
14 auth_views.PasswordResetDoneView.as_view (),
15 name = 'password_reset_done',
16),
17 путь (
18 'reset /  /  /',
19 auth_views.PasswordResetConfirmView.as_view (),
20 name = 'password_reset_confirm',
21),
22 путь (
23 'сбросить / сделать /',
24 auth_views.PasswordResetCompleteView.as_view (),
25 name = 'password_reset_complete',
26), 
27 путь ('', include ('events.urls')),
28]  

В строке 3 мы импортируем представления аутентификации из django.contrib.auth и добавьте четыре новых оператора пути к URL-адресам нашего сайта ( строки 7, 12, 17 и 22, ). Как только Django обнаружит URL-адрес с именем admin_password_reset , он автоматически добавит ссылку для сброса пароля в форму входа в систему (рис. 7-19).

Рисунок 7-19: Добавление представлений аутентификации к URL-адресам вашего сайта включает функцию сброса пароля формы входа.

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

Краткое содержание главы

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

В следующей главе мы изучим основы форм и управления формами в Django.

.

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

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

В этих случаях администратор Django позволяет вам писать и регистрировать «действия» —
функции, которые вызываются со списком объектов, выбранных в списке изменений
страница.

Если вы посмотрите список изменений в админке, вы увидите эту функцию в
действие; Django поставляется с действием «удалить выбранные объекты», доступным для всех.
модели.Например, вот пользовательский модуль из встроенного в Django
django.contrib.auth приложение:

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

Действие «удалить выбранные объекты» использует QuerySet.delete () из соображений эффективности, что
имеет важное предостережение: метод delete () вашей модели не будет
называется.

Если вы хотите отменить это поведение, вы можете отменить
ModelAdmin.delete_queryset () или напишите настраиваемое действие, которое
удаление желаемым способом — например, позвонив
Модель.delete () для каждого из выбранных элементов.

Дополнительные сведения о массовом удалении см. В документации по объекту
удаление.

Читайте дальше, чтобы узнать, как добавить свои собственные действия в этот список.

Написание действий¶

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

Распространенным вариантом использования действий администратора является массовое обновление модели. Представьте себе
новостное приложение с Article модель:

 из django.модели импорта БД

STATUS_CHOICES = [
    ('d', 'Черновик'),
    ('p', 'Опубликовано'),
    ('w', 'Снято'),
]

класс Article (models.Model):
    title = models.CharField (max_length = 100)
    body = models.TextField ()
    status = models.CharField (max_length = 1, choices = STATUS_CHOICES)

    def __str __ (сам):
        вернуть self.title
 

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

Запись функций действий¶

Во-первых, нам нужно написать функцию, которая будет вызываться, когда действие
срабатывает от админа. Функции действий — это обычные функции, которые принимают
три аргумента:

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

 def make_published (администратор модели, запрос, набор запросов):
    queryset.обновление (статус = 'p')
 

Примечание

Для максимальной производительности мы используем метод обновления набора запросов. Другие типы действий могут потребоваться
с каждым объектом индивидуально; в этих случаях мы перебираем
набор запросов:

 для obj в наборе запросов:
    do_something_with (объект)
 

Вот и все, что нужно для написания действия! Однако мы возьмем один
более необязательный, но полезный шаг и дайте действию «красивый» заголовок в админке.
По умолчанию это действие отображается в списке действий как «Опубликовать» —
имя функции с заменой подчеркивания пробелом.Это нормально, но мы
может дать лучшее, более понятное для человека имя, задав
make_published function a short_description attribute:

 def make_published (администратор модели, запрос, набор запросов):
    queryset.update (статус = 'p')
make_published.short_description = "Пометить выбранные истории как опубликованные"
 

Примечание

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

Добавление действий в ModelAdmin

Затем нам нужно сообщить нашему ModelAdmin о действии. Это работает
как и любой другой вариант конфигурации. Итак, полный admin.py с
действие и его регистрация будут выглядеть так:

 от администратора импорта django.contrib
из myapp.models импорт статьи

def make_published (modeladmin, запрос, qu 

.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *