6

In django 1.3 you now have to use csrf even with ajax. I use jquery and I now want to add the csrf token to the $.post. How can i do this? I am not very skilled in jquery so it would be nice with a good description.

It is a rating app and the post is send when a star is clicked. I have seen the django docs but do not understand what to do in my situation. My code is below:

$(function() {  
            $("#avg").children().not(":input").hide();
            $("#rating-widget").children().not("select").hide();    

            $caption = $("<span/>");

            $("#avg").stars({captionEl: $caption});
            $("#rating-widget").stars({
                inputType: "select",
                cancelShow: false,
                captionEl: $caption,
                callback: function(ui, type, value){
-------------->     $.post($("#rating-widget").attr("action"), {score: value}, function(data){

                    });
                }
            });
               $caption.appendTo("#rating-widget");

});

It should be said that the javascript is not in a template but in a static file. Would it be best to put it in a template so I could use {{ csrf_token }}

Thanks in advance!

tmpethick
  • 135
  • 3
  • 9

3 Answers3

7

Place this code before your function. It will take care of CSRF.

$('html').ajaxSend(function(event, xhr, settings) {
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
        // Only send the token to relative URLs i.e. locally.
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
    }
});
  • 1
    I just found an [edited version](http://stackoverflow.com/questions/5100539/django-csrf-check-failing-with-an-ajax-post-request) were they use ajaxSetup instead. It work for me :) Didn't know it was that easy! Thanks! – tmpethick Jun 02 '11 at 08:43
3

In the django documentation you can find a simple description on how to automatically include the csrf token in each ajax request!

Bernhard Vallant
  • 49,468
  • 20
  • 120
  • 148
  • As said in the question: I already checked that place out, but couldn't understand it and fit it into my code. But thanks anyhow for the attempt to help :) – tmpethick Jun 01 '11 at 08:12
  • Didn't work for me until I removed the if statements in ajaxSetup, and just had xhr.setRequestHeader("X-CSRFToken", csrftoken); – bozdoz Jan 11 '13 at 21:52
1

You don't have to use a form! Just create a new url that is bound to a function that "stars" posts. For example

(r'^myapp/star-post/(?P<post_id>.*)/$','myapp.views.myview')

Therefore, if you send a request to that url, it will find the post in your database, change the field to "starred" and return a response to ajax.

Then you can have a callback function on success that will change the CSS accordingly (fill in the star, or etc). This way, you don't have to worry about CSRF.

But you may ask, well what about cross-site-scripting attacks! Well, if you are using user authentication with cookie validation, you shouldn't have to worry about that! Aaaand you're good to go.

systemizer
  • 355
  • 2
  • 6
  • This is exactly what i have done. Problem is I have to store it in the database and it prompt me for a csrf token.. The problem came after i updated fra 1.2 to 1.3 where you have use csrf tokens - even with ajax. i Would like to know how to include the csrf token in the request send with ajax – tmpethick Jun 01 '11 at 08:09
  • @tmpethick Even with the csrf_exempt decorator? from django.views.decorators.csrf import csrf_exempt – systemizer Jun 03 '11 at 00:09