Forbidden (CSRF cookie not set.) in Django jQuery POST

Welcome to Programming Tutorial official website. Today - we are going to cover how to solve / find the solution of this error Forbidden (CSRF cookie not set.) in Django jQuery POST on this date .

I have a Django 3 application with jQuery Ajax posts on bootstrap modals. There are few buttons that do not have any form but uses post to call certain urls.

All the Django methods are implemented as stated here: https://docs.djangoproject.com/en/3.0/ref/csrf/ All the headers are sent properly.

The page and and functionality works fine when user has logged in and also after user has logged out.

However the Ajax calls return the error response as Forbidden (CSRF cookie not set.), when visiting the site first time and in Incognito mode when not logged in. Once user logs in the issue gets resolved, even after the user logs out.

Please guide as to what may be the probable reason.

Edit: As requested in comments, PFB one of the many Ajax calls.

<script>
        $('.likelink').on("click", function (event){
            event.preventDefault();
            var postid = $(this).attr("data-catid");
            $.ajax({
                type: 'POST',
                url: "{% url 'like_post' %}",
                data: {"post_id": postid},
                success: function (response){
                    if(response["valid"]){
                        alert("Yeah!!! You Liked the post :)");
                        $('#likelinkid'+postid).remove();
                    }
                    else{
                        alert("Kindly login to Like!!!");
                    }
                },
                error: function (response){
                    alert(response["responseJSON"]["error"]);
                }
            });
            });
</script>

Similarly there are multiple scripts lined to various anchor tags. The above script works fine when user is logged in and after the user logs out, as mentioned in the question.

Edit 2: Just for reference, I am writing the csrf related codes used as per Django documentation:

<script type="text/javascript">
        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 = cookies[i].trim();
                    // 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);
                }
            }
        });
</script>

Apart from the above, I have also tried using the view decorators @requires_csrf_token and @ensure_csrf_cookie but that didn’t solve the above issue.

Answer

This issue is resolved by moving the jQuery CDN reference from the child template to the base template and replacing the slim jQuery reference of BootStrap.

The earlier slim jQuery reference by Bootstrap in base template was causing an overlap issue with the minified jQuery referenced in the child template. I had used it as such in a hope to have better performance of webpages where full jQuery would not be needed, but it didn’t help.

So when using Bootstrap, make sure you have only one jQuery referenced in extending templates and preferably before other Bootstrap references.