Я делаю запрос POST, используя Axios в своем JS-коде, чтобы отправить некоторую информацию на мой локальный сервер Django. У меня есть {% csrf_token %} в форме html-кода, но я не знаю, как отправить токен csrf с помощью Axios.
Я получаю эту ошибку в терминале: «Запрещено (токен CSRF отсутствует или неверен.): /api/scoring/submit_score_details».
Как мне правильно вставить токен csrf в мой пост axios? Прямо сейчас я не думаю, что JS может читать {{ csrf_token }}, как у меня. Я искал Stack, но кажется, что большинство людей используют jQuery или какой-либо другой тип JS.
Чтобы сэкономить место, я не стал публиковать переменные в полезной нагрузке, но все они просто строки.
Я могу избавиться от ошибки, если поставлю @csrf_exempt над моей функцией в файле views.py.
{
let payload = {
"csrfmiddlewaretoken": "{{ csrf_token }}",
"math_problem": problem,
"user_answer": userInput,
"true_answer": correctAnswer,
"question_status": questionStatus,
}
console.info(payload);
axios.post('../api/scoring/submit_score_details', payload)
}
<div class = "col text-center">
<button id = "start" type = "button" class = "btn btn-primary btn-lg">
New Problem
</button>
<p id = "math_problem"></p>
<form id = "inputForm" method = "POST">
{% csrf_token %}
<input id = "user_input" autocomplete = "off" class = "form-control form-control-lg" type = "text" placeholder = "Type your answer here">
<input id = "correct_answer" type = "hidden">
</form>
<br>
<button id = "result_check" type = "button" class = "btn btn-primary btn-lg">Check</button>
<script src = {% static 'js/game_logic.js' %}></script>
</div>
{
let payload = {
"csrfmiddlewaretoken": "{{ csrf_token }}",
"math_problem": problem,
"user_answer": userInput,
"true_answer": correctAnswer,
"question_status": questionStatus,
}
console.info(payload);
axios.post('../api/scoring/submit_score_details', payload)
}
<form id = "inputForm" method = "POST">
{% csrf_token %}
<input id = "user_input" autocomplete = "off" class = "form-control form-control-lg" type = "text" placeholder = "Type your answer here">
<input id = "correct_answer" type = "hidden">
</form>
Возможно ли, что ваш код Axios создается до того, как csrf_token отображается на странице (по шаблону django)?
Попробуйте что-то подобное в начале кода js:
var my_token = '{{ csrf_token }}';
затем, когда вы вызываете Axios, отправьте это значение вместо рендеринга {{ csrf_token }} в строке, так что-то вроде этого:
{
let payload = {
"csrfmiddlewaretoken": my_token,
"math_problem": problem,
"user_answer": userInput,
"true_answer": correctAnswer,
"question_status": questionStatus,
}
console.info(payload);
axios.post('../api/scoring/submit_score_details', payload)
}
Мне также любопытно, видели ли вы, что ваш токен csrf печатается на консоли в коде, который вы показали (из распечатки полезной нагрузки), поскольку это указывало бы, был ли он отправлен или нет.
Если отправлялся csrf_token, возможно, с приложением возникла какая-то другая проблема, но как только у вас есть токен в my_token, вы можете распечатать его и убедиться, что он настроен правильно, и работать оттуда.
Используете ли вы Django для вывода вывода (это то, что переводит {{ csrf_token }} в требуемую строку? Вот почему я предложил загрузить токен в свою собственную переменную, чтобы его можно было перепроверить. Если вы не используя django для рендеринга html, тогда как вы его настроили?
Да, HTML отображается с помощью Django. Мой JS также находится в моем проекте Django, внутри моей статической папки.
Хм, странно, что он не конвертирует для вас {{ csrf_token }}. Внутри формы он использует {% csrf_token %} для инициализации значения (и делает его доступным для JS), но возможно ли, что ваш код генерируется до отображения формы - вы упомянули, что это в статическом коде - возможно, переместите Axios позвоните в свою форму (временно) после {% csrf_token %}, чтобы увидеть, делает ли это ее счастливее - я полагаю, что столкнулся с подобной проблемой некоторое время назад, поэтому я предложил создать переменную "раньше" в вашем JS. Вы также можете установить точку останова, чтобы проверить ее значение.
что именно я должен добавить в свой HTML из моего JS-файла? JS POST использует множество переменных и других элементов, которые являются частью файла JS.
Похоже, вы можете просто поместить вызов Axios (как показано выше, пусть полезная нагрузка... axios post...) в свой HTML. Вам, очевидно, нужно будет поместить его в тег <script>, но таким образом вы сможете сделать вызов axios и увидеть токен csrf, поскольку токен должен быть действительным в вашей форме. Если это поможет, я много раз использовал подобные методы для рендеринга токена, поэтому я знаю, что это работает. Вы можете использовать фиктивные значения для параметров полезной нагрузки, если вам нужно во время этого теста.
Хорошо, оглядываясь назад на обсуждение, я думаю, что могу знать, что здесь происходит...
Возможно, вы добавили "{{ csrf_token }}" в свой JS (где-то хранится в статическом коде) - это не сработает, поскольку, как вы указали, JS ничего не знает о шаблонах django.
Это можно сделать, изменив код JS так, чтобы он использовал переменную JS (например, my_token).
{
let payload = {
"csrfmiddlewaretoken": my_token, // populated later within form
"math_problem": problem,
"user_answer": userInput,
"true_answer": correctAnswer,
"question_status": questionStatus,
}
console.info(payload);
axios.post('../api/scoring/submit_score_details', payload)
}
Это значение my_token будет предоставлено позже (в вашей форме) перед вызовом Axios. Для этого добавьте в форму:
<script>
// This will be rendered by Django to get the actual string into my_token
var my_token = "{{ csrf_token }}";
</script>
Затем, когда ваш вызов Axios будет выполнен (нажатием кнопки, таймера или чего-то еще), эта глобальная переменная должна быть правильно установлена и использована.
Поместить это до или после моего JS-скрипта в нижней части моего div?
Вы можете поместить его прямо под {% csrf_token %}, чтобы было понятно, что происходит, если хотите.
Получил новую информацию! Я забыл удалить "var my_token" {{csrf_token}} в верхней части JS. Я удалил его, и теперь в консоли выводится строка токена.
В итоге я погуглил и спросил у друга. Мы придумали решение.
Нам пришлось добавить две строки кода, чтобы все заработало:
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';
Мы также избавились от переменной «полезная нагрузка» и просто поместили все в код Axios.
{
axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';
axios.post('../api/scoring/submit_score_details', {
"math_problem": problem,
"user_answer": userInput,
"true_answer": correctAnswer,
"question_status": questionStatus,
});
console.info(`Problem:${problem},
User Input: ${userInput},
Correct Answer: ${correctAnswer},
Question Status: ${questionStatus}`
);
};
<div class = "col text-center">
<button id = "new_problem_button" type = "button" class = "btn btn-primary btn-lg">
New Problem
</button>
<p id = "math_problem"></p>
<form id = "inputForm" method = "POST">
{% csrf_token %}
<input id = "user_input" autocomplete = "off" class = "form-control form-control-lg" type = "text" placeholder = "Type your answer here">
<input id = "correct_answer" type = "hidden">
</form>
<br>
<button id = "result_check" type = "button" class = "btn btn-primary btn-lg">Check</button>
<script src = {% static 'js/game_logic.js' %}></script>
</div>
Вот ссылка, которая нам помогла.
Попробовал ваш метод, но без кубиков. Я получаю ту же ошибку. Я не думаю, что JS знает, что такое {{ csrf_token }}. Токен не выводится в консоли. Вот как выглядит пример полезной нагрузки: csrfmiddlewaretoken: "{{ csrf_token }}" math_problem: "4 x 1" question_status: "correct" true_answer: "4" user_answer: "4"