Vue/reqwest添加CSRF Token及Django POST请求无响应问题排查
我来帮你一步步搞定这两个问题,先从CSRF Token的添加说起,再解决Django视图没响应的问题~
一、在Vue和reqwest中添加CSRF Token
Django默认开启CSRF保护,发送POST请求时必须带上CSRF Token才能通过验证。这个Token通常存在浏览器的csrftoken Cookie里,我们只需要先获取它,再放到请求头里就行。
1. 先写个通用的CSRF Token获取函数
不管用Vue还是reqwest,都可以用这个函数拿到Token:
function getCsrfToken() { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); // 匹配csrftoken的cookie if (cookie.substring(0, 10) === 'csrftoken=') { cookieValue = decodeURIComponent(cookie.substring(10)); break; } } } return cookieValue; }
2. 在reqwest中配置CSRF Token
直接在你的sendData方法里,给reqwest加上请求头配置:
sendData:function () { var self = this; const csrfToken = getCsrfToken(); reqwest({ url: 'http://127.0.0.1:8000/tasks/', method: 'POST', // 一定要明确指定POST方法! headers: { 'X-CSRFToken': csrfToken, 'Content-Type': 'application/json' // 如果发送JSON数据,必须加这个头 }, data: JSON.stringify({ realtimecost: this.realtimecost }), // 把数据转成JSON字符串 success: function(response) { console.log('请求成功啦', response); }, error: function(err) { console.error('请求失败了', err); } }); }
3. Vue全局配置(顺带提下,如果后续用axios的话)
要是你之后改用axios,可以在Vue全局统一配置,不用每个请求都写Token:
import axios from 'axios'; // 自动从cookie取CSRF Token,放到请求头里 axios.defaults.xsrfCookieName = 'csrftoken'; axios.defaults.xsrfHeaderName = 'X-CSRFToken'; // 之后组件里直接用axios.post就自动带Token了
二、解决Django视图POST无响应、print不执行的问题
你的print代码没触发,大概率是请求根本没走到视图函数里,或者被Django的中间件拦截了,常见原因有这几个:
1. 跨域问题
如果Vue运行在另一个端口(比如默认的8080),Django在8000端口,浏览器会先发OPTIONS预请求,如果Django没处理跨域,这个预请求失败后,真正的POST请求根本发不出去。
解决办法:安装django-cors-headers处理跨域:
- 先安装:
pip install django-cors-headers - 在
settings.py里配置:
INSTALLED_APPS = [ # ...其他已安装的app 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 要放在CommonMiddleware前面 'django.middleware.common.CommonMiddleware', # ...其他中间件 ] # 开发环境允许所有来源(生产环境要指定具体域名) CORS_ALLOW_ALL_ORIGINS = True # 允许携带Cookie(因为CSRF Token存在Cookie里) CORS_ALLOW_CREDENTIALS = True
2. 请求方法没设置正确
检查你的reqwest请求有没有明确写method: 'POST',如果没写,reqwest默认是GET请求,那视图里的if request.method == 'POST'自然不会触发print。
3. CSRF验证失败
如果Token没正确携带,Django的CSRF中间件会直接返回403错误,根本不会进入视图逻辑。打开浏览器开发者工具的Network面板,看看请求状态码是不是403,如果是,回到第一部分检查Token的获取和携带是否正确。
4. URL路由配置错误
确认urls.py里有没有把/tasks/映射到你写的那个视图函数:
from django.urls import path from . import views urlpatterns = [ path('tasks/', views.your_task_view, name='tasks'), # 确保这里的视图是你写的那个 ]
5. 视图函数没返回响应
哪怕print执行了,如果视图没返回任何响应,浏览器也会显示“无响应”。记得给视图加上返回:
from django.http import JsonResponse def your_task_view(request): if request.method == 'POST': print("************request body*******") # 这里可以处理请求数据 return JsonResponse({'status': 'success'}) # 一定要返回响应! # 处理GET请求的情况 return JsonResponse({'status': 'get_method'})
内容的提问来源于stack exchange,提问作者zephyr.mao

