@csrf_exempt does not work on generic view based class
class ChromeLoginView(View):
def get(self, request):
return JsonResponse({'status': request.user.is_authenticated()})
@method_decorator(csrf_exempt)
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return JsonResponse({'status': True})
return JsonResponse({'status': False})
I am expecting that the post does stopped by csrf, but it return 403 error.
But if remove that decorator and do this in the URLConf
url(r'^chrome_login/', csrf_exempt(ChromeLoginView.as_view()), name='chrome_login'),
it will work.
What happened here? didn't it supposed to work, because I guess that's what method_decorator do. I'm using python3.4 and django1.7.1
Any advice would be great.
Solution 1:
As @knbk said, this is the dispatch()
method that must be decorated.
Since Django 1.9, you can use the method_decorator
directly on a class:
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt, name='dispatch')
class ChromeLoginView(View):
def get(self, request):
return JsonResponse({'status': request.user.is_authenticated()})
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return JsonResponse({'status': True})
return JsonResponse({'status': False})
This avoids overriding the dispatch()
method only to decorate it.
Solution 2:
You need to decorate the dispatch
method for csrf_exempt
to work. What it does is set an csrf_exempt
attribute on the view function itself to True
, and the middleware checks for this on the (outermost) view function. If only a few of the methods need to be decorated, you still need to use csrf_exempt
on the dispatch
method, but you can use csrf_protect
on e.g. put()
. If a GET
, HEAD
, OPTIONS
or TRACE
HTTP method is used it won't be checked whether you decorate it or not.
class ChromeLoginView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(ChromeLoginView, self).dispatch(request, *args, **kwargs)
def get(self, request):
return JsonResponse({'status': request.user.is_authenticated()})
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return JsonResponse({'status': True})
return JsonResponse({'status': False})
Solution 3:
If you are looking for Mixins to match your needs, then you can create a CSRFExemptMixin and extend that in your view no need of writing above statements in every view:
class CSRFExemptMixin(object):
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(CSRFExemptMixin, self).dispatch(*args, **kwargs)
After that Extend this in your view like this.
class ChromeLoginView(CSRFExemptMixin, View):
You can extend that in any view according to your requirement, That's reusability! :-)
Cheers!