Wagtail 页面中的字段权限

Posted

技术标签:

【中文标题】Wagtail 页面中的字段权限【英文标题】:Permission for field in Wagtail Page 【发布时间】:2018-12-31 01:55:12 【问题描述】:

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

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

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

应该允许每个人编辑标题 - 但只有具有特定权限的用户才能更改正文。

【问题讨论】:

【参考方案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

显然,这是非常时髦和脆弱的。但这是我能找到的唯一解决方案。

【讨论】:

出于好奇,get_current_request() 函数是从哪里来的? @user2415992 我使用 django-crequest 库的一个分支。它提供了一个中间件,用于存储当前请求的线程本地值。 get_current_request() 函数是我编写的一个实用程序,它可以更直接地从 crequest 的中间件中检索当前请求。

以上是关于Wagtail 页面中的字段权限的主要内容,如果未能解决你的问题,请参考以下文章

Wagtail:序列化页面模型

在 Wagtail 页面上禁用 CSRF 验证

Wagtail - 在页面上呈现带有相关片段和标签的数据时遇到问题

如何正确重命名 wagtail 页面模型

如何在主页上显示某些Wagtail页面?

Wagtail "Template-loader postmortem" 来源虽然存在