如何在wagtail管理员中过滤页面列表,以便编辑者只能看到他们创建的页面?

时间:2019-04-25 07:31:30

标签: wagtail

我正在创建一个wagtail网站,用户可以在其中注册,登录wagtail管理员并编写文章页面进行发布。在wagtail管理员中是否有钩子或可能的方法来拦截和过滤数据,以便用户仅看到他们自己创建的文章页面?

到目前为止,我已经使用django-allauth设置了用户注册,并且用户能够成功登录。注册后,将触发user_signed_up接收器,并将用户分配给“作者”角色。在管理员中,作者仅具有添加文章的权限。 Articles是具有文章索引页面和文章页面(基本上是博客和博客索引页面)的应用。登录后,他们唯一看到的就是左侧的“页面”选项卡,单击后将其带到“文章”列表。他们可以在此处添加“文章”页面并查看到目前为止创建的文章。

这也是我的问题所在。从文章列表页面,用户可以查看网站上所有用户创建的所有文章。他们只能编辑自己的内容,这很棒,但是最终会有来自其他用户的数百篇文章。有没有办法在显示“文章”数据之前对其进行拦截并由当前用户对其进行过滤?

拦截这些数据的结果将使登录到wagtail管理员的每个用户仅了解他们创建的文章页面。

非常感谢,这是我第一次使用Wagtail,到目前为止我很喜欢。

3 个答案:

答案 0 :(得分:2)

对于这个问题,我发现了两种不同的解决方案。

  1. 实施 ModelAdmin ,以创建模型的自定义页面列表视图。这使您可以创建一个全新的管理菜单项和相应的列表视图。这种方法涉及更多,但提供了更多的控制权。
  2. 实施 construct_explorer_page_queryset 管理钩子,以按组过滤文件结果。此方法易于实现,可让您使用Wagtails现有的页面浏览器。

我将介绍如何处理上述每种方法。两者都有效,这取决于我是否愿意使用内置在页面浏览器中的Wagtails。

方法1:ModelAdmin

在Wagtail文档here中找到了ModelAdmin.get_queryset()和其他有用方法的使用。

根据Wagtail文档中的this page,我将ModelAdmin添加到INSTALLED_APPS:

# base.py settings

INSTALLED_APPS = [
    ...
    'wagtail.contrib.modeladmin',
]

然后,我在“文章”应用中创建了一个名为 wagtail_hooks.py 的文件。在该文件中,我添加了用于在管理员中创建文章列表页面的代码:

# wagtail_hooks.py

from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
from .models import Article


class ArticleAdmin(ModelAdmin):
    model = Article
    menu_label = 'Articles'
    menu_icon = 'doc-full-inverse'
    menu_order = 000
    add_to_settings_menu = False
    exclude_from_explorer = False
    list_display = ('title', 'owner')
    search_fields = ('title', 'owner')

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        #only show articles from the current user
        return qs.filter(owner=request.user)


modeladmin_register(ArticleAdmin)

这里的关键是实现 ModelAdmin.get_queryset(),该过滤器使我可以过滤文章所有者。

您可能还想删除Page Explorer菜单项,因为它有点多余。我也建议您同时实施下面的方法2。即使删除了“页面浏览器”菜单项,用户也可以通过直接在浏览器中输入URL来到达那里。如果可以,实施方法2将确保看不到其他用户创作的内容。

方法2:construct_explorer_page_queryset @hooks

Wagtail文档中的钩子信息-construct_explorer_page_queryset 还引用了此Google网上论坛文章-https://groups.google.com/forum/#!topic/wagtail/10tcq8PB8io

在我上面创建的同一wagtail_hooks.py文件中,我添加了以下代码:

@hooks.register('construct_explorer_page_queryset')
def show_authors_only_their_articles(parent_page, pages, request):
    user_group = request.user.groups.filter(name='Author').exists()
    if user_group:
        pages = pages.filter(owner=request.user)

    return pages

第二种方法就是这样。

答案 1 :(得分:0)

@Pahikua请注意,方法2只是从列表中隐藏页面,并不保护页面不被编辑和删除。在您的情况下,这意味着Author1可以打开诸如pages / id / edit /之类的url,其中id是Author2拥有的页面的id,然后对其进行编辑。

为避免这种情况,您必须添加before_edit_page和before_delete_page挂钩。像这样:

@hooks.register('before_edit_page')
def before_edit_page(request, page):
    user_group = request.user.groups.filter(name='Author').exists()
    if user_group and page.owner != request.user:
        raise PermissionDenied

答案 2 :(得分:0)

感谢@Pahikua和@Igor Margitich。我能够将他们的答案组合成精美的布置,这正是我想要的。

  1. 按照@Pahikua在其方法1 中的建议,为Article(或您希望作者可以使用的任何其他模型)创建管理菜单项。这将为作者提供快速访问其内容的快捷方式(甚至从此处添加内容)。

  2. 我没有删除“页面资源管理器”管理菜单项,因为我确实希望我的作者能够导航其他作者的页面,以便找到添加页面的正确位置。
    否则,仅将新创建的“文章”菜单项中的页面添加到正确的位置(在步骤1中)非常麻烦。

  3. 按照@Igor Margitich的建议添加这些“之前”钩子。我也使用了 before_create_page 钩子,因为我希望作者只能添加一种类型的页面。

    from wagtail.core import hooks
    from django.core.exceptions import PermissionDenied
    from django.views.defaults import permission_denied
    from .models import Article
    
    @hooks.register('before_edit_page')
    def before_edit_page(request, page):
        # user_group = request.user.groups.filter(name='Author').exists() # I did not use user_group
        if not (request.user.is_superuser or page.owner == request.user):
            return permission_denied(request, PermissionDenied("You do not have permission to edit this page."))
    
    @hooks.register('before_delete_page')
    def before_delete_page(request, page):
        if not (request.user.is_superuser or page.owner == request.user):
            return permission_denied(request,PermissionDenied("You do not have permission to delete this page."))
    
    @hooks.register('before_create_page')
    def before_create_page(request, parent_page, page_class):
        if not (request.user.is_superuser or page_class == Article):
            return permission_denied(request, PermissionDenied("You do not have permission to add this page."))