11

情况很简单:我正在编写一个多用户博客系统。系统应防止非所有者编辑或删除博客文章。在我看来,我使用通用视图。

类博客更新视图(更新视图):...

我知道我应该使用@method_decorator 来装饰调度方法。但是,大多数示例只是 @method_decorator(login_required) 或模型级别权限。如何应用对象级别的权限来检查 request.user 是否是这篇博文的作者?例如,我尝试使用 django-authority 应用程序,我在这个文件中有一个 BlogPermission 类。我试图在这个类中定义一个方法,例如

def blog_edit(self, ??, ??)

我应该在这个方法中加入什么?

然后像这样调用它: @method_decorator(permission_required('blog_permission.blog_edit(???)'))

我应该在这里传递什么?

更新:阅读method_decorator代码后,我发现它只能接受没有参数的函数。我认为这就是为什么 permission_required 在这里不起作用。但是解决这个问题的方法是什么?

更新解决方案:

在 dispatch 方法中,我检查用户权限,如果用户不满足权限,则返回 HttpResponseForbidden()。

4

2 回答 2

15

您可以使用基于类的视图来做到这一点:

class BlogEdit(UpdateView):
    model = Blog

    def dispatch(self, request, *args, **kwargs):
        if not request.user.has_perm('blog_permission.blog_edit'):
            return HttpResponseForbidden()
        return super(BlogEdit, self).dispatch(request, *args, **kwargs)

    # OR (for object-level perms)

    def get_object(self, *args, **kwargs):
        obj = super(BlogEdit, self).get_object(*args, **kwargs)
        if not obj.user == self.request.user:
            raise Http404 # maybe you'll need to write a middleware to catch 403's same way
        return obj
于 2012-04-28T05:11:48.393 回答
0

另一种选择是使用UserPassesTestMixin(或基于函数的user_passes_test)。

class UserPassesTestMixin

使用基于类的视图时,您可以使用 UserPassesTestMixin来执行此操作。

test_func()

您必须重写test_func()类的方法以提供执行的测试。此外,您可以设置任何参数来自AccessMixin定义对未授权用户的处理:

from django.contrib.auth.mixins import UserPassesTestMixin

class MyView(UserPassesTestMixin, View):

    def test_func(self):
        return self.request.user.email.endswith('@example.com')

我们现在可以检查是否self.request.user允许处理传递给self.request.GETor的详细信息self.request.POST

class MyView(UserPassesTestMixin, View):
    raise_exception = True  # To not redirect to the login url and just return 403. For the other settings, see https://docs.djangoproject.com/en/3.2/topics/auth/default/#django.contrib.auth.mixins.AccessMixin

    def test_func(self):
        return (
            self.request.user.is_staff
            or self.request.user.has_perm('app.change_blog')
            or self.request.user.email.endswith('@company.staff.com')
            or is_requested_object_accessible(self.request.user, self.request.GET, self.request.POST)  # If you have a custom checker
        )
    ...
于 2021-08-24T09:57:33.447 回答