在哪里检查 Django CBV 中的 403?
Where to check for 403 in a Django CBV?
我正在制作一个基本的应用程序来教初学者。每个用户都可以写笔记,但我想让一个用户不能查看或更新不同用户的笔记。
我有以下看法,但我不得不重复一遍。
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):
创建一个 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_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 扩展你的视图以避免重复。
我正在制作一个基本的应用程序来教初学者。每个用户都可以写笔记,但我想让一个用户不能查看或更新不同用户的笔记。
我有以下看法,但我不得不重复一遍。
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):
创建一个 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_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 扩展你的视图以避免重复。