Johanna
Johanna

Reputation: 1353

Django - jquery : populate combobox based on selection of another combobox

I am quite new to Django and jquery stuff. I am trying to populate a comboBox (ChoiceField in Django) based ont the choice selected in another comboBox (without reloading the page).

I can't find any simple example of such a basic application of ajax.

For now I'm call the following ajax function when I select an item from the first dropdown list.

function get_asset_from_type(){
        var type_asset = $("#id_type").val();
        var data = {type_asset:type_asset};
        var args = {type:"POST", url:"/asset/etatType/", data:data};
        $.ajax(args);

        alert(type_asset);

        return false;
};

It alerts the right type but gives a 403 error on the given url. Weird thing is this url works the first time I load the page. I don't understand what's going on..

EDIT: 403 error seems to be gone, remains the initial question :)

Upvotes: 2

Views: 2308

Answers (1)

Chris Pickett
Chris Pickett

Reputation: 2822

I think you're running up against a CSRF problem. As Django by default blocks POST requests that do not have a CSRF Token with a 403. There are a couple ways to deal with this in JS. One is to pull the value out of the cookie, the code to do that can be found here: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

or you can do it by passing the CSRF_TOKEN in with the javascript script tag:

<script src='myjavascript.js?CSRF_TOKEN={{ csrf_token }}'></script>

Note that it's using a double braket, instead of {%%}. This gets the value of the token, instead of the form input.

function getOptionsFromScriptSrc() {
    // Get last script tag in parsed DOM.
    // Due to the way html pages are parsed, 
    // the last one is always the one being loaded.

    var options = {}
    var js_src = $('script').last().attr('src');

    if(js_src.match(/\?/)) {
        var options_list = js_src.split('?')[1].split('&');
        for(var i = 0; i < options_list.length; i++) {
            var tmp = options_list[i].split('=');
            options[$.trim(tmp[0])] = $.trim(tmp[1]);
        }
    }

    return options;
}

function get_asset_from_type(){
    var options = getOptionsFromScriptSrc();
    var type_asset = $("#id_type").val();
    var data = {type_asset: type_asset, csrfmiddlewaretoken: options['CSRF_TOKEN']};
    var args = {type:"POST", url:"/asset/etatType/", data:data};
    $.ajax(args);

    alert(type_asset);

    return false;
};

I haven't, of course, tested this code, but I have used this method before and it works pretty well.


To the main problem of populating a select box, you need to specify a callback for your ajax post, and then deal with the data returned from your server:

function get_asset_from_type(){
    var options = getOptionsFromScriptSrc();
    var type_asset = $("#id_type").val();
    var post_data = {type_asset: type_asset, csrfmiddlewaretoken: options['CSRF_TOKEN']};

    $.post('/asset/etatType/', post_data, function(data){
        // Assuming server is going to respond with the html of the options, eg: <option value="1">One</option><option value="2">Two</option>...
        $('#id_ofmyselectbox').append(data);
    }); 
};

Upvotes: 2

Related Questions