首页 > 解决方案 > Django - POST 方法不适用于在模板中的 FOR 循环中创建的表单

问题描述

我在模板中使用 for 循环来创建多个method="post"与 Ajax 一起使用的表单。但只有第一个元素的表单items_list可以正常工作,其余的根本不工作,显示错误 405 0 Method Not Allowed。我认为他们都应该以同样的方式工作。只是想知道这个问题是由 for 循环还是其他原因引起的。

cart_items.html:

<script>
    $(document).ready(function () {
        $("#remove").click(function (event) {
            event.preventDefault();
            $.ajax({
                url: '{% url "cart:remove_from_cart" %}',
                type: "POST",
                dataType: 'json',
                data: {bookID: $('#idInput').val()},
                success: function (response_data) {
                    alert('works fine')
                },
                error: function (response_data) {
                    console.log('error occurred');
                }
            });
        });
    });
</script>

{% for book in items_list %}
    <div class="items">
        <p id="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
        <form method="post">
            {% csrf_token %}
            <input id="idInput" value="{{ book.book.id }}" >
            <button id="remove" type="submit"> Remove</button>
        </form>
    </div>
{% endfor %}

下面函数体中的代码仅用于测试。一旦第一种形式起作用,我想问题不是由功能视图引起的。

购物车/views.py:

@csrf_exempt
def remove_books(request):
    cart = Cart.objects.get(user=request.user)
    if request.method == 'POST':
        passed_id = request.POST['bookID']
        secured_id = int(passed_id)
        response_data = {
            'quantity': secured_id
        }
        return JsonResponse(response_data)

标签: django

解决方案


<script>
    $(document).ready(function () {
        $(".remove").click(function (event) {
            // event.preventDefault();  // don't think it should be required with button type=button
            var book_id = $(this).parent().find('.idInput').val(); // find correct input box. 
            var csrf = $('input[name="csrfmiddlewaretoken"]').val(); // get csrf token in variable.
            // there are multiple ways to get csrf token, I personally like this ^^, see https://docs.djangoproject.com/en/2.1/ref/csrf/#ajax for more
            $.ajax({
                url: '{% url "cart:remove_from_cart" %}',
                type: "POST",
                dataType: 'json',
                data: {
                    bookID: book_id,
                    csrfmiddlewaretoken: csrf // add csrf token to post data
                },
                success: function (response_data) {
                    alert('works fine')
                },
                error: function (response_data) {
                    console.log('error occurred');
                }
            });
        });
    });
</script>

{% csrf_token %} <!-- It will render a hidden input field with csrf token in it. Keep it outside for loop but in html. No need to render exactly same element multiple times. -->
{% for book in items_list %}
    <div class="items">
        <p class="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
        <form method="post">
            <input class="idInput" value="{{ book.book.id }}" > <!-- use class not id -->
            <button class="remove" type="button"> Remove</button> <!-- you can use button type=button to avoid form submit and hence avoid event.preventDefault(); in js -->
        </form>
    </div>
{% endfor %}

推荐阅读