zoukankan      html  css  js  c++  java
  • 关于form表单或者Ajax向后台发送数据时,数据格式的探究

    最近在做一个资产管理系统项目,其中有一个部分是客户端向服务端发送采集到的数据的,服务端是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 拿到的数据是这样的:    

    '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"}}'
  • 相关阅读:
    day 21 01 序列化模块和模块的导入的复习以及包的初识
    day 20 02 模块的导入
    Shell从入门到精通进阶之三:表达式与运算符
    Shell从入门到精通进阶之二:Shell字符串处理之${}
    shell从入门到精通进阶之一:Shell基础知识
    容器平台自动化CI/CD流水线实践之一:环境概述
    什么是DevOps?
    kubernetes进阶之七:Service
    kubernetes进阶之六:StatefulSet & DaemonSet
    kubernetes进阶之五:Replication Controller&Replica Sets&Deployments
  • 原文地址:https://www.cnblogs.com/zhang-can/p/7631262.html
Copyright © 2011-2022 走看看