Django:DRY原理和UserPassesTestMixin [英] Django: DRY principle and UserPassesTestMixin
问题描述
我有一个名为 Post
的模型,并有一个名为 owner
的字段(<$ c $的外键c>用户)。当然,只有所有者可以更新
或删除
自己的帖子。
I have a model named Post
and have a field there called owner
(foreign key to User
). Of course, only owners can update
or delete
their own posts.
话虽这么说,我在视图中使用 login_required
装饰器以确保用户已登录,但是随后,我还需要确保用户尝试更新
/ 删除
,问题是所有者
。
That being said, I use login_required
decorator in the views to make sure the user is logged in but then, I also need to make sure the user trying to update
/delete
the question is the owner
.
当我使用 Django:通用编辑视图,该文档说我需要使用 Django:UserPassesTestMixin 。
As I'm using Django: Generic Editing Views the documentation says I need to use Django: UserPassesTestMixin.
此验证将针对更新
和删除
视图。 DRY,如何处理?我应该创建一个名为 TestUserOwnerOfPost
的类并创建一个 test_func()
然后进行 update
和 delete
视图是否从中继承?
This validation will be done for the update
and delete
views. DRY, what is the way to go about this? should I create a class named TestUserOwnerOfPost
and create a test_func()
and then make the update
and delete
views inherit from it?
原因是我尝试过的但没有起作用,代码如下:
Cause that's what I have tried and didn't work, code below:
from django.views.generic.edit import UpdateView
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import UserPassesTestMixin
class TestUserOwnerOfPost(UserPassesTestMixin):
def test_func(self):
return self.request.user == self.post.owner
class EditPost(UpdateView, TestUserOwnerOfPost):
model = Post
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(EditPost, self).dispatch(*args, **kwargs)
使用上面的代码,每个登录的用户系统中的人可以编辑
/ 删除
任何帖子。我究竟做错了什么?我错过了什么吗?
With the code above, every logged-in user in the system can edit
/delete
any post. What am I doing wrong? am I missing something? thanks.
推荐答案
第一个问题是,如@rafalmp所说,您继承的类的顺序不正确。
The first problem is that the order of the classes you inherit is incorrect, as @rafalmp says.
但是,解决该问题并不能解决问题,因为 UserPassesTest
mixin会执行之前运行视图。这意味着检查 self.object
的所有者并不适合,因为尚未设置 self.object
然而。注意我使用的是 self.object
而不是 self.post
-我不认为视图曾经设置了 self.post
,但我对此可能是错的。
However, fixing that doesn't solve the problem, because the UserPassesTest
mixin performs the test before running the view. This means that it's not really suitable to check the owner of self.object
, because self.object
has not been set yet. Note I'm using self.object
instead of self.post
-- I'm don't think that the view ever sets self.post
but I might be wrong about that.
一种选择是调用 self.get_object()
在测试函数中。这有点效率低下,因为您的视图将两次获取对象,但实际上这并不重要。
One option is to call self.get_object()
inside the test function. This is a bit inefficient because your view will fetch the object twice, but in practice it probably doesn't matter.
def test_func(self):
self.object = self.get_object()
return self.request.user == self.object.owner
另一种方法是覆盖 get_queryset
,以将其限制为用户拥有的对象。这意味着如果用户不拥有该对象,则将收到404错误。此行为与 UserPassesTestMixin
完全不同,后者将重定向到登录页面,但对您来说可能没问题。
Another approach is to override get_queryset
, to restrict it to objects owned by the user. This means the user will get a 404 error if they do not own the object. This behaviour is not exactly the same as the UserPassesTestMixin
, which will redirect to a login page, but it might be ok for you.
class OwnerQuerysetMixin(object):
def get_queryset(self):
queryset = super(OwnerQuerysetMixin, self).get_queryset()
# perhaps handle the case where user is not authenticated
queryset = queryset.filter(owner=self.request.user)
return queryset
这篇关于Django:DRY原理和UserPassesTestMixin的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!