我有一个PrintDetailView,如果打印的to_publish属性设置为True,我希望仅可以访问打印的所有者,或者任何人。
为了做到这一点,我试图使用一个permission_required()
方法装饰器,它接受来自Print模型的可调用:
class PrintDetailView(DetailView):
template_name = 'prints/detail.html'
queryset = Print.objects.all()
@method_decorator(permission_required('prints.user_is_owner_or_public'))
def dispatch(self, request, *args, **kwargs):
return super(PrintDetailView, self).dispatch(request, *args, **kwargs)
以下是Print模型中的user_is_owner_or_public()
方法:
def user_is_owner_or_public(self, user):
"""Checks whether the print is a public print, or
whether the current user is the owner
"""
if self.user is user or self.to_publish:
return True
现在,当我在其to_publish属性设置为True的打印详细信息页面上测试时,我仍然看到登录屏幕,所以我知道正在调用permission_required()函数;但是,它显然没有调用user_is_owner_or_public()方法。
任何人都可以让我了解如何使这项工作成功吗?
TIA,Andy
答案 0 :(得分:2)
这根本不是permission_required
所做的 - permission_required
是Django权限系统的一部分,并且会导致Django检查权限数据库表以查找已登录用户的适当命名的权限对象(直接授予或通过集团授予)。你要做的是在dispatch
周围的装饰器范围之外 - 如果没有别的,你的print实例直到后面的视图才被加载,所以它将无法检查{{1} }。
我要处理的最简单方法是在视图上定义to_publish
方法:
get_queryset
那将为用户无法看到的任何打印件抛出404。如果您宁愿重定向到登录页面,则必须覆盖from django.db.models import Q
class PrintDetailView(DetailView):
template_name = 'prints/detail.html'
def get_queryset(self):
return Print.objects.filter(Q(user=self.request.user) | Q(to_publish=True))
方法:
get
作为旁注,如果可以仅从用户对象确定调度方法,则可以使用user_passes_test
装饰器添加对调度方法的限制。这在这里没有用,但是如果你的测试只需要用户而不是打印实例那么。