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

Osc*_*lal 151 django django-views django-authentication django-class-based-views class-based-views

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

我尝试使用@method_decorator,但它回复" / errors/prueba/_wrapped_view()中的TypeError至少需要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
Run Code Online (Sandbox Code Playgroud)

A L*_*Lee 188

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

  1. 在您的urls.py路线中添加装饰器,例如,login_required(ViewSpaceIndex.as_view(..))

  2. dispatchmethod_decorator例如,装饰你的CBV 方法

    from django.utils.decorators import method_decorator
    
    @method_decorator(login_required, name='dispatch')
    class ViewSpaceIndex(TemplateView):
        template_name = 'secret.html'
    
    Run Code Online (Sandbox Code Playgroud)

    在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)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用Django 1.9+中提供的django.contrib.auth.mixins.LoginRequiredMixin等访问mixins ,并在其他答案中概述:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
    
        login_url = '/login/'
        redirect_field_name = 'redirect_to'
    
    Run Code Online (Sandbox Code Playgroud)

你得到的原因TypeError在文档中解释:

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

  • 最新文档中提到这里https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/ (3认同)

Ger*_*eyn 115

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

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)
Run Code Online (Sandbox Code Playgroud)

每当您想要保护视图时,只需添加适当的mixin:

class SomeProtectedViewView(LoginRequiredMixin, TemplateView):
    template_name = 'index.html'
Run Code Online (Sandbox Code Playgroud)

只要确保你的mixin是第一个.

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

  • +1表示这个mixin必须是第一个. (4认同)

mjt*_*lyn 45

这是使用基于类的装饰器的替代方法:

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
Run Code Online (Sandbox Code Playgroud)

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

@class_view_decorator(login_required)
class MyView(View):
    # this view now decorated
Run Code Online (Sandbox Code Playgroud)

  • 这是如此之大,应考虑纳入上游IMO. (9认同)
  • 您可以使用它来链接视图装饰器,很好!+1 (3认同)

mep*_*sto 14

我意识到这个线程有点陈旧,但无论如何这里是我的两分钱.

使用以下代码:

from django.utils.decorators import method_decorator
from inspect import isfunction

class _cbv_decorate(object):
    def __init__(self, dec):
        self.dec = method_decorator(dec)

    def __call__(self, obj):
        obj.dispatch = self.dec(obj.dispatch)
        return obj

def patch_view_decorator(dec):
    def _conditional(view):
        if isfunction(view):
            return dec(view)

        return _cbv_decorate(dec)(view)

    return _conditional
Run Code Online (Sandbox Code Playgroud)

我们现在有办法修补装饰器,因此它将变得多功能化.这实际上意味着当应用于常规视图装饰器时,如下所示:

login_required = patch_view_decorator(login_required)
Run Code Online (Sandbox Code Playgroud)

这个装饰器在按原来的方式使用时仍然可以工作:

@login_required
def foo(request):
    return HttpResponse('bar')
Run Code Online (Sandbox Code Playgroud)

但在使用时也会正常工作:

@login_required
class FooView(DetailView):
    model = Foo
Run Code Online (Sandbox Code Playgroud)

在我最近遇到的几个案例中,这似乎工作得很好,包括这个现实世界的例子:

@patch_view_decorator
def ajax_view(view):
    def _inner(request, *args, **kwargs):
        if request.is_ajax():
            return view(request, *args, **kwargs)
        else:
            raise Http404

    return _inner
Run Code Online (Sandbox Code Playgroud)

编写ajax_view函数是为了修改(基于函数的)视图,因此每当非ajax调用访问此视图时,它都会引发404错误.通过简单地将补丁函数应用为装饰器,该装饰器也被设置为在基于类的视图中工作


vis*_*ell 14

对于那些你谁使用的Django> = 1.9,它已经列入django.contrib.auth.mixinsAccessMixin,LoginRequiredMixin,PermissionRequiredMixinUserPassesTestMixin.

所以要将LoginRequired应用于CBV(例如DetailView):

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.detail import DetailView


class ViewSpaceIndex(LoginRequiredMixin, DetailView):
    model = Space
    template_name = 'spaces/space_index.html'
    login_url = '/login/'
    redirect_field_name = 'redirect_to'
Run Code Online (Sandbox Code Playgroud)

这也很好地记住GCBV密新秩序:混入必须走在左边一侧,基本视图类必须在走右边侧.如果订单不同,您可能会破坏不可预测的结果.

  • 这是 2019 年的最佳答案。此外,关于混合顺序的要点。 (2认同)

小智 5

使用 Django 大括号。它提供了许多易于使用的有用的mixin。它有漂亮的文档。试试看。

您甚至可以创建自定义的 mixin。

http://django-braces.readthedocs.org/en/v1.4.0/

示例代码:

from django.views.generic import TemplateView

from braces.views import LoginRequiredMixin


class SomeSecretView(LoginRequiredMixin, TemplateView):
    template_name = "path/to/template.html"

    #optional
    login_url = "/signup/"
    redirect_field_name = "hollaback"
    raise_exception = True

    def get(self, request):
        return self.render_to_response({})
Run Code Online (Sandbox Code Playgroud)