g:如何将按钮“添加子页面”添加到自定义列表视图(IndexView)的操作列表中?

时间:2019-05-29 11:39:40

标签: python wagtail

我正在按浏览器视图和自定义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 个答案:

答案 0 :(得分:2)

答案

ModelAdmin没有使用相同的系统来构建其视图中列出的按钮。

相反,它具有“帮助程序类”的概念,它们用于生成URL和权限检查,而这些检查又用于生成出现在各种视图中的按钮。

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

您将需要在ModelAdmin实例上设置自定义button_helper_class,以生成您想要的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

  • 通过添加add_child_button覆盖get_buttons_for_obj
  • 使用现有的权限帮助器类进行一些检查,这将避免需要重写容易出错的用户和身份验证逻辑
  • 调用方法(我们将添加)以生成按钮内容add_child_button
  • 添加方法add_child_button-必须返回带有url,标签,类名和标题的对象。尝试将现有的约定保留在可以在全局范围内附加/删除类名的位置
  • 最困难的是url生成,我们将利用URL帮助器的现有结构,但是您可以直接生成此URL。

CustomPageAdminURLHelper

  • 重写方法get_action_url并处理我们关心的'action'在'add-child'位置的特殊情况
  • 此方法必须简单地返回一个字符串(将是一个相对URL),最好使用现有的Django URL反向系统。
  • 添加子页面的网址名称为'wagtailadmin_pages:add_subpage'
  • 最后使用传入的args / kwargs调用Django反向实用程序,您将获得漂亮的url作为回报。

CustomAdmin

  • 最后一步是在CustomAdmin实例上设置这些自定义url和按钮帮助器类。
  • 这仅需要将button_helper_classurl_helper_class设置为其各自的帮助程序替代。

其他注意事项和注意事项

  • 已经很好地阅读了ModelAdmin文档,它们的布局非常好,对您有很大帮助。 http://docs.wagtail.io/en/v2.5.1/reference/contrib/modeladmin/index.html
  • 缺少某些方面,但是代码库中的helpers文件夹很容易阅读,应该可以帮助您确定正在定制的代码流程。
  • 这是假设您只想在Page模型上使用这些自定义帮助程序,ModelAdmin处理页面和其他对象的方式之间存在细微差别,您可以进行额外的检查,但这取决于您。
  • 如果您不关心类名并遵循现有的modeladmin约定,则可以简化一些样板代码。
  • 这假定您的主键是URL安全的,您将在modeladmin代码中看到很多额外的utils用法使所有URL安全。
  • 创建子页面后,用户将返回到父页面的NON-model admin列表。更改此设置可能需要付出很多额外的工作,但是上面的代码应该可以为您提供所需的内容。