2

假设我的应用程序就像一个论坛,但每个帖子都有一组可能会看到它的人。

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()被调用时,我对这个对象一无所知。在已经检索到对象后,是否有一种好的/惯用的方法来限制用户访问?

4

1 回答 1

2

您可以访问self方法装饰器内部,因此您可以访问当前调用的对象self.get_object()

无论如何,如果您只在通用视图上使用此行为,那么您最好创建一个实现该dispatch方法(或可能是该get_object方法)并在那里进行检查的 mixin,例如(使用一点想象力,因为 idk how您的组已定义,也许您正在使用 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

于 2013-03-03T02:58:03.393 回答