Ошибка :Forbidden (CSRF токен отсутствует или неверен.) при использовании django rest framework
Я использую в своем учебном проекте django rest framework.Я получаю ошибку 403 Forbidden (CSRF token missing or incorrect, когда я пытаюсь сохранить с помощью метода POST. Вот мой код 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 интерфейсе появилась возможность добавлять в api методом post, но с помощью js в моем html я не могу добавить данные.Помогите, пожалуйста
при передаче данных из формы в django rest framework, вы не добавляете тег csrf_token перед формами, а передаете его в качестве заголовка при отправке api post на вашу конечную точку. Добавьте эту строку после
productUpdater.setRequestHeader('Content-Type', 'application/json');
productUpdater.setRequestHeader('X-CSRF-Token', 'abcdef');
У меня есть такой вариант. Он работает.Я добавил в 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>