Django - 未定义csrf标记

时间:2017-02-22 00:14:50

标签: javascript django django-csrf

此代码应该做的是让用户点击他们的描述并能够编辑它。我有弹出模式,但保存按钮不会保存数据并产生以下错误:

Uncaught ReferenceError: csrftoken is not defined
at HTMLButtonElement.<anonymous> (modalShortListDescription.js:6)
at HTMLButtonElement.dispatch (jquery.min.js:3)
at HTMLButtonElement.r.handle (jquery.min.js:3)

这里是调用模态的地方:

<div class="tab-content col-xs-12">
{% for list in lists %}
    <input type="hidden" id="idList" id_list="{{list.id}}">
    {% if forloop.first and not createTabActive %}
    <div role="tabpanel" class="tab-pane fade active in" id="list{{list.id}}">
    {% else %}
    <div role="tabpanel" class="tab-pane fade" id="list{{list.id}}">
    {% endif %}
        <div class="content col-xs-12">
            <div class="form-horizontal sort-by col-xs-12">
                <h3>Description</h3>
                    {% if list.description %}
                        <a href="#" data-toggle="modal" data-target="#modalDescription{{list.id}}" id="editDescription">{{list.description}}</a>
                    {% else %}
                        <a href="#" data-toggle="modal" data-target="#modalDescription{{list.id}}">None</a>
                    {% endif %}
                {% include "layout/popUp/modal-short-list-description.html" %}
                </div>

这是模态本身:

<div class="modal fade" id="modalDescription{{list.id}}" role="dialog">
  <div class="modal-dialog">
    <form class="form-horizontal" action="{% url 'update-list-description' %}" method="post">
    {% csrf_token %}
    <!-- Modal content-->
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">&times;</button>
        <h4 class="modal-title">Description</h4>
      </div>
      <div class="modal-body modal-body-exper modal-body-value modal-body-t">
          <div class="lineEnterValue lineTeamSize lineTitle">
              <div class="form-group {% if form.description.errors %} has-error{% elif form.is_bound %} has-success{% endif %}">
                        <div class="col-sm-10">
                            <textarea name="{{ form.description.html_name }}" class="form-control" id="{{ form.description.id_for_label }}" rows="5" style="margin: 0px; height: 90px; width: 455px;"></textarea>
                        </div>
                        {% if form.description.errors %}
                        <ul class="col-sm-10 col-sm-offset-2 error-list text-danger">
                        {% for error in form.description.errors %}
                            <li>{{ error|escape }}</li>
                        {% endfor %}
                        </ul>
                        {% endif %}
                    </div>
          </div>
      </div>
      <div class="modal-footer modal-footer-value">
        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        <button type="submit" class="btn btn-primary" id="description_save">Save</button>
    </div>
  </div>
</form>
</div>

以下是保存按钮使用的.js:

$(document).ready(function() {
    $("#description_save").click(function() {
        var description = $("#form.description").val();
        var idList = $("#idList").attr("id_list");
        var url = "/bid/update-list-description";
        csrftoken();
        $.ajax({
            type: "POST",
            url: url,
            data: {description : description, idList: idList},
        }).done(function(response){
            $(".modalDescription").modal("hide");
            $(".editDescription").text(description);
        });
    })
})

修改 views.py:

@csrf_protect
def updateListDescription(request):
    checkEmployer(request)
    pageClass="my-short-lists search-for-prospect"

    #shortList = get_object_or_404(List, id = request.POST.get("idList"))
    shortList = request.user.profile.profile_employers.employer_lists.filter(pk=request.POST.get("idList"))

    if request.method =="POST":
        form = ListForm(request.POST)
        if form.is_valid():
            shortList.description = form.cleaned_data["description"]
            shortList.save()
    else:
        form = ListForm()

    return redirect('my-short-lists')

3 个答案:

答案 0 :(得分:0)

AJAX POST不包含csrf_token。添加:

'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()

到$ .ajax数据(连同description和idList)并删除csrftoken()。

答案 1 :(得分:0)

将你的js编辑为

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

$(document).ready(function() {
    $("#description_save").click(function() {
        var description = $("#form.description").val();
        var idList = $("#idList").attr("id_list");
        var url = "/bid/update-list-description";
        var csrftoken = getCookie('csrftoken');
        $.ajax({
            type: "POST",
            url: url,
            data: {description : description,
                   idList: idList,
                   csrfmiddlewaretoken: csrf_token
            },
        }).done(function(response){
            $(".modalDescription").modal("hide");
            $(".editDescription").text(description);
        });
    })
})

答案 2 :(得分:0)

编辑:

我认为问题不仅存在csrftoken,还存在于按钮中:如果按钮调用ajax,则不应该是submit。如果它发布表单,则不应该执行ajax调用。看来你在表单中添加了令牌,但是ajax首先做了他的事......所以第一个答案似乎是有效的。

或者,

您可以在$.ajaxSetup()中为每个ajax调用添加标头。 DOC对此部分进行了解释:

  1. 定义getCookie(name)方法;
  2. 定义var csrftoken = getCookie('csrftoken');;
  3. 使用以下行:
  4. 那是:

    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);
            }
        }
    });
    
    1. 然后您不必更改任何ajax调用。标头附加在每个ajax调用中。
    2. https://docs.djangoproject.com/en/2.0/ref/csrf/,在“Ajax”部分下。

      我使用过这种方法,但它确实有效。