小编典典

如何在基于 django 类的视图上使用 permission_required 装饰器

all

我在理解新的 CBV 的工作原理时遇到了一些麻烦。我的问题是,我需要登录所有视图,其中一些视图需要特定权限。在基于函数的视图中,我使用
@permission_required() 和视图中的 login_required 属性来执行此操作,但我不知道如何在新视图上执行此操作。django
文档中是否有一些部分对此进行了解释?我什么也没找到。我的代码有什么问题?

我尝试使用@method_decorator,但它回复“ TypeError at /spaces/prueba/_wrapped_view()
需要至少 1 个参数(给定 0)

这是代码(GPL):

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required, permission_required

class ViewSpaceIndex(DetailView):

    """
    Show the index page of a space. Get various extra contexts to get the
    information for that space.

    The get_object method searches in the user 'spaces' field if the current
    space is allowed, if not, he is redirected to a 'nor allowed' page. 
    """
    context_object_name = 'get_place'
    template_name = 'spaces/space_index.html'

    @method_decorator(login_required)
    def get_object(self):
        space_name = self.kwargs['space_name']

        for i in self.request.user.profile.spaces.all():
            if i.url == space_name:
                return get_object_or_404(Space, url = space_name)

        self.template_name = 'not_allowed.html'
        return get_object_or_404(Space, url = space_name)

    # Get extra context data
    def get_context_data(self, **kwargs):
        context = super(ViewSpaceIndex, self).get_context_data(**kwargs)
        place = get_object_or_404(Space, url=self.kwargs['space_name'])
        context['entities'] = Entity.objects.filter(space=place.id)
        context['documents'] = Document.objects.filter(space=place.id)
        context['proposals'] = Proposal.objects.filter(space=place.id).order_by('-pub_date')
        context['publication'] = Post.objects.filter(post_space=place.id).order_by('-post_pubdate')
        return context

阅读 180

收藏
2022-08-08

共1个答案

小编典典

CBV 文档中列出了一些策略:

urls.py在( [docs](https://docs.djangoproject.com/en/dev/topics/class-

based-views/intro/#decorating-in-urlconf) )中实例化视图时装饰视图

urlpatterns = [
    path('view/',login_required(ViewSpaceIndex.as_view(..)),
    ...
]

urls.py装饰器是基于每个实例应用的,因此您可以根据需要在不同的路由中添加或删除它。

装饰您的类,以便包装视图的每个实例([文档](https://docs.djangoproject.com/en/dev/topics/class-

based-views/intro/#decorating-the-class))

有两种方法可以做到这一点:

  1. 适用method_decorator于您的 CBV 调度方法,例如,

     from django.utils.decorators import method_decorator
    

    from django.contrib.auth.decorators import login_required

    @method_decorator(login_required, name=’dispatch’)
    class ViewSpaceIndex(TemplateView):
    template_name = ‘secret.html’

如果您使用的是 Django <
1.9(您不应该这样做,它不再受支持),则您不能method_decorator在该类上使用,因此您必须dispatch手动覆盖该方法:

    class ViewSpaceIndex(TemplateView):

        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super(ViewSpaceIndex, self).dispatch(*args, **kwargs)
  1. 使用像django.contrib.auth.mixins.LoginRequiredMixin这样的 mixin ,在此处的其他答案中得到了很好的概述:

     from django.contrib.auth.mixins import LoginRequiredMixin
    

    class MyView(LoginRequiredMixin, View):

     login_url = '/login/'
     redirect_field_name = 'redirect_to'
    

确保将 mixin 类放在继承列表的第一个位置(因此 Python
方法解析顺序算法会选择正确的东西)。

您获得 a 的原因TypeError在文档中进行了解释:

注意:method_decorator 将 args 和 *kwargs 作为参数传递给类上的装饰方法。如果您的方法不接受一组兼容的参数,它将引发
TypeError 异常。

2022-08-08