Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django @login_required for class views

I inherited a Django(1.5.1) project and I need to put one view behind a @login_required decorator. Here is what i have in views.py:

I got this snippet of code from here and it looks like its purpose is to allow someone to apply the @login_requireddecorator to a class

class LoginRequiredMixin(object):
    """
    View mixin which verifies that the user has authenticated.

    NOTE:
        This should be the left-most mixin of a view.
    """

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


class PermissionRequiredMixin(object):
    login_url = settings.LOGIN_URL
    permission_required = None
    raise_exception = False
    redirect_field_name = '/workers/'

    def dispatch(self, request, *args, **kwargs):
        # Verify class settings
        if self.permission_required == None or len(
            self.permission_required.split(".")) != 2:
            raise Error("'PermissionRequiredMixin' requires "
                "'permission_required' attribute to be set.")

        has_permission = request.user.has_perm(self.permission_required)

        if not has_permission:
            if self.raise_exception:
                return HttpResponseForbidden()
            else:
                path = urlquote(request.get_full_path())
                tup = self.login_url, self.redirect_field_name, path
                return HttpResponseRedirect("%s?%s=%s" % tup)

        return super(PermissionRequiredMixin, self).dispatch(
            request, *args, **kwargs)

I then apply this to the view i want to add permissions to like so:

class RootWorkerView(LoginRequiredMixin, PermissionRequiredMixin, APIView):
    renderer_classes = (WorkersJSONRenderer, JSONRenderer,
                        BrowsableAPIRenderer)

    def get(self, request):
        worker_list = rest_models.WorkerList(request)
        serializer = WorkerListSerializer(worker_list)
        return Response(serializer.data)

The APIView argument is a carry over, as before it was the only argument. Is this correct?

When run, I get nothing. The template for the view I want to secure shows up with no login prompt.

Relevant snippet from urls.py:

url(r'^workers/$', views.RootWorkerView.as_view(),
    name='root_worker_view'),

url(r'^login/$', 'django.contrib.auth.views.login',
    {'template_name': 'dashboard/login.html'}),

/login/ does work, and I can login successful, so that's not the issue.

I feel like @method_decorator(login_required) isnt doing its job. Any ideas?

like image 545
Michael Avatar asked Feb 17 '15 05:02

Michael


People also ask

How do you use decorators in class based view in Django?

To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class. The decorators will process a request in the order they are passed to the decorator.

How is decorator used in class based view?

You need to apply the decorator to the dispatch method of the class based view. This can be done as follows: class ProfileView(View): @youdecorator def dispatch(self,request,*args,**kwargs): return super(ProfileView,self). dispatch(request,*args,**kwargs) //Rest of your code.


Video Answer


2 Answers

You can add the decorator in the urls.py

from django.contrib.auth.decorators import login_required
 url(r'^workers/$', login_required(views.RootWorkerView.as_view()))

This worked for me.

like image 113
FMZ Avatar answered Sep 20 '22 08:09

FMZ


now you can use Django builtin LoginRequiredMixin

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

https://docs.djangoproject.com/en/3.2/topics/auth/default/#the-loginrequired-mixin

like image 25
Mahdi mehrabi Avatar answered Sep 22 '22 08:09

Mahdi mehrabi