首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在基于django类的视图上使用permission_required装饰器

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

Stack Overflow用户
提问于 2011-05-20 16:01:12
回答 13查看 103.8K关注 0票数 170

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

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

以下是代码(GPL):

代码语言:javascript
复制
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
EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2011-05-20 16:42:20

the CBV docs中列出了一些策略

urls.py (docs)中实例化视图时装饰视图

代码语言:javascript
复制
urlpatterns = [
    path('view/',login_required(ViewSpaceIndex.as_view(..)),
    ...
]

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

装饰您的类,以便包装视图的每个实例(docs)

有两种方法可以完成此操作:

  1. method_decorator应用于您的CBV派单方法,例如,

从django.utils.decorators导入method_decorator @method_decorator(login_required,name='dispatch')类ViewSpaceIndex(TemplateView):template_name =django.utils.decorators

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

代码语言:javascript
复制
    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这样的混入,在这里的其他答案中描述得很好:

从django.contrib.auth.mixins导入登录类登录( LoginRequiredMixin,MyView):login_url =‘/MyView/’redirect_field_name =LoginRequiredMixin

确保将mixin类放在继承列表的第一位(以便Python的Method Resolution Order algorithm选择正确的内容)。

文档中解释了你获得TypeError的原因:

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

票数 229
EN

Stack Overflow用户

发布于 2011-06-23 21:51:53

这是我的方法,我创建了一个受保护的混入(它保存在我的混入库中):

代码语言:javascript
复制
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

class LoginRequiredMixin(object):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

当你想要保护一个视图时,你只需添加适当的混合:

代码语言:javascript
复制
class SomeProtectedViewView(LoginRequiredMixin, TemplateView):
    template_name = 'index.html'

只要确保你的混入是第一位就行了。

更新: Django我在2011年发布了这篇文章,从1.9Django版本开始,现在包括了这个和其他有用的 (AccessMixin,PermissionRequiredMixin,UserPassesTestMixin)作为标准!

票数 120
EN

Stack Overflow用户

发布于 2011-12-08 18:13:28

这里有一个使用基于类的装饰器的替代方案:

代码语言:javascript
复制
from django.utils.decorators import method_decorator

def class_view_decorator(function_decorator):
    """Convert a function based decorator into a class based decorator usable
    on class based Views.

    Can't subclass the `View` as it breaks inheritance (super in particular),
    so we monkey-patch instead.
    """

    def simple_decorator(View):
        View.dispatch = method_decorator(function_decorator)(View.dispatch)
        return View

    return simple_decorator

然后可以像这样简单地使用它:

代码语言:javascript
复制
@class_view_decorator(login_required)
class MyView(View):
    # this view now decorated
票数 47
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6069070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档