Search code examples
javascriptpythondjangocsrfdjango-csrf

CSRF verification failed for Django despite Firebug saying there is a csrftoken underneath cookies tab. Why?


I followed a lot of the stuff recommended on StackOverflow but to no avail. Also I tried to squeeze in {% csrf_token %} in the html in various places but none seemed to work. Any suggestions? Here's my Django template input button:

<input id=saveWaypoints type=button value=Save disabled=disabled>

Which then triggers this Javascript:

$('#saveWaypoints').click(function () {
    var waypointStrings = [];
    for (id in waypointByID) {
        waypoint = waypointByID[id];
        waypointStrings.push(id + ' ' + waypoint.lng + ' ' + waypoint.lat);
    };
    waypointStrings["csrfmiddlewaretoken"] = $('input[name=csrfmiddlewaretoken]').val();
    $.post("{% url 'waypoints-save' %}", {
        waypointsPayload: waypointStrings.join('\n')
    }, function (data) {
        if (data.isOk) {
            $('#saveWaypoints').attr('disabled', 'disabled');
        } else {
            alert(data.message);
        }
    });
});

Which then calls the this view in views.py:

def save(request):
    'Save waypoints'
    for waypointString in request.POST.get('waypointsPayload', '').splitlines():
        waypointID, waypointX, waypointY = waypointString.split()
        waypoint = Waypoint.objects.get(id=int(waypointID))
        waypoint.geometry.set_x(float(waypointX))
        waypoint.geometry.set_y(float(waypointY))
        waypoint.save()
    return HttpResponse(simplejson.dumps(dict(isOk=1)), content_type='application/json')

Solution

  • According to django docs, you can either put the token as header of the request or add it as payload https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

    You're almost there, but you just have to send it as its own parameter, and not part of waypointsPayload:

    $.post("{% url 'waypoints-save' %}", {
      csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
      waypointsPayload: waypointStrings.join('\n')
    }, function (data) {
      ...
    });
    

    The cookie is an alternate location to read the token from, instead of the input (in case you don't want to pepper the template with token tags).