在Django CBV中在哪里检查403?
我正在制作一个基本的应用程序来教初学者。每个用户都可以编写注释,但我希望这样做,以便用户无法查看或更新其他用户的注释 我有以下观点,但我不得不重复我自己的观点在Django CBV中在哪里检查403?,django,django-views,django-class-based-views,Django,Django Views,Django Class Based Views,我正在制作一个基本的应用程序来教初学者。每个用户都可以编写注释,但我希望这样做,以便用户无法查看或更新其他用户的注释 我有以下观点,但我不得不重复我自己的观点 from django.core.exceptions import PermissionDenied ... class NoteUpdate(LoginRequiredMixin, UpdateView): ... def get(self, request, *args, **kwargs):
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()来回答您的问题感觉有点奇怪:覆盖
.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将允许您轻松地将此代码添加到许多类中
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):
...
您可以重写get方法或get_queryset方法。如果登录用户不是所有者,则get_查询集将引发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扩展视图以避免重复。如果我覆盖GET,但不覆盖POST,我知道我将防止发生意外(因为他们无法通过web查看表单页面以提交表单)但是,难道就不能有人仍然怀有恶意吗?我还以为你在尝试重构以实现可伸缩的使用。我更新了我的答案,直接回答了你的问题“是否覆盖了
get
和post
正确-我的答案是肯定的。您可以查看我修改过的答案以了解原因,主要解决方案显示了如何将一些验证引入模型级别以减少视图中的代码,同时允许以后轻松实现。感谢您更新的答案。这对于制作厚模型和瘦视图来说是一个很好的提醒,尽管在模型中放置HTTP响应内容的方法确实错误。(我删除了我以前的评论,因为它不适用于你关于mixin的新评论,尽管现在我看到你回复了它。对不起!)。