无法从 Django request.POST 获取 POST 数据
Cannot get POST data from Django request.POST
我正在尝试验证 POST 请求中是否包含所需数据。我有一个 django
后端和一个 vue3
前端。
这是我的 django 视图:
views.py
# Sign user in and issue token
@require_http_methods(['POST'])
def login(request: HttpRequest):
if request.method == 'POST':
# check that required fields were send with POST
print(request.body)
if {'username', 'password'} >= set(request.POST): # <- evaluates as False
print('missing required fields. INCLUDED: ' + str(request.POST))
return JsonResponse(
data={'message': 'Please provide all required fields.'},
content_type='application/json',
status=400)
# check that username exists and password matches
if (User.objects.filter(username=request.POST['username']).count() >
0):
user = User.objects.get(username=request.POST['username'])
if user.password == request.POST['password']:
# Delete previously issued tokens
Token.objects.filter(user_id=user.id).delete()
token = Token(user_id=user.id)
token.save()
return JsonResponse(data={'userToken': token.to_json()},
content_type='application/json',
status=200)
else:
return JsonResponse(
data={'message': 'Incorrect username or password.'},
content_type='application/json',
status=400)
else:
return HttpResponseNotAllowed(permitted_methods=['POST'])
还有我的 axios 请求
Login.vue
axios
.post('http://localhost:8000/api/users/login', {
'username': form.get('username'),
'password': form.get('password'),
}, {
validateStatus: (status) => {
return status !== 500
},
})
.then((response) => {
console.log(response.data)
if (response.data.success) {
// Commit token value to store
store.commit('setToken', response.data.token)
// Request user data ...
} else {
alert.message = response.data.message
alert.type = 'error'
document.querySelector('#alert')?.scrollIntoView()
}
})
我可以看到 username
和 password
是在 request.body
中设置的,但不是 request.POST
,如 django 日志中所示。
December 01, 2021 - 17:40:29
Django version 3.2.9, using settings 'webserver.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
b'{"username":"site.admin","password":"password"}'
missing required fields. INCLUDED: <QueryDict: {}>
Bad Request: /api/users/login
[01/Dec/2021 17:40:30] "POST /api/users/login HTTP/1.1" 400 50
/Users/colby/Projects/emotions/backend/webserver/users/views.py changed, reloading.
Watching for file changes with StatReloader
Performing system checks...
我做错了什么?
编辑
这是从 axios 请求中设置的 headers
{
'Content-Length': '47',
'Content-Type': 'application/json',
'Host': 'localhost:8000',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0',
'Accept': 'application/json,
text/plain, */*',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Origin': 'http://localhost:8080',
'Dnt': '1',
'Connection': 'keep-alive',
'Referer': 'http://localhost:8080/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'Sec-Gpc': '1'
}
编辑 2
我可以通过将 Content-Type header 显式设置为 multipart/form-data
来更正此问题。
axios
.post('http://localhost:8000/api/users/login', formData,
{
validateStatus: (status) => {
return status !== 500
},
headers: {
'Content-Type': 'multipart/form-data',
}
).then(...)
我还必须将 django 视图中的 if 语句调整为
if 'username' not in request.POST or 'password' not in request.POST:
...
我怀疑 Axios 自动设置了一个 content-type: application/json
header,这意味着请求 body 不包含 Django 可以理解的 HTTP POST 参数。
您可以通过打印 request.headers
来验证这一点,如果这确实是问题所在,请通过以下任一方式解决:
- 正在解析来自 JSON 的请求 body:
import json
data = json.loads(response.body.decode())
if {'username', 'password'} >= set(data): # etc.
- 将数据作为表单数据发送client-side:
var formData = new FormData();
formData.append("username", form.get("username"))
formData.append("password", form.get("password"))
axios
.post('http://localhost:8000/api/users/login',
formData,
{headers: {'Content-Type': 'multipart/form-data'}
})
我个人推荐解决方案 1,因为我发现它不那么冗长且更易于维护,但这主要取决于您的偏好和要求:)
我正在尝试验证 POST 请求中是否包含所需数据。我有一个 django
后端和一个 vue3
前端。
这是我的 django 视图:
views.py
# Sign user in and issue token
@require_http_methods(['POST'])
def login(request: HttpRequest):
if request.method == 'POST':
# check that required fields were send with POST
print(request.body)
if {'username', 'password'} >= set(request.POST): # <- evaluates as False
print('missing required fields. INCLUDED: ' + str(request.POST))
return JsonResponse(
data={'message': 'Please provide all required fields.'},
content_type='application/json',
status=400)
# check that username exists and password matches
if (User.objects.filter(username=request.POST['username']).count() >
0):
user = User.objects.get(username=request.POST['username'])
if user.password == request.POST['password']:
# Delete previously issued tokens
Token.objects.filter(user_id=user.id).delete()
token = Token(user_id=user.id)
token.save()
return JsonResponse(data={'userToken': token.to_json()},
content_type='application/json',
status=200)
else:
return JsonResponse(
data={'message': 'Incorrect username or password.'},
content_type='application/json',
status=400)
else:
return HttpResponseNotAllowed(permitted_methods=['POST'])
还有我的 axios 请求
Login.vue
axios
.post('http://localhost:8000/api/users/login', {
'username': form.get('username'),
'password': form.get('password'),
}, {
validateStatus: (status) => {
return status !== 500
},
})
.then((response) => {
console.log(response.data)
if (response.data.success) {
// Commit token value to store
store.commit('setToken', response.data.token)
// Request user data ...
} else {
alert.message = response.data.message
alert.type = 'error'
document.querySelector('#alert')?.scrollIntoView()
}
})
我可以看到 username
和 password
是在 request.body
中设置的,但不是 request.POST
,如 django 日志中所示。
December 01, 2021 - 17:40:29
Django version 3.2.9, using settings 'webserver.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
b'{"username":"site.admin","password":"password"}'
missing required fields. INCLUDED: <QueryDict: {}>
Bad Request: /api/users/login
[01/Dec/2021 17:40:30] "POST /api/users/login HTTP/1.1" 400 50
/Users/colby/Projects/emotions/backend/webserver/users/views.py changed, reloading.
Watching for file changes with StatReloader
Performing system checks...
我做错了什么?
编辑
这是从 axios 请求中设置的 headers
{
'Content-Length': '47',
'Content-Type': 'application/json',
'Host': 'localhost:8000',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0',
'Accept': 'application/json,
text/plain, */*',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Origin': 'http://localhost:8080',
'Dnt': '1',
'Connection': 'keep-alive',
'Referer': 'http://localhost:8080/',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'cross-site',
'Sec-Gpc': '1'
}
编辑 2
我可以通过将 Content-Type header 显式设置为 multipart/form-data
来更正此问题。
axios
.post('http://localhost:8000/api/users/login', formData,
{
validateStatus: (status) => {
return status !== 500
},
headers: {
'Content-Type': 'multipart/form-data',
}
).then(...)
我还必须将 django 视图中的 if 语句调整为
if 'username' not in request.POST or 'password' not in request.POST:
...
我怀疑 Axios 自动设置了一个 content-type: application/json
header,这意味着请求 body 不包含 Django 可以理解的 HTTP POST 参数。
您可以通过打印 request.headers
来验证这一点,如果这确实是问题所在,请通过以下任一方式解决:
- 正在解析来自 JSON 的请求 body:
import json
data = json.loads(response.body.decode())
if {'username', 'password'} >= set(data): # etc.
- 将数据作为表单数据发送client-side:
var formData = new FormData();
formData.append("username", form.get("username"))
formData.append("password", form.get("password"))
axios
.post('http://localhost:8000/api/users/login',
formData,
{headers: {'Content-Type': 'multipart/form-data'}
})
我个人推荐解决方案 1,因为我发现它不那么冗长且更易于维护,但这主要取决于您的偏好和要求:)