关于form表单或者Ajax向后台发送数据时,数据格式的探究
2017-10-06 11:18
393 查看
最近在做一个资产管理系统项目,其中有一个部分是客户端向服务端发送采集到的数据的,服务端是Django写的,客户端需要用requests模块模拟发送请求
假设发送的数据是这样的:
data = {'status' : True , 'content' : { 'k1' : 'xxxx' , 'k2' : 'xxxx' }}
是字典套字典的,然后通过requests.post(url = url ,data = data) 发送,会发现在服务端接收到的数据是这样的,<QueryDict>:{ [ 'status' , 'content' ] }
发生了什么,为什么只取到了key,但是没有取到values呢,既然能取到key,说明Django是没问题的
那问题肯定就出在requests.post发送数据上了
好了,铺垫完毕
想一下,ajax是怎么发送数据的
$.ajax ({
url : 'xxxx',
data : {
k1 : 1,
k2 : 'abc',
k3 : [1,2,3,4,'s']
}
})
呐,只能发送这三种格式吧,没有字典吧,如果非要发送字典,可以通过JSON把字典转成字符串格式,JSON.stringfy({ 'k1':'xxx' })
form 表单也是这样的,而requests.post就是仿造的form表单提交
发现了问题,我们再来剖析一下http发送post请求的过程
ajax发送的data是个字典,是键值对的形式,在http的post请求过程中,把这种键值对转换成
k1=xxx&k2=xxx这种格式,并且会带上一个请求头:
content-type : application/x-www-form-urlencoded
这个请求头和k1=xxx&k2=xxx这种格式是以一一对应的,只要发送这个格式,就必须带上这个请求头,后台的request.POST会根据这个请求头解析这种格式,还原成以前字典的格式。而且这种格式和这个请求头都是默认的,所以如果我们不修改,直接发送文章开始说的那种格式,服务端就不能解析,所以只拿到字典的key,没拿到value
但如果是现在这种情况,我们发送的不是这个格式,而是想要发送JSON.stringfy({ 'k1':'xxx' })这种json字符串,也是有办法的,ajax可以自定义请求头,改成这样:
$.ajax ({
url : 'xxxx',
headers : { 'content-type' : 'application/json' },
data : JSON.stringfy( {k1 : 1,k2 : 'abc',k3 : [1,2,3,4,'s']})
})
这样后台就会根据json去解析接收到的数据(json格式的字符串)
但是不能用request.POST了,因为request.POST 默认是按k1=xxx&k2=xxx这种格式解析数据的,
应该用request.body去拿数据,再用json.loads一下就拿到这个字典了
默认情况下,form 表单,ajax 以及 requests.post 都是这样处理的
所以在这个项目中,我们需要用requests自定义这个请求头,这个写法就很简单了
requests.post(url = url ,json = data) ,就行了,把原来的data关键字参数换成json关键字参数。
内部做的就是,1.序列化data,2.带一个请求头'content-type' : 'application/json'
这样,服务端拿到的数据,先decode解码一下,在json.loads,就是我们熟悉的字典了
在ajax中,像后台发送数据:
GET请求:
1.如果是字符串,数字,可以正常发送:
$.ajax({
url : 'xxxx',
type : 'get',
data : { 'k1':'v1','k2':'v2' }
....
})
2.如果是字典(数组)格式
a.发送的格式为:'test_list':[1,2,3,'abc']
后台request.GET 拿到的数据是这样的:
b.ajax发送时添加一个traditional:true
后台request.GET 拿到的数据是这样的:
POST请求:
发送的数据格式:
后台依次打印
1.就直接这样发送:
后台拿到的数据:
2.加上traditional:true
3.ajax通过JSON.stringify( ) 发送
前端:
后台拿到的数据:
假设发送的数据是这样的:
data = {'status' : True , 'content' : { 'k1' : 'xxxx' , 'k2' : 'xxxx' }}
是字典套字典的,然后通过requests.post(url = url ,data = data) 发送,会发现在服务端接收到的数据是这样的,<QueryDict>:{ [ 'status' , 'content' ] }
发生了什么,为什么只取到了key,但是没有取到values呢,既然能取到key,说明Django是没问题的
那问题肯定就出在requests.post发送数据上了
好了,铺垫完毕
想一下,ajax是怎么发送数据的
$.ajax ({
url : 'xxxx',
data : {
k1 : 1,
k2 : 'abc',
k3 : [1,2,3,4,'s']
}
})
呐,只能发送这三种格式吧,没有字典吧,如果非要发送字典,可以通过JSON把字典转成字符串格式,JSON.stringfy({ 'k1':'xxx' })
form 表单也是这样的,而requests.post就是仿造的form表单提交
发现了问题,我们再来剖析一下http发送post请求的过程
ajax发送的data是个字典,是键值对的形式,在http的post请求过程中,把这种键值对转换成
k1=xxx&k2=xxx这种格式,并且会带上一个请求头:
content-type : application/x-www-form-urlencoded
这个请求头和k1=xxx&k2=xxx这种格式是以一一对应的,只要发送这个格式,就必须带上这个请求头,后台的request.POST会根据这个请求头解析这种格式,还原成以前字典的格式。而且这种格式和这个请求头都是默认的,所以如果我们不修改,直接发送文章开始说的那种格式,服务端就不能解析,所以只拿到字典的key,没拿到value
但如果是现在这种情况,我们发送的不是这个格式,而是想要发送JSON.stringfy({ 'k1':'xxx' })这种json字符串,也是有办法的,ajax可以自定义请求头,改成这样:
$.ajax ({
url : 'xxxx',
headers : { 'content-type' : 'application/json' },
data : JSON.stringfy( {k1 : 1,k2 : 'abc',k3 : [1,2,3,4,'s']})
})
这样后台就会根据json去解析接收到的数据(json格式的字符串)
但是不能用request.POST了,因为request.POST 默认是按k1=xxx&k2=xxx这种格式解析数据的,
应该用request.body去拿数据,再用json.loads一下就拿到这个字典了
默认情况下,form 表单,ajax 以及 requests.post 都是这样处理的
所以在这个项目中,我们需要用requests自定义这个请求头,这个写法就很简单了
requests.post(url = url ,json = data) ,就行了,把原来的data关键字参数换成json关键字参数。
内部做的就是,1.序列化data,2.带一个请求头'content-type' : 'application/json'
这样,服务端拿到的数据,先decode解码一下,在json.loads,就是我们熟悉的字典了
在ajax中,像后台发送数据:
GET请求:
1.如果是字符串,数字,可以正常发送:
$.ajax({
url : 'xxxx',
type : 'get',
data : { 'k1':'v1','k2':'v2' }
....
})
2.如果是字典(数组)格式
a.发送的格式为:'test_list':[1,2,3,'abc']
后台request.GET 拿到的数据是这样的:
'test_list[]': ['1', '2', '3', 'abc']
b.ajax发送时添加一个traditional:true
后台request.GET 拿到的数据是这样的:
'test_list': ['1', '2', '3', 'abc']
POST请求:
发送的数据格式:
var test_list = [1,2,'abc']; var test_dict = {'kk1':'vv1','kk2':'vv2'}
data: {'k1':123,'k2':'abc','k3':test_list,'k4':test_dict}
后台依次打印
print(request.POST) print(json.loads(request.body.decode('utf-8'))) print(request.body)
1.就直接这样发送:
后台拿到的数据:
<QueryDict: {'k1': ['123'], 'k2': ['abc'], 'k3[]': ['1', '2', 'abc'], 'k4[kk1]': ['vv1'], 'k4[kk2]': ['vv2']}> 报错 b'k1=123&k2=abc&k3%5B%5D=1&k3%5B%5D=2&k3%5B%5D=abc&k4%5Bkk1%5D=vv1&k4%5Bkk2%5D=vv2'
2.加上traditional:true
<QueryDict: {'k1': ['123'], 'k2': ['abc'], 'k3': ['1', '2', 'abc'], 'k4': ['[object Object]']}> 报错 b'k1=123&k2=abc&k3=1&k3=2&k3=abc&k4=%5Bobject+Object%5D'
3.ajax通过JSON.stringify( ) 发送
前端:
data: JSON.stringify({'k1':123,'k2':'abc','k3':test_list,'k4':test_dict})
后台拿到的数据:
<QueryDict: {'{"k1":123,"k2":"abc","k3":[1,2,"abc"],"k4":{"kk1":"vv1","kk2":"vv2"}}': ['']}> {'k1': 123, 'k2': 'abc', 'k3': [1, 2, 'abc'], 'k4': {'kk1': 'vv1', 'kk2': 'vv2'}} b'{"k1":123,"k2":"abc","k3":[1,2,"abc"],"k4":{"kk1":"vv1","kk2":"vv2"}}'
相关文章推荐
- 将表单序列化之后变成的json格式的数据无法通过Ajax发送到后台的解决
- JS将form表单转换为json数据,使用ajax发送请求案例
- 关于Ajax 请求数据格式FormData、Ruquest PayLoad、Query String Parameters 区别
- Ajax发送FormData对象封装的表单数据
- ajax 请求后台数据(及使用FormData对象提交表单及上传图片)
- ajax发送请求后台处理数据格式然后返回前台的方法(ObjectMapper)
- 关于esayui ajax前台form表单传值后台springmvc页面报400错误
- 关于jQuery使用serializeArray()序列化表单数据,使用FormData()实现AJAX请求的问题
- struts2 + ajax(由前台的form提交数据到后台,再根据form所调用返回获取的后台json格式的数据返回到前端,然后前端用jquery对json数据进行解析)==》》涉及文件上传的部分
- 【工作日志】0006利用Ajax或者form表单从前台传值到后台
- struts2 + ajax(由前台的form提交数据到后台,再根据form所调用返回获取的后台json格式的数据返回到前端,然后前端用jquery对json数据进行解析)==》》涉及非文件上传的部分
- 纯js将form表单的数据封装成json 以便于ajax发送
- 在使用ajax向后台发送json数据,存在格式不正确的问题
- EXT--表单AJax提交后台,返回前端数据格式的转换
- Ajax发送formdata数据,SpringMVC后台处理
- flask获取表单以enctype="multipart/form-data"格式发送的数据
- jQuery通过ajax获得后台json数据给form表单赋值
- JQuery调用Ajax使用Submit方法后台无法接受到发送的form表单
- Form表单和ajax中的post请求&&后台获取数据方法(深度好文)
- ajax发送json格式数据到后台(输入流content)