Ajax does not work even though I used csrf_token

I have a web game project using django

first, when I bring user character data using ajax-get method,

it working fine

(function(){
    $("document").ready(function(){

        $get_id = $('#character');

        //?? ??? ? ??? ???? ?? ??? ???? ??
        $user_has_character = $(".data").data("hasCharacter");


        /*****************************
         * when user have character
         * ***************************/
        if($user_has_character=="True"){

            get_gamestart_api_url = '/api/gamestart/data/';

            //?? ?? ??
            $scene = $('#scene');

            $scene.css("background", "url(../static/images/game/loadingBackground.jpg) no-repeat");

        /*****************************
         * 
         * json will get user's character data
         * 
         * **************************/
        $.ajax({

            method:'GET',
            url:get_gamestart_api_url,

        }).done(function(data){
                character = data[0].character[0]
                $get_id.append("<li class='stat'> ??? ???: "+character.nickname+"</li>",
                    "<li class='stat'> ??? ??: "+character.level+"</li>",
                    "<li class='stat'> ??? ??: "+character.job+"</li>",
                    "<li class='stat'> ??? ???: "+character.status.attack_point+"</li>",
                    "<li class='stat'> ??? ???: "+character.status.defence_point+"</li>",
                    "<li class='stat'> ??? ??: "+character.status.health+"</li>",
                    "<li class='stat'> ??? ??: "+character.status.mana+"</li>",
                    );
            });


    }else{
        /*********************
         * When the user does not have a character
         ********************/

    }

});
})();

So, I think $.ajax doesn't have any problem,

and when user doesn't have character, user must create a character

}else{
     /*********************
     * When the user does not have a character
     ********************/

        //form tag will created
        $get_id.append("<form method='post' action='/'> <input name='nickname' type='text' style='border: 1px solid #ff0000;'><input type='submit' class='btn_character'> </form>");

        $btn_character = $(".btn_character");
        console.log($btn_character);

        //when user click create user button
        $btn_character.on("click", function(event){

            //using jQuery
            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;
            }
            var csrftoken = getCookie('csrftoken');

            function csrfSafeMethod(method) {
                //these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
                $.ajaxSetup({
                    beforeSend: function(xhr, settings) {
                        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                            xhr.setRequestHeader("X-CSRFToken", csrftoken);
                    }
                }
            });

            //get input text nickname
            $nickname = $("input[name=nickname]").val();

            $.ajax({
                method:'POST',
                url:'/api/user/characters/',
                data:{
                    nickname:$nickname
                },
            });
        });

    }

even though I used jquery csrf_token, when send $.ajax post, it show error

Forbidden (CSRF token missing or incorrect.): /

but I can't understand what is problem in my code...

Answers 1

  • Assuming this script is inside your HTML and not in an external .js file you can rewrite this:

    $get_id.append("<form method='post' action='/'> <input name='nickname' type='text' style='...'><input type='submit' class='btn_character'> </form>");
    

    to this:

    $get_id.append("<form method='post' action='/'>{% csrf token %} <input name='nickname' type='text' style='...'><input type='submit' class='btn_character'> </form>");
    

    When you POST data to Django, you must post the csrf token along with the other form data. That's the cause of your error.

    The csrf_token is generated by the server and is injected as a hidden input inside your form.

    If this script lives in its own file and you load it in your HTML as: <script src="path/to/the/script.js"></script> then you have 2 options:

    1. Instead of loading it this way, {% include %} it, so that Django can render this value. For example, you should save it (including the <script></script> tags!) as game_script.html. Then in your HTML template inject it like this:

      <body> staf here and ... ... at the bottom {% include 'game_script.html' %} </body>

    2. The other option is before creating the form dynamically, make another AJAX request to the server to get a csrf token and once you get it, then create the form (inside the append) including the csrf_token you received.

    The easiest solution, however, is not to make a POST request to Django but a GET one. Simply, change the method='post' to method='get' and you are good to go. No csrf tokens need it.


Related Articles