Category Archives: jQuery

Interactive page development with jQuery/Javascript, especially jQuery-UI and Ajax.

Django Form Submission using jQuery and cookies to protect the csrf Token

I recently wrote about how to add csrf protection for jQuery Ajax submissions when using the ‘POST’ method.  We can use a similar method to protect forms while not exposing the csrf token.  When we set  ‘django.middleware.csrf.CsrfViewMiddleware’, in the MIDDLEWARE_CLASSES in ‘’, Django sets a csrf token as a cookie for each web page.  We can use the jQuery ‘.submit()’ method to read the cookie and add a hidden input field to the form prior to submission.  Django will process the form just as if you had included {% csrf_token %} in the form.  The benefit is that it is not easy to read the crsf token because it is stored in a cookie and browsers don’t expose cookies outside of the active page.

First, here is a code example of the simple but vulnerable way to add a csrf token to a Django form.

<form action="/" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Category"/>

Now, we’ll change our form so that we can take advantage of the jQuery ‘.submit()’ method each time this form is submitted.  We are writing this using classes, so that we can write a site-wide ‘$(document).ready(function(){…}’ that takes action on these classes.  As a reminder, one can have more than one ‘$(document).ready(function(){…}’ function.  We use one in a javascript file that defines site-wide behaviors via classes and then one for each specific page that defines page specific behaviors.  Here is the updated form that does not expose the csrf token and makes use of site-wide classes.

<form action="/" method="post" class="YPForm">
    {{ form.as_p }}
    <input type="submit" value="Category" class="YPButton"/>

Now we can go to the site-wide javascript file and define the event handler that fires when forms of this class are submitted.  Please note that this code has a dependency on the ‘jquery.cookie.js’ library.  Also, please note that I am using C-style indentation to make everything fit onto this page.

function submitYPForm() {
    var csrfToken = "<input type='hidden' name='csrfmiddlewaretoken' 
                           value='" + $.cookie('csrftoken') + "' />"

    // Enables setting csrf cookie into Ajax 'POST' header
    $.ajaxSetup({ beforeSend:setCookieInHeader });

    // Enables jQuery UI events (for CSS) on the buttons on the site

    // Submit event handler

I would recommend doing everything that really matters with https, but short of that, this is quite a bit more secure than exposing the the csrf token on your webpage.  Enjoy!

jQuery Ajax Cross Site Request Forgery Tokens with Python/Django

The Django tutorial demonstrates how to add a csrf token to a form, but how do we do it for Ajax?  The Django documentation explains how to do this. How does it work?  First, make sure that you set ‘django.middleware.csrf.CsrfViewMiddleware’, in your MIDDLEWARE_CLASSES in  This will cause Django to set a csrf token as a cookie for each web page.  Other sites cannot access the cookie, but your page can.

One other thing stands out right away is this section.

In any template that uses a POST form, use the csrf_token tag inside the <form> element if the form is for an internal URL, e.g.:

<form action="." method="post">{% csrf_token %}

This should not be done for POST forms that target external URLs, since that would cause the CSRF token to be leaked, leading to a vulnerability.

We’ll get to proper form csrf protection, but first, let’s get it working for Ajax.  I took the code samples from the documentation and modified the code so that it will automatically get called for any Ajax submission.  I include this javascript file on any page that uses Ajax.  It is important to note that even though this file has a $(document).ready(function(){…}, you can include other javascript files with the same function.  They’ll all get called in order (assuming they download quickly enough).  Also, I am using C-style indentation so that my code sample will fit onto this page.

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 =; // 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
        (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.

function setCookieInHeader (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", $.cookie('csrftoken'));

    $.ajaxSetup({ beforeSend:setCookieInHeader });

(Update: You will need the jQuery cookie plugin for the $.cookie() function to work.)

Now that we’ve got csrf protection for Ajax submissions, we’ll have to work on proper form submissions next.


jQuery UI Autocomplete with Python/Django

I have been developing a website using Python/Django and the HTML 5 / Javascript / JQuery documentation is lacking.  I wanted to make a text widget that uses Ajax to query the database for suggestions, i.e. autocomplete.  After a lot of searching, here is what I figured out.  In short: JQuery UI.

I am using a class based Django form in my to create the form with the autocomplete text entry on the index page of the site.  (I am going to have to do some C-style indentation to get this Python code to wrap on my page).

class IndexForm(forms.Form):
    category = forms.CharField(max_length=100,
             (attrs={'placeholder':'Category', 'autofocus':'true'}))

Here is the section from index.html that renders the form (again, I am wrapping lines to fit onto the blog page).

    <form action="/" method="post">
        {% csrf_token %}    <!-- <><><> FIXME -->
        {{ form.as_p }}
        <input type="submit" value="Category"/>
        {% if invalidCategory %}
            <p class ="YPBodyText">There is no match to 
                                       '{{ invalidCategory }}'.</p>    
        {% endif %}

One thing to note is that I am using {% csrf_token %} directly on the webpage.  This is a no-no for front facing pages.  I have a work around for form submission and ajax and will post about that soon.  Please note that you must include jQuery and jQuery UI on your page for the autocomplete to work.  And now we’ll look at index.js for the jQuery UI call.  In our class based form in our, we created a text widget called ‘category’.  It can be found in the DOM as ‘id_category’.

$(document).ready(function() {
    $("#id_category").autocomplete({ source:'SuggestCategory' });

As you can see, the autocomplete will make an ajax call to $URL/SuggestCategory.  Here is the line in our that routes the call to the right view in our

url(r'^SuggestCategory/$', views.SuggestCategory.as_view()),

And finally back to for the class-based view that responds to the Ajax call.  Since the Ajax call has no side effects on the database, it is handled using the GET method.  I wrote an internal method that searches the ‘text’ column of the ‘category’ table in my  If the start of any of these fields matches the submission in ‘starts_with’, we add it to a list, and returned it in JSON format.

class SuggestCategory(generic.View):

    def _get_category_list(self, max_results=0, starts_with=''):
        #import pdb; pdb.set_trace()
        categories = []
        cat_list = []
        if starts_with:
            categories = Categories.objects.filter

        max_len = len(categories)
        if max_results > 0 and max_len > max_results:
            max_len = max_results

        for cat in categories[:max_len]:

        return cat_list

    def get(self, request):
        #import pdb; pdb.set_trace()
        cat_list = self._get_category_list
                   (DEF_AUTO_COMPLETE_RESULTS, request.GET['term'])
        return HttpResponse(json.dumps(cat_list), 
                                 content_type = "application/json")