Django:DRY原理和UserPassesTestMixin [英] Django: DRY principle and UserPassesTestMixin

查看:98
本文介绍了Django:DRY原理和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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆