Пользовательские поля и действия в админ-панели

Курс по Django: https://stepik.org/a/183363

Архив проекта: 39_sitewomen.zip

Продолжаем настраивать и изучать работу с админ-панелью. Это занятие начнем с добавления собственного (пользовательского) поля в список статей модели Women. То есть, мы сформируем (отобразим) новое поле, которого нет в БД. Для этого перейдем в файл women/admin.py и в классе WomenAdmin пропишем метод с произвольным названием. Пусть он называется brief_info (краткая информация). Сам метод будет следующим:

class WomenAdmin(admin.ModelAdmin):
    ...
    def brief_info(self, women: Women):
        return f"Описание {len(women.content)} символов."

Он принимает дополнительный параметр, который я назвал women, и ссылается на объект класса модели Women. То есть, при отображении нового столбца для каждой записи, в этот метод Django автоматически будет передавать объект класса Women. Для удобства я его аннотировал. А содержимое столбца – это возвращаемые методом данные в виде строки. То есть, в нашем примере – это строка с числом символов в статье.

После объявления метода, мы можем его указывать в списке list_display. Для удобства я уберу из него поле ‘id’ и добавлю поле по имени метода brief_info следующим образом (также поле id следует убрать из списка list_display_links):

class WomenAdmin(admin.ModelAdmin):
    list_display = ('title', 'time_create', 'is_published', 'cat', 'brief_info')
    list_display_links = ('title', )
    list_editable = ('is_published', )
    ordering = ['-time_create', 'title']
    list_per_page = 5
 
    def brief_info(self, women: Women):
        return f"Описание {len(women.content)} символов."

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

    @admin.display(description="Краткое описание")
    def brief_info(self, women: Women):
        return f"Описание {len(women.content)} символов."

Параметр description этого декоратора, как раз и определяет название столбца в админ-панели. Обновим ее и увидим указанный заголовок:

Однако сейчас новая колонка не поддерживает сортировку. Дело в том, что Django просто не знает по какому критерию ее сортировать. При необходимости это тоже можно указать в декораторе admin.display с помощью дополнительного параметра ordering:

    @admin.display(description="Краткое описание", ordering='content')
    def brief_info(self, women: Women):
        return f"Описание {len(women.content)} символов."

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

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

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

Создание пользовательских действий

Во второй части занятия мы с вами научимся добавлять свои действия в админ-панель. На самом верху списка расположен combobox с одним действием «Удалить выбранные записи». Давайте сюда добавим еще одно действие, которое будет устанавливать статус «Опубликовано» всем выбранным статьям. Для этого в класс WomenAdmin добавим еще один метод, допустим, с именем set_published:

    def set_published(self, request, queryset):
        queryset.update(is_published=Women.Status.PUBLISHED)

Он принимает два дополнительных обязательных параметра: request – объект запроса; queryset – объект QuerySet с выбранными записями. Затем, используя набор записей, мы для них вызываем метод update() и изменяем поле is_published на значение PUBLISHED.

Чтобы этот метод был использован в качестве действия в админ-панели, его нужно указать в списке actions класса WomenAdmin:

actions = ['set_published']

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

    @admin.action(description="Опубликовать выбранные записи")
    def set_published(self, request, queryset):
        queryset.update(is_published=Women.Status.PUBLISHED)

Обновляем страницу и видим это название в действиях админ-панели.

Давайте еще немного улучшим работу нашего действия, а именно, пусть дополнительно выводится сообщение о том, сколько записей было изменено. Для этого воспользуемся специальным методом message_user(), доступный для админ-панели, следующим образом:

    @admin.action(description="Опубликовать выбранные записи")
    def set_published(self, request, queryset):
        count = queryset.update(is_published=Women.Status.PUBLISHED)
        self.message_user(request, f"Изменено {count} записи(ей).")

Отметим несколько записей для изменения и видим появление нашего сообщения.

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

    @admin.action(description="Снять с публикации выбранные записи")
    def set_draft(self, request, queryset):
        count = queryset.update(is_published=Women.Status.DRAFT)
        self.message_user(request, f"{count} записи(ей) сняты с публикации!", messages.WARNING)

Смотрите, мы здесь в методе message_user() дополнительно указали флаг messages.WARNING для отображения сообщения как предупреждения, что публикации были сняты. После выбора записей и выполнения команды снятия с публикации, увидим ожидаемый результат.

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

Курс по Django: https://stepik.org/a/183363

Видео по теме