Description

On updating my javascript AJAX CSRF token fix to match the current docs, I encountered a problem. If your browser does not yet have the CSRF cookie for your site and you did not include {% csrf_token %} somewhere in the template rendered on full page load, the following will result in csrftoken being undefined:

var csrftoken = getCookie('csrftoken');

Or with jQuery cookie plugin:

var csrftoken = $.cookie('csrftoken');

The example javascript code simply references this csrftoken variable, set on initial page load, in ajaxSetup's beforeSend method. When an AJAX form is brought in later, regardless of whether it includes the csrf cookie, the javascript code assumes it already checked for the cookie and got undefined, and it results in a 403 error.

The fix is simply to move the cookie checking function into ajaxSetup's beforeSend method. A fully working example, using Jquery >= 1.5.1 and the $.cookie plugin:

I found I also had to use the ensure_csrf_cookie() decorator on the view used for the AJAX request in order for the token cookie to actually be included, regardless of whether I put {% csrf_token %} in the AJAX form template. I'm not sure why that is the case, but the docs imply this might be the expected behavior:

Warning
If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie().

This is probably more of a bug than an optimization, but since it's not really part of the Django code, I just labeled it as an optimization.

"If your browser does not yet have the CSRF cookie for your site and you did not include {% csrf_token %} somewhere in the template rendered on full page load, the following will result in csrftoken being undefined:"

is addressed by the warning you mention later:

"If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie()."

Does including ensure_csrf_cookie() on the first (non-AJAX) view not address the problem?