我正在创建一个wagtail网站,用户可以在其中注册,登录wagtail管理员并编写文章页面进行发布。在wagtail管理员中是否有钩子或可能的方法来拦截和过滤数据,以便用户仅看到他们自己创建的文章页面?
到目前为止,我已经使用django-allauth设置了用户注册,并且用户能够成功登录。注册后,将触发user_signed_up接收器,并将用户分配给“作者”角色。在管理员中,作者仅具有添加文章的权限。 Articles是具有文章索引页面和文章页面(基本上是博客和博客索引页面)的应用。登录后,他们唯一看到的就是左侧的“页面”选项卡,单击后将其带到“文章”列表。他们可以在此处添加“文章”页面并查看到目前为止创建的文章。
这也是我的问题所在。从文章列表页面,用户可以查看网站上所有用户创建的所有文章。他们只能编辑自己的内容,这很棒,但是最终会有来自其他用户的数百篇文章。有没有办法在显示“文章”数据之前对其进行拦截并由当前用户对其进行过滤?
拦截这些数据的结果将使登录到wagtail管理员的每个用户仅了解他们创建的文章页面。
非常感谢,这是我第一次使用Wagtail,到目前为止我很喜欢。
答案 0 :(得分:2)
对于这个问题,我发现了两种不同的解决方案。
我将介绍如何处理上述每种方法。两者都有效,这取决于我是否愿意使用内置在页面浏览器中的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。我能够将他们的答案组合成精美的布置,这正是我想要的。
按照@Pahikua在其方法1 中的建议,为Article(或您希望作者可以使用的任何其他模型)创建管理菜单项。这将为作者提供快速访问其内容的快捷方式(甚至从此处添加内容)。
我没有删除“页面资源管理器”管理菜单项,因为我确实希望我的作者能够导航其他作者的页面,以便找到添加页面的正确位置。
否则,仅将新创建的“文章”菜单项中的页面添加到正确的位置(在步骤1中)非常麻烦。
按照@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."))