在Django CBV中检查403的位置?

时间:2015-05-06 02:32:37

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

我正在制作一个基础应用程序来教授初学者。每个用户都可以写笔记,但我想这样做是为了让用户无法查看或更新不同用户的笔记。

我有以下观点,但我不得不重复自己。

from django.core.exceptions import PermissionDenied

...

class NoteUpdate(LoginRequiredMixin, UpdateView):

    ...

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()

        if self.object.owner != self.request.user:
            raise PermissionDenied

        return super(NoteUpdate, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()

        if self.object.owner != self.request.user:
            raise PermissionDenied

        return super(NoteUpdate, self).post(request, *args, **kwargs)

我觉得可能有一种方法可以做到这一点而不重复自己。是的,我可以写一个像这样的方法并从两个方面调用它:

def check_permission(self):
   if self.object.owner != self.request.user:
        raise PermissionDenied 

但我真正的意思是我压倒了错误的方法吗?有没有更传统的方式来做到这一点?感觉有点怪异的重写.get()和.post()

2 个答案:

答案 0 :(得分:3)

要回答您的问题:覆盖.get().post()很好,因为出于安全性和完整性原因,您需要先验证get()post()个观看次数显示并特别修改数据。现在,如果你想在get或post中重构这个,有两种简单的方法:

主要(模型方法):

models.py

class Model(models.Model):
    owner = models.ForeignKey(User)
    ...

    def deny_if_not_owner(self, user):
        if self.owner != user:
            raise PermissionDenied
        return self.owner

views.py

class NoteUpdate(LoginRequiredMixin, UpdateView):
    ...

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()

        self.object.deny_if_not_owner(request.user)

        return super(NoteUpdate, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()

        self.object.deny_if_not_owner(request.user)

        return super(NoteUpdate, self).post(request, *args, **kwargs)

///////

替代方案(Mixin):

如果您将来再次使用此验证,那么创建一个Mixin将允许您轻松地将此代码添加到许多类中。

class DenyWrongUserMixin(object):
    def get(self):
        if self.object.owner != self.request.user:
            raise PermissionDenied
        return super(DenyWrongUserMixin, self).get(*args, **kwargs)

    def post(self):
        if self.object.owner != self.request.user:
            raise PermissionDenied
        return super(DenyWrongUserMixin, self).post(*args, **kwargs)

然后:

class NoteUpdate(LoginRequiredMixin, DenyWrongUserMixin, UpdateView):

    ...

    def get(self, request, *args, **kwargs):
        ...

    def post(self, request, *args, **kwargs):
        ...

答案 1 :(得分:0)

您可以覆盖get方法或get_queryset方法。如果登录用户不是所有者,则get_queryset将引发404。

def get_queryset(self):
    qs = super(NoteUpdate, self).get_queryset()
    return qs.filter(owner=self.request.user)

或者您可以覆盖get方法,因为它将首先调用,然后引发PermissionDenied,因此没有理由覆盖post方法。

def get(self, request, *args, **kwargs):
    self.object = self.get_object()
    if self.object.owner != self.request.user:
        raise PermissionDenied
    return super(NoteUpdate, self).get(request, *args, **kwargs)

然后你可以创建一个mixin并从mixin扩展你的视图以避免重复。