0

我有一个 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)

这是user_is_owner_or_public()Print 模型中的方法:

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,安迪

4

1 回答 1

2

这根本不是什么permission_required-permission_required是 Django 权限系统的一部分,它将导致 Django 检查权限数据库表,以查找登录用户的适当命名的权限对象(直接授予或通过组授予)。您正在尝试做的事情超出了周围装饰器的范围dispatch- 如果没有别的,您的打印实例直到稍后在视图中才会加载,因此它将无法检查to_publish.

我处理这个问题的最简单方法是get_queryset在视图上定义方法:

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))

对于用户不应该看到的任何打印,这将引发 404。如果您希望重定向到登录页面,则必须重写该get方法:

from django.conf import settings
from django.shortcuts import redirect

class PrintDetailView(DetailView):
    template_name = 'prints/detail.html'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        if not(self.object.to_publish or self.object.user == request.user):
            return redirect(settings.LOGIN_URL) # or a login viewname
        else:
            context = self.get_context_data(object=self.object)
            return self.render_to_response(context)

附带说明一下,user_passes_test如果可以仅从用户对象确定它们,则可以使用装饰器对调度方法添加限制。这在这里无济于事,但如果您的测试只需要用户而不需要打印实例,它会。

于 2013-09-04T22:34:37.667 回答