Django 使用 CSRF 令牌向 views.py 发送 POST 请求,然后重定向页面

Posted

技术标签:

【中文标题】Django 使用 CSRF 令牌向 views.py 发送 POST 请求,然后重定向页面【英文标题】:Django send POST request to views.py with CSRF token, then redirect page 【发布时间】:2021-01-11 04:43:10 【问题描述】:

我最初对我的视图进行了 AJAX 调用,然后我意识到我不能return render(request, 'my/new/template.html, context)

所以我遇到了这个相关的问题,这导致了我在下面展示的内容:Redirect to new page after receiving data from javascript

但是我无法让 CSRF 令牌工作,它给了我一个 403 错误。附带说明一下,我也使用 shell_plus 来使用安全连接,但我认为这不会导致问题。

这是我对视图函数的调用:

submitForm.addEventListener('submit', function (e) 

    const form = new FormData(e.target);
    // const csrf_token = form.get("csrfmiddlewaretoken");
    // instead using var csrf_token =  csrf_token  in template
    e.preventDefault()
    instance.requestPaymentMethod(function (err, payload) 
      var url = '/shop/payment/';
      var newForm = '<form action="' + url + '" method="post">';
      newForm += '<input type="hidden" name="csrf_token" value="' + csrf_token +'" />'
      newForm += '<input type="hidden" name="paymentMethodNonce" value="' + payload.nonce + '" />'
      newForm += '<input type="hidden" name="orderTotal" value="' + order_total + '" />'
      newForm += '<input type="hidden" name="address" value="' + $('#address-select').val() + '" />
      newForm += '<input type="hidden" name="first-name" value="' + form.get("first-name") + '" />'
      newForm += '<input type="hidden" name="last-name" value="' + form.get("last-name") + '" />'
      newForm += '</form>'
      var form_element = $(newForm);
      $('body').append(form_element);
      form_element.submit();
    );

我之前使用 ajax 的尝试看起来像这样:

$.ajax(
        type: 'POST',
        url: '/shop/payment/',
        headers:  "X-CSRFToken": csrf_token ,
        data: 
            'paymentMethodNonce': payload.nonce,
            'orderTotal': order_total,
            'address': $('#address-select').val(),
            'first-name': form.get("first-name"),
            'last-name': form.get("last-name")
        
).done(function (result) 
     console.log(result.result)
    // WON'T REDIRECT
);

【问题讨论】:

【参考方案1】:

我通过使用带有 method="post" 的常规表单解决了这个问题:

<form id="braintree-submit-form" method="post" action="% url 'shop:payment' %">
% csrf_token %
# added any inputs I could get from the template here, for example #
<input type="text" name="first-name" class="form-control" value=" request.user.first_name" required />
# ... #

我仍然需要添加一些表单输入,我只能通过 javascript 访问其值,但我最终得到了一个更短且更简单的函数。原因是这是Braintree's Dropin UI的实现。

submitForm.addEventListener('submit', function (e) 

    e.preventDefault()

    instance.requestPaymentMethod(function (err, payload) 

        var nonceInput = document.createElement("input")
        nonceInput.setAttribute('name', 'paymentMethodNonce')
        nonceInput.setAttribute('value', payload.nonce)
        nonceInput.setAttribute('type', 'hidden')
        submitForm.appendChild(nonceInput)

        var addrInput = document.createElement("input")
        addrInput.setAttribute('name', 'address')
        addrInput.setAttribute('value', $('#address-select').val())
        addrInput.setAttribute('type', 'hidden')
        submitForm.appendChild(addrInput)

        submitForm.submit()
    )

【讨论】:

以上是关于Django 使用 CSRF 令牌向 views.py 发送 POST 请求,然后重定向页面的主要内容,如果未能解决你的问题,请参考以下文章

如何以及在何处生成 CSRF 令牌以通​​过 REST API 向 Django 应用程序发出请求?

如何使用 Django 和 AngularJS 创建 POST 请求(包括 CSRF 令牌)

Django - 403 Forbidden - CSRF 令牌丢失或不正确

Django CSRF 令牌错误或缺少 Ajax POST 请求

Angular2 和 Django:CSRF 令牌头痛

CSRF 令牌丢失或不正确。 Django + AngularJS