Question

I am using Daxice library to create AJAX calls in my Django app. When I create a POST method on a form I get the mentioned error:

Forbidden (403)
CSRF verification failed. Request aborted.

My settings.py have:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.request',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.csrf',
)

My urls.py

from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from dajaxice.core import dajaxice_autodiscover, dajaxice_config
dajaxice_autodiscover()

urlpatterns = patterns('',
    url(dajaxice_config.dajaxice_url, include('dajaxice.urls')),
    url(r'^$', 'apps.views.home'),
)

urlpatterns += staticfiles_urlpatterns()

My views.py:

from django.http import HttpResponse
from django.template import loader, Context

from django.core.context_processors import csrf

def home(request):
    t = loader.get_template('index.html')
    html = t.render(Context( ))
    return HttpResponse(html)

My template index.html:

{% load dajaxice_templatetags %}

<html>
  <head>
    <title>My base template</title>

    <script src="http://code.jquery.com/jquery-latest.min.js"
        type="text/javascript"></script>

    {% dajaxice_js_import %}

    <script type="text/javascript">

    function shout(data){
        alert(data.message)

    }

    </script>
  </head>
  <body>

    <form method="POST" action="">{% csrf_token %}
        Page: <input type="text" name="page"><br>
        From: <input type="text" name="from"> (From < To) <br>
        To: <input type="text" name="to"> (returns results before that day)<br>
        <input type="submit" onclick="Dajaxice.apps.hello(shout);" value="Submit">
    </form>

    <br>
    <br>

    <input type="button" onclick="Dajaxice.apps.hello(shout);" value="Get message from server!">

   </body>
</html>

And my ajax.py:

import simplejson
from dajaxice.decorators import dajaxice_register

@dajaxice_register(method='GET')
@dajaxice_register(method='POST', name='other_post')
def hello(request):
    return simplejson.dumps({'message':'Hello from Python!'})

If I click the button, the message gets alerted. When I submit the form I get this error. How can I fix it?

Finally I believe I have fixed all the possibilities for the CSRF display in the debug page:

In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function uses RequestContext for the template, instead of Context.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
Was it helpful?

Solution

Alright I think I got it. In the line:

<form>
...
<input type="submit" onclick="Dajaxice.apps.hello(shout);" value="Submit"></form>
...
</form>

If the type is button it works. It should be something with the submit behavior of the server request. I'm not an expert to explain why is this happening, so if somebody can explain I would gladly give the vote.

OTHER TIPS

According to docs you can send csrf-token on every ajax-post request if you run this script first:

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
    // test that a given url is a same-origin URL
    // url could be relative or scheme relative or absolute
    var host = document.location.host; // host + port
    var protocol = document.location.protocol;
    var sr_origin = '//' + host;
    var origin = protocol + sr_origin;
    // Allow absolute or scheme relative URLs to same origin
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
        (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
            // Send the token to same-origin, relative URLs only.
            // Send the token only if the method warrants CSRF protection
            // Using the CSRFToken value acquired earlier
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

It is written in jquery. If you want vanilla js, visit docs

Dajaxice does CSRF handling for you, you don't need any custom jQuery beforeSend code.

But you need to grant Dajaxice access to your CSRF cookie. Therefore:

Make sure CSRF_COOKIE_HTTPONLY is set to False in your settings.py!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top