Python全栈之路-Django(十六)

今日内容:Ajax
http://www.cnblogs.com/wupeiqi/articles/5703697.html

1 Ajax介绍

AJAX,Asynchronous JavaScript and XML (异步的JavaScript和XML),一种创建交互式网页应用的网页开发技术方案。

1.1异步的JavaScript:

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

PS:以上请求和响应的整个过程是【偷偷】进行的,页面上无任何感知。

1.2 XML

XML是一种标记语言,是Ajax在和后台交互时传输数据的格式之一
利用AJAX可以做:

  • 注册时,输入用户名自动检测用户是否已经存在。
  • 登陆时,提示用户名密码错误
  • 删除数据行时,将行ID发送到后台,后台在数据库中删除,数据库删除成功后,在页面DOM中将数据行也删除。

1.3 Ajax定义总结

偷偷向后台发请求  

2 Ajax发送数据

  • 原生Ajax,利用XMLHttpRequest对象
  • JQuery Ajax,内部基于原生Ajax
  • 伪Ajax,非XMLHttpRequest

2.1 原生Ajax

1、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...

实例:

a. XMLHttpRequest

GET请求:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        alert(xhr.responseText);
    }
};
xhr.open('GET','/add2/?i1=12&i2=19');
xhr.send();

POST请求:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        alert(xhr.responseText);
    }
};
xhr.open('POST','/add2/');
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send("i1=12&i2=19");

2.2 伪Ajax

伪Ajax,非XMLHttpRequest,利用iframe标签 不刷新打开页面发送HTTP请求

app01.views.py

def fake_ajax(request):
    if request.method == 'GET':
        return render(request, 'fake_ajax.html')
    else:
        print(request.POST)
        return HttpResponse('...')

templates.fake_ajax.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form id="f1" action="/fake_ajax/" method="post" target="ifr" >
    <iframe id="ifr" frameborder="1" name="ifr" style="display: none;"></iframe>
    <input type="text" name="user">
    <input type="button" value="提交" onclick="submitForm();">
</form>
<script>
    function submitForm() {
        document.getElementById('f1').submit();
        document.getElementById('ifr').onload = LoadIframe;

    }
    function LoadIframe() {
        var content = document.getElementById('ifr').contentWindow.document.body.innerText
        alert(content)
    }
</script>
</body>
</html>

2.3 实例

templates.index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>首页</h1>
    <input type="text" id="i1">
    +
    <input type="text" id="i2">
    =
    <input type="text" id="i3">

    <input type="button" id="btn1" value="JQuery Ajax" onclick="add1();">
    <input type="button" id="btn2" value="原生 Ajax" onclick="add2();">
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        function add1() {
            $.ajax({
                url: '/add1/',
                type: 'POST',
                data: {'i1': $('#i1').val(),'i2':$('#i2').val()},
                success: function (arg) {
                    $('#i3').val(arg)
                }
            })
        }
        function add2() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
               if (xhr.readyState ==4){
                   alert(xhr.responseText);
               }
            };
            // xhr.open('GET','/add2/?i1=12&i2=19');
            xhr.open('POST','/add2/');
            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            xhr.send('i1=12&i2=19');
        }
    </script>
</body>
</html>

app01.views.py

def add1(request):
    i1 = int(request.POST.get('i1'))
    i2 = int(request.POST.get('i2'))
    return HttpResponse(i1+i2)


def add2(request):
    if request.method == 'GET':
        i1 = int(request.GET.get('i1'))
        i2 = int(request.GET.get('i2'))
        print(i1+i2)
        return HttpResponse(i1+i2)
    else:
        # i1 = int(request.POST.get('i1'))
        # i2 = int(request.POST.get('i2'))
        # print(i1 + i2)
        print(request.POST)
        print(request.body)
        return HttpResponse('...')

3 上传文件

  • 基于原生Ajax XMLHttpRequest对象
  • JQuery Ajax
  • 伪Ajax

app01.views.py

import os
def upload(request):
    if request.method == 'GET':
        return render(request, 'upload.html')
    else:
        print(request.POST, request.FILES)
        file_obj = request.FILES.get('fafafa')
        file_path = os.path.join('static', file_obj.name)
        print(file_path)
        with open(file_path, 'wb') as f:
            for chunk in file_obj.chunks():
                f.write(chunk)
        return HttpResponse(file_path)

templates.upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>原生Ajax上传文件</h1>
    <input type="file" id="i1">
    <a onclick="upload1();">上传文件</a>
    <div id="container1"></div>

    <h1>JQuery Ajax上传文件</h1>
    <input type="file" id="i2">
    <a onclick="upload2();">JQuery Ajax上传文件</a>
    <div id="container2"></div>

    <h1>伪Ajax上传文件</h1>
    <form id="f1" action="/upload/" method="post" target="ifr" enctype="multipart/form-data">
        <iframe id="ifr" name="ifr" style="display: none;"></iframe>
        <input type="file" id="i3" name="fafafa">
        <a onclick="upload3();">伪Ajax上传文件</a>
    </form>
    <div id="container3"></div>

    <script src="/static/jquery-3.2.1.min.js"></script>
    <script>
        function upload1() {
            var formData = new FormData();
            formData.append('k1', 'v1');
            formData.append('fafafa', document.getElementById('i1').files[0]);
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function(){
                if(xhr.readyState == 4){
                    var  file_path = xhr.responseText;
                    var tag = document.createElement('img');
                    tag.src = "/"+ file_path;
                    document.getElementById('container1').appendChild(tag);

                }
            };
            xhr.open('POST','/upload/');
            // xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            xhr.send(formData);
        }
        function upload2() {
            var formData = new FormData();
            formData.append('k1', 'v1');
            formData.append('fafafa', $('#i2')[0].files[0]);

            // DOM对象和JQuery对象的互换
            // $('#i2') -> $('#i2')[0]
            // document.getElementById('i1') -> $(document.getElementById('i1'))
            $.ajax({
                url: '/upload/',
                type: 'POST',
                data: formData,
                processData: false,  // 让原生的FormData做处理
                contentType: false,  // 让原生的FormData做处理
                success:function (arg) {
                    var tag = document.createElement('img');
                    tag.src = "/"+ arg;
                    $('#container2').append(tag)
                }
            })
            
        }
        function  upload3() {
            document.getElementById('ifr').onload = loadIframe;
            document.getElementById('f1').submit();
        }
        function loadIframe() {
            var content = document.getElementById('ifr').contentWindow.document.body.innerText;
            var tag = document.createElement('img');
            tag.src = "/"+ content;
            $('#container3').append(tag)
        }
    </script>
</body>
</html>

总结:

伪Ajax兼容性更好(建议上传文件时使用),数据传输时建议使用JQuery

4 JSONP技术

4.1 Ajax存在的问题

  • 访问其他域名的URL会被阻止
  • 浏览器:
    • 同源策略,Ajax跨域发送请求时,再回来时浏览器拒绝接受
    • 允许script标签

4.2 JSONP的本质

templates.jsonp.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/commons.js"></script>
</head>
<body>
<a onclick="sendMsg();">发送</a>

<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    function sendMsg() {
        // ajax会存在跨域问题
        /*
        $.ajax({
            url: 'http://dig.chouti.com/',
            type: 'GET',
            success:function (arg) {
                console.log(arg)
            }
        })
        */
        // 报错:XMLHttpRequest cannot load http://dig.chouti.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8001' is therefore not allowed access.
        
        // JSONP
        var tag = document.createElement('script');
        tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';  // 返回list(数据)
        document.head.appendChild(tag); 
    }
</script>

</body>
</html>

/static/commons.js

function list(arg) {
    console.log(arg);
}
原文地址:https://www.cnblogs.com/wanyuetian/p/7152829.html