Django:使用基于类的视图基于对象的属性进行身份验证

时间:2013-03-03 01:54:44

标签: django django-authentication django-class-based-views

假设我的应用就像一个论坛,但每个帖子都有一群人可以看到它。

SecretPost(Model):
    can_see = myapp.main.models.GroupOfUsers()

我想写一个限制用户访问这些帖子的视图,我更喜欢使用装饰器,因为这就是我在其他地方处理访问控制的方式。

SecretPostView(DetailView):
    """Can only be seen by members of its group"""

    @method_decorator(part_of_its_group)
    def dispatch(self, request, *args, **kwargs):
        return super(SecretPostView, self).dispatch(request, *args, **kwargs)

但是当调用dispatch()时,我对该对象一无所知。在检索到对象后,是否存在限制用户访问的良好/惯用方法?

1 个答案:

答案 0 :(得分:2)

您可以访问方法装饰器中的self,这样就可以访问当前调用self.get_object()的对象。

无论如何,如果你只是在通用视图上使用这种行为,你可能最好创建一个实现dispatch方法的mixin(或者可能是get_object方法)并进行检查在那里,例如(使用一些想象力,因为idk如何定义你的组,也许你正在使用django.contrib.auth组):

class GroupRestrictionMixin(object):
    group_field = 'group'

    def dispatch(request, *args, **kwargs):
        self.request = request
        self.args = args
        self.kwargs = kwargs

        obj_group = getattr(self.get_object(), self.group_field)
        user_groups = request.user.groups

        if obj_group not in user_groups:
            raise PermissionDenied

        return super(GroupRestrictionMixin, self).dispatch(request, *args, **kwargs)

然后,您可以使用mixin创建需要该行为的任何视图:

class SecretPostView(GroupRestrictionMixin, DetailView):
    pass

如果它是你所谓的“惯用语”,请点击,但这是让它变得简单和可重复使用的更容易的方式。

编辑:必须在此处设置请求,args和kwargs,以便get_object方法可以访问它们。它有点丑陋(你必须重复一些基于dispatch方法的代码),但仍然有效:F