1、什么是json?

JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。

2. 那么JSON和JavaScript又有什么关系呢?

json对象其实最初就是从JS中衍生出来的一种数据格式,它和JS有着本质的区别。可以说JSON是JavaScript对象的子集,json继承了JavaScript的number,string(" "),bool,null,array,{"name":"egon" ,"age ":18} 注意json只支持双引号 。所以相比其他语言,JavaScript把json字符串解析成JS对象有天然优势。

3. JSON和Python的关系?

Python有Python的数据类型,JS有JS的数据类型,但前后端之所以可以交互,是因为中间有 json字符串做中间转换

4. JSON和JS对象,以及Python的相互转化关系

JSON.stringify(JS对象)     将JS对象序列化成 JSON字符串    ------->python的json.dumps()

JSON.parse('JSON对象')    将json字符串反序列化成 JS对象--------->python的json.loads()

5 什么是Ajax?

AJAXAsynchronous Javascript And XML)翻译成中文就是异步JavascriptXML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,可以指定json),

异步的JavaScript,使用 【JavaScript语言】 以及 相关【浏览器提供类库】 的功能向服务端发送请求,当服务端处理完请求之后,【自动执行某个JavaScript的回调函数】

6 Ajax的应用场景

相对于Form表单而言的,其最大的优势就是页面不刷新,提交时可以偷偷向后台发数据

注册时,输入用户名自动检测用户是否已经存在(监测光标,输入完成后会移动到其他地方,此时发送ajax请求)

登陆时,提示用户名密码错误

删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除

7 原生Ajax和Jquery封装的Ajax

  使用Ajax直接使用JS的XMLHttp Request对象, 无需引入Jquery了。这样响应客户端携带信息量减少,可节省流量,适用于手机移动端。

8 原生的Ajax(Xmlhttprequest)

  XmlHttpRequest对象的主要方法:

a. void open(String method,String url,Boolen async)
   用于创建请求
    
   参数:
       method: 请求方式(字符串类型),如:POST、GET、DELETE...
       url:    要请求的地址(字符串类型)
       async:  是否异步(布尔类型)
 
b. void send(String body)
    用于发送请求
 
    参数:
        body: 要发送的数据(字符串类型)
 
c. void setRequestHeader(String header,String value)
    用于设置请求头
 
    参数:
        header: 请求头的key(字符串类型)
        vlaue:  请求头的value(字符串类型)
 
d. String getAllResponseHeaders()
    获取所有响应头
 
    返回值:
        响应头数据(字符串类型)
 
e. String getResponseHeader(String header)
    获取响应头中指定header的值
 
    参数:
        header: 响应头的key(字符串类型)
 
    返回值:
        响应头中指定的header对应的值
 
f. void abort()
 
    终止请求

XmlHttpRequest对象的属性:

a. Number readyState
   状态值(整数)
 
   详细:
      0-未初始化,尚未调用open()方法;
      1-启动,调用了open()方法,未调用send()方法;
      2-发送,已经调用了send()方法,未接收到响应;
      3-接收,已经接收到部分响应数据;
      4-完成,已经接收到全部响应数据;
 
b. Function onreadystatechange
   当readyState的值改变时自动触发执行其对应的函数(回调函数)
 
c. String responseText
   服务器返回的数据(字符串类型)
 
d. XmlDocument responseXML
   服务器返回的数据(Xml对象)
 
e. Number states
   状态码(整数),如:200、404...
 
f. String statesText
   状态文本(字符串),如:OK、NotFound...

原生Ajax的四步操作:

创建核心对象XMLhttprequest

与服务器进行连接open

发送请求send

监听readystate

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <h1>XMLHttpRequest - Ajax请求</h1>
    <input type="button" onclick="XmlGetRequest();" value="Get发送请求" />
    <input type="button" onclick="XmlPostRequest();" value="Post发送请求" />

    <script src="/jquery-3.3.1.js" type="text/javascript"></script>
    <script type="text/javascript">

        {#这个函数是为了解决不同浏览器的兼容性问题#}
        function GetXHR(){
            var xhr = null;
            if(XMLHttpRequest){
                xhr = new XMLHttpRequest();
            }else{
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            }
            return xhr;

        }

        function XmlPostRequest(){
            var xhr = GetXHR();
            // 定义回调函数
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已经接收到全部响应数据,执行以下操作
                    var data = xhr.responseText;
                    console.log(data);
                }
            };
            // 指定连接方式和地址----文件方式
            xhr.open('POST', "/test", true);
            // 设置请求头问题出现了为什么后端request.post方法没有数据呢?
            {#使用jQuery发送post请求jQuery会默认把 发送的数据(js对象)编码成urlencoded格式,使用原生ajax就不会了#}
            {#所以使用原生ajax发POST请求之前,请求头中 务必要指定数据的编码格式“Content-Type”, “application/x-www-form-urlencoded”才能发到server端;#}
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
            // 发送请求
            xhr.send('n1=1;n2=2;');
        }

        function XmlGetRequest(){
            var xhr = GetXHR();
            // 定义回调函数
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    // 已经接收到全部响应数据,执行以下操作
                    var data = xhr.responseText;
                    console.log(data);

                }
                if(xhr.readyState==1){console.log("对象未调用open方法")}
                if(xhr.readyState==2){console.log("请求发送")}
                if(xhr.readyState==3){console.log("接收中")}
            };
            // 指定连接方式和地址----文件方式
            xhr.open('get', "/test?n1=1", true);
            // get发送请求,想要传递参数不能在send中传递,只能在open的url里面加?加参数
            xhr.send();
        }

    </script>

</body>
</html>

后端返回数据用httpresponse即可,因为ajax传递字符,相对应的后端也需要同种方式传递

def ajax(request):
    return render(request, 'ajax.html')

def test(request):
    print('shoudao')
    n1 = request.GET.get('n1')
    a = request.GET
    print(a, n1)
    return HttpResponse('shoudao')

9 jqeury的Ajax

jquery就是把上述四步封装成整体:

<script>
    $('p button').click(function () {
      var $user=$('p input').val()
       d={
    "name": "中国",
    "province": [{
        "name": "黑龙江",
        "cities": {
            "city": ["哈尔滨", "大庆"]
        }
    }, {
        "name": "广东",
        "cities": {
            "city": ["广州", "深圳", "珠海"]
        }
    }, {
        "name": "台湾",
        "cities": {
            "city": ["台北", "高雄"]
        }
    }, {
        "name": "新疆",
        "cities": {
            "city": ["乌鲁木齐"]
        }
    }]
}
     d=JSON.stringify(d)
      $.ajax({
           url:'/ajax/',
           type:'POST',
{# traditional:一般是我们的data数据有数组时会用到 #}
           traditional:true,
           data:d,
{#  ----------------- ajax的回调函数----------------------#}
{#       1、server端response 200成功,执行的回调函数#}
           success:function (data) {
               data=JSON.parse(data)
               console.log(typeof data)},
{#      2、erver端 response错误,执行的回调函数 #}
           error:function () {
               console.log(arguments)
               alert(123) },
{#      3、无论server端返回的结果如何,都会执行的回调函数#}
           complete:function () {
               alert(321)  },
{#      4、根据server端返回的状态码,执行的回调函数#}
           statusCode:{
               '403':function () {alert(403)},
               '503':function () {alert(503)}

           }
          })
    })
</script>

请求参数的介绍

data:
ajax请求要携带的数据是肯定是一个json的object对象,ajax方法就会默认地把它编码成urlencode (urlencoded:?a=1&b=2)就像form表单、a标签格式的数据发送给server,此外,ajax默认以get方式发送请求。


注意:因为ajax要携带的数据是json的object对象,也会默认编码成urlcode格式,思考 如果你用 requests模块或者原生ajax向server发送数据、或者发送json数据,应该怎么做?
当然要指定 数据content-Type 和报头信息?

#-----------------------------------------------------------------
processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,
             那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString()
             ,最后得到一个[object,Object]形式的结果。

#-----------------------------------------------------------------------

contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。
             用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,
             比如contentType:"application/json",即向服务器发送一个json字符串:
               $.ajax("/ajax_get",{
             
                  data:JSON.stringify({
                       a:22,
                       b:33
                   }),
                   contentType:"application/json",
                   type:"POST",
             
               });                          //{a: 22, b: 33}

             注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json

----------------------------------------------
traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]},
              traditional为false会对数据进行深层次迭代;数据就会变成c=x&&c=y可能不会拿到我们想要结果

响应参数

/*

dataType:  预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。
            默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;
            比如我们的服务器响应的content Type为json格式,这时ajax方法就会对响应的内容
            进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式
            的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用
            data Type。
            dataType的可用值:html|xml|json|text|script
            见下dataType实例

*/

10 伪造ajax(iframe+form)

  iframe其实就是在原页面中开辟了一个新的窗口,可以加载出其他页面,如果我们利用form表单将数据提交到iframe指定的url,系统依然会去执行url对应的view,我们只需要把所需要的数据从iframe的窗口中提取出来即可,把iframe设置为隐藏模式,这样就不会有人发现iframe的存在了,完美的模拟了ajax的不刷新功能。至于回调功能,我们只需要 设置一个iframe的onload即可,别忘了iframe本质上也只是一个窗口。

可以看到iframe就是一个窗口,接下来我们就来伪造ajax了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>伪造Ajax</title>
</head>
<body>

<input type="text">
<form id="f1" action="/login.html" method="post" target="ifr">
    <iframe name="ifr" id="ifr"></iframe>
{#    当iframe加载时,也就是有返回值的时候 执行loadiframe()     模拟回调函数#}
    <input name="user" type="text">
    <a onclick="submit_form()">提交 </a>
</form>
</body>
<script>
    function submit_form() {
       document.getElementById('f1').submit()
       document.getElementById('ifr').onload=loadiframe
    }
   function loadiframe() {
      var return_values=document.getElementById('ifr').contentWindow.document.body.innerHTML
      console.log(return_values)
   }
</script>
</html>

11 ajax的一些应用,实现上传和预览功能

  ajax要想发送文件,就必须借助JS中formdata对象,( var formdata=new FormData()),formdata对象帮我们把文件 构造成特定的请求体和请求头,在post中也无需设置content-type了,设置了反而会多此一举而出错。

  11.1 原生ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>伪造Ajax</title>
</head>
<body>

<h1>原生ajax上传文件</h1>
<div id="container"></div>
<p><input type="file"  id="f1"></p>
<p><input id="f2" type="button" onclick="fileup()" value="上传"></p>
<div id="preview"></div>
<script>
    function fileup() {
        var formdata = new FormData()
        {#        要想发文件必须借助一个特殊的 formdata对象,帮助我们封装 文件对象 #}
        formdata.append('k1', 'v2')
        formdata.append('k1', document.getElementById('f1').files[0])
        {#        获取文件对象.files得到是一个列表(全部的文件对象)获取第1个切片[0]#}
        var xhr = new XMLHttpRequest()
        xhr.open('POST', '/ajax.html')
        {#        xhr.setRequestHeader("ConTent-Type" ,"application/x-www-form-urlencoded")#}
        {#        切记 既然文件对象帮我们做了文件封装,#}
        {#        也包括了请求头"ConTent-Type,就无需在像原来发字符串的时候加"ConTent-Type了#}
        xhr.send(formdata)
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                var filepath = xhr.responseText
                console.log(filepath)
                {#                获取服务端返回的文件路径#}
                var tag = document.createElement('img')
                tag.src = "/" + filepath
                {#                在本地生成一个img标签显示#}
                document.getElementById('preview').appendChild(tag)

            }
        }
    }
</script>
</body>
</html>

后端

def fileup(request):
    print('ok')
    if request.method=='GET':
        return render(request,'up_file.html')
    else:
        print('OK')
        fileobj=request.FILES.get('k1')
        filepath=os.path.join('static',fileobj.name)
        with open(filepath,'wb') as f:
            for chunk in fileobj.chunks():
                f.write(chunk)
        return HttpResponse(filepath)

  11.2jquery ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>原生Aja上传文件</title>
</head>
<body>
<h1>原生ajax上传文件</h1>
<div id="container"></div>
<p><input type="file" id="f1"></p>
<p><input id="f2" type="button" onclick="Queryup()" value="上传"></p>
<script src="/static/zhanggen.js"></script>
<script>
 function Queryup() {
    var formdata=new FormData()
{#   $(document.getElementById('f1'))       #}
{#    doc对象转换成Jquery对象 $(doc对象)    #}
{#    jQueryup对象转成doc对象 jQuery对象[0] #}
{#    $('#f1')[0]#}
    formdata.append("k1", $('#f1')[0].files[0])
    $.ajax({
        url:'/fileup/',
        type:'POST',
        contentType:false,
{#        告诉Jquery不要对请求头做特殊处理,因为formDta已经把数据封装好了#}
        processData:false,
        data:formdata ,
        success:function (args) {
           var ele=document.createElement('img')
            ele.src="/"+ args
           document.getElementById('container') .appendChild(ele)
        }
    })
}

</script>
</body>
</html>

  11.3 iframe+form

  由于FormData对象是HTML5之后提出的新对象,不兼容之前老版本的浏览器,一般JS的上传插件都是通过 iframe+form伪造出来的,所以这种上传方法的兼容性会更好些

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>伪造Ajax上传</title>
</head>
<body>
<h1>伪造Ajax上传</h1>
<form method="post" id="f1" action="/fileup/" target='ifr'enctype="multipart/form-data">
  <p><input type="file" name="k1"></p>
  <p><iframe id="ifr"name="ifr" style="display: none"></iframe></p>
  <p><input type="button" value="提交" onclick="upfile()"></p>
</form>
<div id="container"></div>
</body>
<script>
function upfile() {
{#    找到iframe标签在线绑定事件 页面加载事件()#}
    document.getElementById('ifr').onload=loadIframe
{#    使用.submit()方法 提交表单#}
    document.getElementById('f1').submit()
                }
function loadIframe() {
{#    服务端有返回值 iframe标签就会加载,利用此特性绑定 加载事件,然后创建img标签,apendchilder到 一个div中显示 #}
    var return_value=document.getElementById('ifr').contentWindow.document.body.innerHTML
    var tag=document.createElement('img')
    tag.src='/'+return_value
    document.getElementById('container').appendChild(tag)}
</script>
</html>

 

posted on 2018-08-03 16:57  momo大魔王  阅读(152)  评论(0编辑  收藏  举报