required decorators on django class

I'm having a bit of trouble understanding how the new CBVs work. My question is this, I need to require login in all the views, and in some of them, specific permissions. In function-based views I do that with @permission_required() and the login_required attribute in the view, but I don't know how to do this on the new views. Is there some section in the django docs explaining this? I didn't found anything. What is wrong in my code?

I tried to use the @method_decorator but it replies " TypeError at /spaces/prueba/ _wrapped_view() takes at least 1 argument (0 given) "

Here is the code (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

There are a few strategies listed in the CBV docs:

  • Add the decorator in your urls.py route, eg, login_required(ViewSpaceIndex.as_view(..))

  • Decorate your CBV's dispatch method with a method_decorator eg,

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

    Before Django 1.9 you can't use method_decorator on the class, so you have to override the dispatch method:

    class ViewSpaceIndex(TemplateView):
    
        @method_decorator(login_required)
        def dispatch(self, *args, **kwargs):
            return super(ViewSpaceIndex, self).dispatch(*args, **kwargs)
    
  • Use the access mixins like django.contrib.auth.mixins.LoginRequiredMixin available in Django 1.9+ and outlined well in the other answers here:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class MyView(LoginRequiredMixin, View):
    
        login_url = '/login/'
        redirect_field_name = 'redirect_to'
    
  • The reason you're getting a TypeError is explained in the docs:

    Note: method_decorator passes *args and **kwargs as parameters to the decorated method on the class. If your method does not accept a compatible set of parameters it will raise a TypeError exception.


    Here is my approach, I create a mixin that is protected (this is kept in my mixin library):

    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)
    

    Whenever you want a view to be protected you just add the appropriate mixin:

    class SomeProtectedViewView(LoginRequiredMixin, TemplateView):
        template_name = 'index.html'
    

    Just make sure that your mixin is first.

    Update: I posted this in way back in 2011, starting with version 1.9 Django now includes this and other useful mixins (AccessMixin, PermissionRequiredMixin, UserPassesTestMixin) as standard!


    Here's an alternative using class based decorators:

    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
    

    This can then be used simply like this:

    @class_view_decorator(login_required)
    class MyView(View):
        # this view now decorated
    
    链接地址: http://www.djcxy.com/p/77260.html

    上一篇: Django表单不会呈现

    下一篇: django类需要装饰器