Трясогузка: Как добавить кнопку «Добавить подстраницу» в список действий пользовательского представления списка (IndexView)? - PullRequest
2 голосов
/ 29 мая 2019

Я создаю меню администратора для каждого пользователя без представления проводника и пользовательских ModelAdmin экземпляров.

@hooks.register('construct_main_menu')
def hide_page_explorer_menu_item(request, menu_items):
    if request.user.username == 'user1':
        menu_items[:] = [item for item in menu_items if item.name not in [
            'explorer',
            ]
        ]

class CustomAdmin(ModelAdmin):
    model = MyPage
    menu_label = 'custom ModelAdmin'

    list_display = ('title', "live")
    list_filter = ("date")
    search_fields = ("title")

modeladmin_register(CustomAdmin)

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

Мне специально нужно добавить ADD CHILDPAGE.Я знаю о крючке register_page_listing_buttons.Но вы можете зарегистрировать кнопки только для списка действий вида проводника.

Можно ли добавить кнопку «добавить подстраницу» в список действий пользовательского вида списка?


Вид списка проводника:

Explorer View:

Пользовательский вид списка ModelAdmin:

enter image description here

1 Ответ

2 голосов
/ 09 июня 2019

Ответ

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

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

http://docs.wagtail.io/en/v2.5.1/reference/contrib/modeladmin/primer.html#overriding-helper-classes

Вам нужно будет настроить пользовательский button_helper_class для экземпляра ModelAdmin, который будет генерировать пользовательские кнопки, которые вы хотите использовать в своем IndexView. Для этого вам нужно будет импортировать и расширять класс PageButtonHelper с помощью пользовательского метода get_buttons_for_obj, который будет возвращать список кнопок.

Пример кода

# wagtail_hooks.py

from django.urls import reverse
from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
from wagtail.contrib.modeladmin.helpers import (PageAdminURLHelper, PageButtonHelper)
# MyPage model import not included but will be needed

class CustomPageAdminURLHelper(PageAdminURLHelper):

    def get_action_url(self, action, *args, **kwargs):
        if action == 'add-child':
            # note: add_subpage is used as the internal name for adding child pages
            url_name = 'wagtailadmin_pages:add_subpage'
            target_url = reverse(url_name, args=args, kwargs=kwargs)
            return target_url

        # for every other case - just call the parent method
        return super().get_action_url(action, *args, **kwargs)


class CustomPageButtonHelperClass(PageButtonHelper):

    add_child_button_classnames = ['add-child'] # can be anything - just setting this to match convention

    # add a new button generator that mimics the 'copy_button' from existing code
    def add_child_button(self, pk, classnames_add=[], classnames_exclude=[]):
        classnames = self.add_child_button_classnames + classnames_add
        final_classnames = self.finalise_classname(classnames, classnames_exclude)

        return {
            # if we wanted - we can skip the creation of CustomPageAdminURLHelper & generate the URL here
            # but this may work against reusability later
            'url': self.url_helper.get_action_url('add-child', pk), # may need to wrap pk in quote if it could contain non-url-safe chars
            'label': 'Add Child',
            'classname': final_classnames,
            'title': 'Add Child uner this %s' % self.verbose_name
        }

    # override the PageButtonHelper method to 'add' custom buttons
    def get_buttons_for_obj(self, obj, exclude=[], classnames_add=[], classnames_exclude=[]):
        # call the parent class method to get the default set of buttons
        buttons = super().get_buttons_for_obj(obj, exclude, classnames_add, classnames_exclude)

        # set up some variables to do user checks and also get the primary key (id)
        permission_helper = self.permission_helper
        user = self.request.user
        pk = getattr(obj, self.opts.pk.attname)

        # many existing permission helpers are already available - see wagtail/contrib/modeladmin/helpers/permission.py
        if ('add-child' not in exclude and permission_helper.user_can_create(user)):
            # above we follow the convention set up where buttons can be included/excluded easier
            # we also do a permissions check
            # finally we build the button and add it to the end of the buttons list
            add_child_button = self.add_child_button(pk, classnames_add, classnames_exclude)
            buttons.append(add_child_button)

        return buttons

class CustomAdmin(ModelAdmin):
    model = MyPage
    menu_label = 'custom ModelAdmin'
    button_helper_class = CustomPageButtonHelperClass # added to enable custom button generation
    url_helper_class = CustomPageAdminURLHelper # added to enable custom url generation

    list_display = ('title', "live")
    list_filter = ("date")
    search_fields = ("title")

modeladmin_register(CustomAdmin)

Пояснение кода

CustomPageButtonHelperClass

  • Переопределите get_buttons_for_obj, добавив кнопку add_child_.
  • Используйте существующий класс помощника по разрешениям для выполнения некоторых проверок, это избавит от необходимости переписывать логику user & auth, которая может быть подвержена ошибкам
  • Вызвать метод (который мы добавим) для генерации содержимого кнопки, add_child_button
  • Добавить метод add_child_button - должен возвращать объект с URL, меткой, именем класса и заголовком. Попытайтесь сохранить существующие соглашения в месте, где имена классов могут быть добавлены / удалены глобально
  • Самым сложным является генерирование URL, мы будем использовать существующую структуру помощников URL, но вы можете просто сгенерировать этот URL в строке.

CustomPageAdminURLHelper

  • Переопределите метод get_action_url и обработайте конкретный случай, о котором мы заботимся, где «действие» равно 'add-child'
  • Этот метод должен просто возвращать строку (которая будет относительным URL), лучше всего использовать существующую систему реверсирования URL Django.
  • URL-адрес для добавления дочерней страницы: 'wagtailadmin_pages:add_subpage'
  • Наконец, вызовите утилиту реверса Django с переданными в args / kwargs, и вы получите красивый URL взамен.

CustomAdmin

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

Дополнительные замечания и предостережения

  • Внимательно прочитайте документы ModelAdmin, они очень хорошо изложены и очень помогают. http://docs.wagtail.io/en/v2.5.1/reference/contrib/modeladmin/index.html
  • Некоторые аспекты отсутствуют, но папка helpers в кодовой базе довольно легко читается и должна помочь вам разобраться с потоком кода, который вы настраиваете.
  • Предполагается, что вы хотите использовать эти пользовательские помощники только на моделях страниц. Существуют тонкие различия в том, как ModelAdmin обрабатывает страницы и другие объекты, вы можете добавлять дополнительные проверки, но это зависит от вас.
  • Вы могли бы немного сократить шаблонный код, если вас не интересуют имена классов и следование существующим соглашениям modeladmin, это ваше дело.
  • Это предполагает, что ваши первичные ключи безопасны для URL, вы увидите, что в коде modeladmin есть много дополнительных утилит, чтобы сделать все URL безопасными.
  • После создания дочерней страницы пользователь вернется к списку администраторов НЕ-модели родительской страницы. Изменение этого может потребовать немало дополнительной работы, но приведенный выше код должен дать вам то, что вы хотите.
...