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_required
decorator 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?
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With