Django REST API可通过Swagger POST,Postman/Vue Axios请求失败
问题排查:Vue Axios POST请求Django API返回400错误(Unsupported media type "text/plain")
我有一个Django模型,通过Admin界面或Swagger的POST请求能正常添加记录,但Vue表单用Axios请求时返回400错误且无额外提示;用Postman测试时返回错误:"detail": "Unsupported media type \"text/plain\" in request."。三种请求的JSON内容基本一致,仅Swagger的JSON带有换行符,但只有Swagger请求成功。同一Vue应用内其他表单可正常工作,现寻求排查方案。
一、请求对比信息
1. Swagger成功请求的JSON数据
{ "matchingKey": "chgpt-a", "sequence": 1515, "param_kwargs_json": {}, "param1": "tensorFlow", "param2": "N/A", "param3": "N/A", "param4": "N/A", "param5": "N/A", "param6": "N/A", "param7": "N/A", "param8": "N/A", "param9": "N/A", "param10": "N/A", "description": "test from postman 1331" }
2. Swagger响应头
access-control-allow-origin: * allow: GET, POST, HEAD, OPTIONS content-length: 265 content-type: application/json cross-origin-opener-policy: same-origin date: Fri, 07 Apr 2023 06:27:13 GMT referrer-policy: same-origin server: WSGIServer/0.2 CPython/3.10.9 vary: Accept, Origin, Cookie x-content-type-options: nosniff x-frame-options: DENY
3. Postman测试的请求头
request_headers= {'Content-Length': '222', 'Content-Type': 'application/json', 'Host': 'localhost:8000', 'Connection': 'keep-alive', 'Sec-Ch-Ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"', 'Accept': 'application/json, text/plain, */*', 'Sec-Ch-Ua-Mobile': '?0', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36', 'Sec-Ch-Ua-Platform': '"Windows"', 'Origin': 'http://localhost:444', 'Sec-Fetch-Site': 'same-site', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Dest': 'empty', 'Referer': 'http://localhost:444/', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US,en;q=0.9'}
二、相关配置代码
1. Django CORS配置
CSRF_TRUSTED_ORIGINS = ["http://localhost:8000", "http://localhost:444/"] #CSRF_COOKIE_DOMAIN = '.localhost' CORS_ALLOW_ALL_ORIGINS = True CORS_ALLOWED_ORIGINS = [ 'http://127.0.0.1:8000', 'http://localhost:8000', 'http://127.0.0.1:5173', 'http://localhost:5173', 'http://127.0.0.1:444', 'http://localhost:444' ]
2. Vue表单提交方法
saveParameter(_newParameters){ console.log('saveParameter()') this.swalLoading('Adding New Parameter...') //check for completeness if(true){ console.log('saveParameter data = %s', _newParameters.matchingKey) setTimeout(()=>{ // POST API FOR ADDING Parameter getAPI.post('http://localhost:8000/api/parameters/', _newParameters) .then(res=>{ // SETS MESSAGE FOR RESPONSE let message = `Parameter ${res.data.requestpath} ${res.data.requestmethod} has been successfully added.` // DISPLAYS SUCCESS SCREEN/MODAL this.swalSuccess(message) }) .catch(err=>{ this.swalError(err) }) }, 1000) }
三、控制台错误日志
toggleAddParameterModal mixins.js:130 --mixins toggleModal(addParameter) mixins.js:139 Proxy(Object) {closeModal: ƒ, …} ParametersTableModal.vue?t=1680847383434:119 saveParameter() ParametersTableModal.vue?t=1680847383434:123 saveParameter data = moogoogaipan mixins.js:130 --mixins toggleModal(addParameter) mixins.js:139 Proxy(Object) {closeModal: ƒ, …} xhr.js:187 POST http://localhost:8000/api/parameters/ 400 (Bad Request) dispatchXhrRequest @ xhr.js:187 xhrAdapter @ xhr.js:13 dispatchRequest @ dispatchRequest.js:53 request @ Axios.js:108 Axios.<computed> @ Axios.js:140 wrap @ bind.js:9 (anonymous) @ ParametersTableModal.vue?t=1680847383434:126 setTimeout (async) saveParameter @ ParametersTableModal.vue?t=1680847383434:124 (anonymous) @ ParametersTableModal.vue:111 (anonymous) @ runtime-dom.esm-bundler.js:1450 callWithErrorHandling @ runtime-core.esm-bundler.js:155 callWithAsyncErrorHandling @ runtime-core.esm-bundler.js:164 invoker @ runtime-dom.esm-bundler.js:339 mixins.js:130 --mixins toggleModal(parametersTable) mixins.js:139 Proxy(Object) {validate: ƒ, formatPrice: ƒ, formatPriceIntl: ƒ, …}
四、排查与解决建议
1. 强制设置Axios请求头
即使默认配置存在,显式指定Content-Type确保请求被正确识别:
getAPI.post('http://localhost:8000/api/parameters/', _newParameters, { headers: { 'Content-Type': 'application/json' } })
同时确认_newParameters是纯JavaScript对象,未被意外转为字符串。
2. 检查Django REST Framework解析器配置
确保全局或视图级配置包含JSON解析器:
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': [ 'rest_framework.parsers.JSONParser', # 保留其他需要的解析器 ] }
3. 处理CSRF Token
跨域请求需携带CSRF Token,在Vue中添加如下逻辑:
// 获取Cookie中的CSRF Token function getCookie(name) { 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(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } const csrftoken = getCookie('csrftoken'); // 请求时添加头 getAPI.post('url', data, { headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken } })
4. 校验请求数据格式
确保param_kwargs_json是对象而非字符串,若来自表单输入需手动解析:
_newParameters.param_kwargs_json = JSON.parse(_newParameters.param_kwargs_json || '{}');
内容的提问来源于stack exchange,提问作者Ali Vleotsky
相关产品推荐
相关产品推荐

