Search code examples
pythondjangocsrf

Django @csrf_exempt decorator not working


I'm using DJango 1.8 on a linode server, and have the following view:

import json

from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt

def home_view(request):
        r = { 'response': 'OK', 'data': None }
        return HttpResponse(json.dumps(r), content_type = "application/json")

@csrf_exempt
def ping(request):
        r = { 'response': 'OK', 'data': 'ping' }
        return HttpResponse(json.dumps(r), content_type = "application/json")

My urls look like this:

urlpatterns = [
    url(r'^django/admin/', include(admin.site.urls)),
    url(r'^django/$', home_view),
    url(r'^django/ping/$', ping),
    url(r'^django/echo/$', echo),
]

If I go to my linode site at http://mylinodesite/django/ping/

I get:

{"data": "ping", "response": "OK"}

Great. If I use jquery and do a

$.get("http://mylinodesite/django/ping/")

I get

No 'Access-Control-Allow-Origin' header is present on the requested resource.

From what I understand the @csrf_exempt is supposed to get rid of the CSRF header stuff. What gives?


Solution

  • Daniel, turns out you're partially right. It's CORS but it cannot be fixed on the jQuery side. Here's my Django view code that does what I want. Note that it adds the Access-Control-Allow-Origin header to allow requests from all (*) for GET only.

    This is also just a demonstration of how to do this all in one file. One could create middleware to do this for all requests if needed, but this works and is a good example of how to do it all in one place so you can see what is going on, and here is the full gist of the entire view file:

    def ping(request):
            r = { 'response': 'OK', 'data': 'ping' }
            response = HttpResponse("['ok']", content_type="application/json")
            response['Access-Control-Allow-Origin'] = '*'
            response['Access-Control-Allow-Methods'] = 'GET'
    
            return response