Django:AJAX + CSRF POST给出了403

时间:2015-04-09 22:57:43

标签: javascript django django-templates django-staticfiles

我有一个简单的代码,我在POST中对包含CSRF令牌的URL进行Django调用。当我将javascript代码粘贴到<script>代码中的模板中时,它可以正常工作,但是只要我将代码移动到静态文件,我就会收到HTTP 403响应。这很奇怪!

这是代码:

$(document).ready(function() {
    $(".like-button").click(function(event) {
        $.ajax({
            url: <relative path of URL>,
            type: "POST",
            data: {
                csrfmiddlewaretoken: "{{ csrf_token }}",
                // other data items
            },
            success: function(data, textStatus, jqXHR) {},
            error: function(jqXHR, textStatus, errorThrown) {}
        });
        // other javascript code to toggle like button class
    });
});

以下是我在Django模板中包含静态文件的方法:

{% block javascript %}
{% load static %}
<script type="text/javascript" src="{% static 'app/app.js' %}"></script>
{% endblock %}

该文件位于静态目录中:

app
├── static
│   └── app
│       └── app.js

和静态设置是:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

注意,我的设置中还没有STATICFILE_DIRS。我可以验证文件是否正在加载和执行,因为console.log()语句完全正常。但是,我在POST上收到HTTP 403请求。

2 个答案:

答案 0 :(得分:2)

当您直接使用标记时,django会处理模板并用正确的标记替换csrfmiddlewaretoken: "{{ csrf_token }}"

现在,当您使用静态文件时,该变量不会被替换。 要添加令牌,您应该配置django文档描述的ajax调用:https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#ajax

      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]);
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
              cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
              break;
            }
          }
        }
        return cookieValue;
      }
      var csrftoken = getCookie('csrftoken');
      $.ajaxSetup({
        beforeSend: function(xhr, settings) {
          xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      });

答案 1 :(得分:0)

来自Django文档:

NOTE:
The CSRF token is also present in the DOM, but only if explicitly
included using csrf_token in a template. The cookie contains the
canonical token; the CsrfViewMiddleware will prefer the cookie to the
token in the DOM. Regardless, you’re guaranteed to have the cookie if
the token is present in the DOM, so you should use the cookie!

jQuery cookie插件:

var csrftoken = $.cookie('csrftoken');

https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/

任何未直接在模板上呈现的静态文件都无法使用django的模板引擎。您需要使用csrf cookie。

在运行时检查你的javascript,你会注意到模板变量是一个空字符串。