Wa页面中的字段权限

时间:2018-07-23 14:53:35

标签: django permissions wagtail

如何将权限应用于Wagtail页面的各个字段? 假设我们有一个这样的页面:

class HomePage(Page):
   body = RichTextField(blank=True)

   content_panels = Page.content_panels + [
       FieldPanel('body', classname="full"),
   ]

每个人都可以编辑标题-但只有具有一定权限的用户才可以更改正文。

1 个答案:

答案 0 :(得分:1)

我意识到现在这是一个非常老的问题,但是以防万一将来有人遇到它,这就是我的代码店在Wagtail 2.3中是如何做到的。在更高版本中它可能会或可能不会起作用。

将以下内容添加到您编写的Page子类中:

panels = [
    ...
    MultiFieldPanel(
        [
            FieldPanel('display_locations', widget=forms.CheckboxSelectMultiple),
            StreamFieldPanel('assets'),
        ],
        heading='Admin-only Fields',
        # NOTE: The 'admin-only' class is how EventPage.get_edit_handler() identifies this MultiFieldPanel.
        classname='collapsible admin-only'
    ),
    ...
]

class Meta:
    verbose_name = 'Event'
    verbose_name_plural = 'Events'
    ordering = ['start_date', 'title']
    permissions = (
        ('can_access_admin_fields', 'Can access Event Admin fields'),
    )

@classmethod
def get_edit_handler(cls):
    """
    We override this method (which is added to the Page class in wagtail.admin.edit_handlers) in order to enforce
    our custom field-level permissions.
    """
    # Do the same thing that wagtail.admin.edit_handlers.get_edit_handler() would do...
    bound_handler = cls.edit_handler.bind_to_model(cls)
    # ... then enforce admin-only field permissions on the result.
    current_request = get_current_request()
    # This method gets called during certain manage.py commands, so we need to be able to gracefully fail if there
    # is no current request. Thus, if there is no current request, the admin-only fields are removed.
    if current_request is None or not current_request.user.has_perm('calendar_app.can_access_admin_fields'):
        # We know for sure that bound_handler.children[0].children is the list of Panels in the Content tab.
        # We must search through that list to find the admin-only MultiFieldPanel, and remove it.
        # The [:] gets us a copy of the list, so altering the original doesn't change what we're looping over.
        for child in bound_handler.children[0].children[:]:
            if 'admin-only' in child.classname:
                bound_handler.children[0].children.remove(child)
                break
    return bound_handler

这显然很时髦且脆弱。但这是我能找到的唯一解决方案。