castiel castiel - 7 months ago 58
Python Question

@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.

Answer

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})