Error :Forbidden (CSRF token missing or incorrect.) while using django rest framework

Error :Forbidden (CSRF token missing or incorrect.) while using django rest framework

我在我的学习项目中使用 django rest framework.I 得到错误 403 Forbidden (CSRF token missing or incorrect, when I try to save using the POST method. 这是我的代码 html

<form id = "product_form" method = "post">
    {% csrf_token %}
    <input type = "hidden" name = "id" id = "id">
    <p>Назвние:<input name = "name" id = "name"></p>
    <p><input type = "reset" value = "Oчистить"></p>
    <input type = "submit" value = "Сохранить">
</form>

这是我的代码 js:

let productUpdater = new XMLHttpRequest();
productUpdater.addEventListener('readystatechange', () => {

        if (productUpdater.readyState == 4) {
            if ((productUpdater.status == 200) || (productUpdater.status == 201)) {
                listLoad();
                name.form.reset();
                id.value = '';
            } else {
                window.alert(productUpdater.statusText)
            }
        }
    }
);


name.form.addEventListener('submit', (evt) => {
    evt.preventDefault();
    // let vid = id.value, url, method;
    let vid = id.value;
    if (vid) {
        url = 'http://127.0.0.1:8000/books/api_category/' + vid + '/';
        method = 'PUT';
    } else {
        url = 'http://127.0.0.1:8000/books/api_category/';
        method = 'POST';
    }
    let data = JSON.stringify({id: vid,nameCategory: name.value});
    productUpdater.open(method, url, true);
    productUpdater.setRequestHeader('Content-Type', 'application/json');
    productUpdater.send(data);
})

这是我的 views.py:

@api_view(['GET', 'POST'])
def api_products(request):
    if request.method == 'GET':
        productsAll = CategoryMaskarad.objects.all()
        serializer = CategorySerializer(productsAll, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        serializer = CategorySerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def api_rubric_detail(request, pk):
    product = CategoryMaskarad.objects.get(pk=pk)
    if request.method == 'GET':
        serializer = CategorySerializer(product)
        return Response(serializer.data)
    elif request.method == 'PUT' or request.method == 'PATCH':
        serializer = CategorySerializer(product, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        product.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

这是我的 urls.py:

 path('api_category/<int:pk>/', api_rubric_detail),
 path('api_products/', api_products),
 path('api/drf-auth/', include('rest_framework.urls'))

我添加了最后一个路径并登录。在api界面中可以使用post方法添加到api,但是在js的帮助下我的 html 我不能加 data.Help 我,拜托

将表单中的数据传递给 django rest 框架时,您不会在表单前添加 csrf_token 标记,而是在发送 api 时将其作为 header post 在您的端点上。 在

之后添加这一行

尝试将此函数添加到您的代码中以获取 csrftoken 的值

let 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 = cookies[i].trim();
            if(cookie.substring(0, name.length+1)===(name+'=')){
              cookieValue = decodeURIComponent(cookie.substring(name.length+1));
              break;
            }
          }
        }
        return cookieValue;
      }
      
      

然后更改您在 x-csrf-token 中使用的值并使其成为

productUpdater.setRequestHeader('Content-Type', 'application/json');

productUpdater.setRequestHeader('X-CSRF-Token', getCookie("csrftoken"));

我有这个选项。他被work.I添加到js文件中:

name.form.addEventListener('submit', (evt) => {
    evt.preventDefault();
    // let vid = id.value, url, method;
    let vid = id.value, url, method;
    if (vid) {
        url = 'http://127.0.0.1:8000/books/api_category/' + vid + '/';
        method = 'PUT';
    } else {
        url = 'http://127.0.0.1:8000/books/api_category/';
        method = 'POST';
    }
    let data = JSON.stringify({id: vid, nameCategory: name.value});
    productUpdater.open(method, url, true);
    productUpdater.setRequestHeader('Content-Type', 'application/json');
    productUpdater.setRequestHeader('X-CSRFToken', csrftoken);
    productUpdater.send(data);
})

我添加到 html 文件:

<script>
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
</script>