【问题标题】:Wagtail: How to add button "add subpage" to the action list of a custom listing view (IndexView)?Wagtail:如何将“添加子页面”按钮添加到自定义列表视图(IndexView)的操作列表中?
【发布时间】:2019-05-29 11:39:40
【问题描述】:

我正在为每个用户构建管理菜单,没有资源管理器视图和自定义 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)

但是生成的列表视图的操作列表(即上下文菜单)缺少资源管理器视图提供的一些功能。

我特别需要“添加子页”。我知道钩子register_page_listing_buttons。但是您只能为资源管理器视图操作列表注册按钮。

是否可以将“添加子页面”按钮添加到自定义列表视图的操作列表中?


资源管理器列表视图:

自定义 ModelAdmin 列表视图:

【问题讨论】:

    标签: python wagtail


    【解决方案1】:

    回答

    ModelAdmin 不使用相同的系统来构建他们视图中列出的按钮。

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

    https://docs.wagtail.io/en/stable/reference/contrib/modeladmin/primer.html?highlight=primer

    您需要在 ModelAdmin 实例上设置自定义 button_helper_class,该类将在 IndexView 中生成您想要的自定义按钮。为此,您需要使用自定义 get_buttons_for_obj 方法导入和扩展 PageButtonHelper 类,该方法将返回按钮列表。

    代码示例

    # 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 并处理我们关心的特定情况,其中“动作”是'add-child'
    • 这个方法必须简单地返回一个字符串(这将是一个相对的url),最好使用现有的Django URL反转系统。
    • 添加子页面的url名称为'wagtailadmin_pages:add_subpage'
    • 最后用传入的 args/kwargs 调用 Django 反向工具,你会得到一个漂亮的 url 作为回报。

    CustomAdmin

    • 最后一步是在您的 CustomAdmin 实例上设置这些自定义 url 和按钮帮助程序类。
    • 这只需要将 button_helper_classurl_helper_class 设置为各自的帮助程序覆盖。

    额外说明和注意事项

    • 仔细阅读 ModelAdmin 文档,它们的布局非常好,帮助很大。 https://docs.wagtail.io/en/stable/reference/contrib/modeladmin/index.html?highlight=modeladmin%20helpers#
    • 缺少某些方面,但代码库中的 helpers 文件夹非常易于阅读,应该可以帮助您确定要自定义的代码流。
    • 这是假设您只想在页面模型上使用这些自定义帮助程序,ModelAdmin 处理页面和其他对象的方式之间存在细微差别,您可以进行额外检查,但这取决于您。
    • 如果您不关心类名并遵循现有的模型管理约定,您可以缩短一些样板代码,这取决于您。
    • 这假设您的主键是 URL 安全的,您会在 modeladmin 代码中看到有很多额外的 utils 使用来确保所有 url 安全。
    • 创建子页面后,用户将返回到父页面的非模型管理列表。更改此设置可能需要相当多的额外工作,但上面的代码应该可以满足您的需求。

    【讨论】:

    • 很抱歉这么晚才接受这个答案。我确定我已经这样做了。
    猜你喜欢
    • 1970-01-01
    • 2020-02-15
    • 2015-12-23
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多