【问题标题】:django csrf error in fetch api ajax获取 api ajax 中的 django csrf 错误
【发布时间】:2026-01-07 09:20:02
【问题描述】:

我想在django框架下用es6 fetch api替换我的jquery ajax代码 这是我的 jquery ajax 代码

var csrf = $('meta[name="csrf_token"]').attr('value')
        //comment vote
        $("#comment_box").on('click', "a.vote-up", function() {
            var voteID = parseInt(this.id.split("-")[1]);
            $.ajax({
                url : "/vote_json/",
                type : "POST",
                dataType: "json",
                data : {
                    "comment_id": voteID,
                    "vote": $('#up-' + voteID).attr('value'),
                    csrfmiddlewaretoken: csrf
                },
                success : function(json) {
                    $('#up-' + voteID).html('<i class="chevron vote up icon"></i>' + json.vote);
                    $('#up-' + voteID).popup({
                        position    : 'top center',
                        content     : json.msg,
                        on          : 'manual'
                    });
                    $('#up-' + voteID).popup('show');
                    setTimeout(function (){$('#up-' + voteID).popup('hide');}, 3000);
                },
                error : function(xhr,errmsg,err) {
                    alert(xhr.status + ": " + xhr.responseText);
                }
            });
            return false;
        });

这段代码是es6 fetch api

let csrf = document.querySelector('meta[name="csrf_token"]').getAttribute('value');
    //comment vote
    [].forEach.call(document.querySelectorAll('a.vote-up'), function (voteup) {
        voteup.addEventListener('click', function () {
            let voteid = parseInt(voteid.id.split("-")[1]);
            fetch('/vote_json/', {
                method: 'POST',
                body: JSON.stringify({
                    comment_id: voteid,
                    vote: document.querySelector('#up-' + voteid).getAttribute('value'),
                    csrfmiddlewaretoken: csrf
                })
            }).then(function (response) {
                return response.json();
            }).then(function (json) {
                document.querySelector('#up-' + voteid).innerHTML = '<i class="chevron vote up icon"></i>' + json.vote
                document.querySelector('#up-' + voteid.popup({
                    position    : 'top center',
                    content     : json.msg,
                    on          : 'manual'
                }),
                document.querySelector('#up-' + voteid).popup('show'),
                setTimeout(function () {
                    document.querySelector('#up-' + voteid).popup('hide'), 3000
                })
                )
            })
        })
    }

这段代码是我在 django 中的观点

def vote(request):
    comment_pk    = request.POST.get('comment_id')
    vote          = request.POST.get('vote')
    comment       = Comment.objects.get(pk=comment_pk)
    if vote == 'true':
        comment.up += 1
        comment.save()
        response_dict = dict(vote=comment.up)
    elif vote == 'false':
        comment.down -= 1
        comment.save()
        response_dict = dict(vote=comment.down)
    return HttpResponse(json.dumps(response_dict), content_type='application/javascript')

问题是在 jquery 代码中一切正常,但在 es6 django 中响应“CSRF 验证失败。请求中止。”我在没有正文块的 Get 方法中测试了 fetch ajax 代码,并且此模式下的另一个 django 视图工作正常

【问题讨论】:

    标签: django ecmascript-6 csrf fetch


    【解决方案1】:

    here复制粘贴。

    解决方案是在 getCookie() 方法中。

    fetch("/graphql", {
            method: "POST",
            credentials: "same-origin",
            headers: {
              "X-CSRFToken": getCookie("csrftoken"),
              "Accept": "application/json",
              'Content-Type': 'application/json'
            },
            body:JSON.stringify(query)
          })
    

    当然,方法必须在同一页面上。取自 Django 文档。

    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;
    }
    

    【讨论】: