python学习:Django使用Ajax和序列化(7)

Django使用Ajax和序列化

        Ajax可以在不刷新页面的情况下,局部更新页面数据。使用Ajax需要引入JQuery库,使用JQuery的Ajax。

        下载JQuery库,http://www.jq22.com/jquery-info122

   

        解压得到jquery-3.4.1.js和jquery-3.4.1.min.js,这两个js文件都可以使用,但是大小不同,一般开发时可以使用jquery-3.4.1.js,而正式项目使用jquery-3.4.1.min.js。

   

        将解压得到的jquery-3.4.1.js拷贝到Django项目建立的静态资源文件夹statics。

 

使用Ajax步骤:

1、引入JQuery文件;

2、使用Ajax,Ajax格式:

        $.ajax({

                url : “”,    

                type:”POST”,

                data:{“name”:“tang”,”pwd”,”123”},

                success:function(arg){

                        //回调函数

                }

})

 

示例:

新建一个ajax.html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax使用</title>
    <script>
        //ajax的data是一个字典类型,键可以用'name',也可以直接name;但是value不能是字典,如果要传递字典值使用JSON.stringify()将字典值转换成字符串。
        //设置traditional:true,传递键值可以是list
        //设置dataType:'JSON',后端传来json字符串,arg自动变成对应对象,就可以不需要JSON.parse转换

        function submit(){
            var user = $("#user").val();
            var pwd = $("#pwd").val();
            var sel = $("#sel").val();
            console.log(user,pwd,sel);

            $.ajax({
                url:"/url_dispatch/ajax1",
                type:"GET",
                data:{name:user,pwd:pwd,sel:sel},
                traditional:true,
                success:function(arg){
                    //回调函数
                    console.log(arg);
                    //后端传过来JSON字符串,转换成对象
                    var arg_obj = JSON.parse(arg);
                    alert(arg_obj.name)
                    //刷新页面
                    //window.location.reload();
                }
            });
        }
    </script>
</head>
<body>
    <p><input type="text" id = "user" name="user"></p>
    <p><input type="password" id = "pwd" name="pwd"></p>
    <!--多选-->
    <p>
        <select id="sel" multiple>
            <option value="1">选项1</option>
            <option value="2">选项2</option>
            <option value="3">选项3</option>
        </select>
    </p>
    <p><input type="button" value="提交" onclick="submit()"></p>
    <!--导入jquery-->
    <script src="/static/jquery-3.4.1.js"></script>
</body>
</html>

 

修改urls.py文件,增加返回ajax.html的url,以及处理ajax请求的url

path("ajax/",views.ajax),

path("ajax1/",views.ajax1)

修改views.py,增加对应视图函数

#处理ajax请求

def ajax1(request):

    #使用GET
    # 可以获取到ajax传的数据data
    #如果传入是value为列表,sel键会自动加上[],所以我们直接使用键获取不到值
    #我们需要在ajax请求中加一个参数traditional:true
    #<QueryDict: {'name': ['1'], 'pwd': ['ere2121'], 'sel[]': ['2', '3']}>
    print(request.GET);
    print(request.GET.get("name"))
    print(request.GET.get("pwd"))
    #getlist获取多个值
    print(request.GET.getlist("sel"))

    #后端返回一个json字符串
    jsonDict = {"name":"tang","age":11,"addr":"chongqing"}
    #使用json.dumps将对象转换成一个Json字符串
    import json
    jsonStr = json.dumps(jsonDict);
    return HttpResponse(jsonStr)
#返回页面 def ajax(request): return render(request,"ajax.html")

 

使用serialize(),直接将form表单的数据变成ajax传输数据。

在ajax.html中增加一个form表单,设置id

<form id="serialize_form">
    name:<input type="text" name="name"></br>
    age:<input type="number" name="age"></br>
</form>
<p><input type="button" value="提交form" onclick="submit1()"></p>

 

编写对应js代码,绑定点击事件响应:

function submit1(){

     $.ajax({
        url:"/url_dispatch/ajax2",
        type:"GET",
        data: $("#serialize_form").serialize(),
        traditional:true,
        success:function(arg){
            //回调函数
            console.log(arg);
        }

    });

}

 

修改urls.py,增加ajax跳转url路径

path("ajax2/", views.ajax2)

修改views.py,编写对应视图函数,获取form表单提交数据

#获取serialize()表单参数

def ajax2(request):

    #<QueryDict: {'name': ['fdf'], 'age': ['1']}>

    print(request.GET);

    return  HttpResponse("ok")

 

 

数据序列化

       后端将数据序列化字符串格式,传入到前端,前端将数据反序列化,拿到数据渲染到页面上。

示例:

#序列化

from django.core import serializers

from helloApp.models import Book

import json

def ajax3_serial(request):

    #返回数据

    ret = {"status":False,"data":None}

    #使用查询,book_list是一个querySet对象

    try:

        #查询出querySet,querySet中是对象

        book_list = Book.objects.all();

        # ret["data"] = book_list;

        #使用serializer序列化book_list,变成字符串

        # 这里相当于两次序列化,前端使用dataType:"JSON",arg是个对象,arg.data拿到字符串,然后使用JSON.parse(arg.data)再次反序列化,拿到对象列表

        ret["data"] = serializers.serialize(book_list);

        ret["status"] = True;

 
        # #使用values查询的querySet中是字典

        # book_list = Book.objects.values("name")

        # #直接使用list(book_list)转化为一个list,就可以直接使用json.dump(ret)转换

        # ret["data"] = list(book_list);

        # ret["status"] = True;

    except Exception as e:

        ret["data"] = e

    #直接使用json.dump(),不能序列化querySet

    #将book_list变成字符串,就可以使用json.dump序列化

    return HttpResponse(json.dump(ret))

    #serializers不能序列化字典,可以序列化queryset

    # return HttpResponse(serializers.serialize(ret));

 

 

Ajax补充

1、XMLHttpRequest,手动请求和jquery请求

       如果不使用jQuery的Ajax提交请求,我们可以使用XMLHttpRequest对象,原生Ajax请求。

       使用步骤:1、创建XMLHttpRequest对象;2、调用open(“method”,url),method为POST或者GET;3、编写回调方法onreadystatechange(),判断readyState == 4成功返回;4、send()方法调用请求

示例:

修改ajax.html,添加提交请求按钮,绑定事件

<!--

    原生请求

    不使用jquery提供的Ajax,实现Ajax提交

    -->

<h1>原生提交GET请求</h1>

<p><button name="btn1" onclick="submit2()">GET提交</button></p>

<h1>原生提交POST请求</h1>

<p><button name="btn2" onclick="submit3()">POST提交</button></p>

编写对应js的方法

//GET提交

function submit2(){

    //创建XMLHttpRequest对象

    var xmlRequest = new XMLHttpRequest();

    xmlRequest.open("GET",'/url_dispatch/ajax4?p = 12');

    //回调函数

    xmlRequest.onreadystatechange = function(){

        if(xmlRequest.readyState == 4){

            console.log(xmlRequest.responseText);

        }

    }

    xmlRequest.send(null);

}

//POST提交

 function submit3(){

    //创建XMLHttpRequest对象

    var xmlRequest = new XMLHttpRequest();

    xmlRequest.open("POST",'/url_dispatch/ajax4/');

    //回调函数

    xmlRequest.onreadystatechange = function(){

        if(xmlRequest.readyState == 4){

            console.log(xmlRequest.responseText);

        }

    }

    //post提交,要获取数据,需要设置请求头

    xmlRequest.setRequestHeader("content-type","application/x-www-form-urlencoded;charset=UTF-8");

    xmlRequest.send("p=12");

}

 

2、‘伪’Ajax

       使用iframe和form伪造Ajax请求。Iframe和form通过form表单的target属性连接起来,让form表单的target等于iframe标签的name属性。

修改ajax.html,添加form和iframe标签

<!--iframe伪造请求

    form配合iframe,form提交请求,iframe获取服务器返回数据,不刷新页面

    iframe获取到数据,

    -->

<h1>Iframe</h1>

<iframe id="iframe" name="ifr" onload="reloadIframe(this)"></iframe>

<form method="get" action="/url_dispatch/ajax4/" target="ifr">

    <input type="text" name="test">

    <input type="submit" value="提交">

</form>

编写处理iframe获取到数据库返回值的回调函数

//Iframe伪造回调函数

function reloadIframe(th){

    //获取返回内容

    console.log(th.contentWindow.document.body.innerHTML);

    //使用jQuery获取内容

    console.log($(th).contents().find("body").html());

}

3、Ajax上传文件

       使用FormData对象,打包数据,将input框选择的文件打包,可以使用原生xmlHttpRequest.send(data)发送,也可以jQuery的ajax发送。

示例:

修改ajax.html,添加文件选择框input

<h1>formData文件上传</h1>

<input type="file" id="files">

<button onclick="submit4()">提交</button>

编写js代码获取数据,sumit4()方法

function submit4(){

      //创建formData对象

    var data = new FormData();

    //将数据加入FormData

    data.append("files",document.getElementById("files").files[0]);

    $.ajax(){

        url:"/url_dispatch/ajax4",

        type:"GET",

        data: data,

        //使用FormData提交需要processData,contentType参数

        processData:false,

        contentType:false,

        success:function(arg){

            //回调函数

            console.log(arg);

        }

    }

}

 

       使用Iframe和Form表单上传文件。

示例:

修改ajax.html,增加上传文件form表单,和iframe标签。

<h1>Iframe文件上传</h1>

<iframe id="iframe1" name="ifr1"></iframe>

<form id="form1" method="post" action="/url_dispatch/ajax4/" enctype="multipart/form-data" target="ifr1">

    <input type="file" name="files">

    <button onclick="submit5()">提交</button>

</form>

 

增加js代码,提交表单

//回调函数,获取返回文件

function reloadIframe1(){

    //获取返回内容

    console.log(this.contentWindow.document.body.innerHTML);

    //使用jQuery获取内容

    console.log($(this).contents().find("body").html());

}

//使用Ifrme上传文件

function submit5(){

//绑定onload函数

    document.getElementById("iframe1").onload = reloadIframe1;

      //提交表单

    document.getElementById("form1").submit();

}

 

4、跨域Ajax,JSONP

使用JSONP跨过同源策略。

示例:

修改ajax.html,jsonp实现过程其实是生成一个<script>块,指定src属性为远程url的标签,通过函数获取返回值。

<h1>Jsonp跨域访问</h1>

<!--浏览器有同源策略

            XMLHttpRequest遵循策略,只能访问本服务器,不能获取其他服务器返回内容

            JSONP越过浏览器同源策略

            <img src="">可以是其他服务器的路径

            <iframe src="">也可以是其他服务器路径

            这些标签没有同源策略限制

    -->

<button onclick="submit6()">提交</button>

 

编写js代码,ajax使用jsonp跨过同源策略限制,jsonp只能发送GET请求

//dataType:"jsonp"使用jsonp越过同源策略

//jsonpCallback指定回调处理函数

//服务器返回就是list()包裹数据,调用list(arg)函数,arg可以直接访问到返回内容

function submit6(){

    $.ajax({

        //url:"http://www.baidu.com",

        url:"/url_dispatch/ajax4",

        type:"GET",

        dataType:"jsonp",

        jsonp:"callback",

        jsonpCallback:"list"

    })

}

//回调函数

function list(arg){

    console.log(arg)

}

 

修改对应url的视图函数返回字符串格式,必须使用:callback指定的名字(返回字符串)。

#不依赖jquery,使用Ajax

def ajax4(request):

    # print(request.GET)

    # print(request.POST)

    # print(request.FILES)

    #  return  HttpResponse("ok");

 

    #同源策略跨过

    #使用callback指定名字返回字符串

    name = request.GET.get('callback')

    print(name);

    #jsonpCallback:"list",callback名字

    #返回数据:指定callback的名字(返回数据)

    return HttpResponse("%s('hello world')" %(name,))

 

    #方式2

    # #使用增加相应头,声明不使用同源策略

    # obj = HttpResponse("hello world")

    # obj["Access-Control-Allow-Origin"] = "*"

    # return  obj;

 

json序列化自定义类型

示例:

#json序列化自定义类型

import json

from datetime import datetime

#自定义json解释器,继承JSONEncoder

class MyJsonEncoder(json.JSONEncoder):

    def default(self, o):

        #是否是时间类型

        if isinstance(o,datetime):

            return o.strftime("%Y-%m-%d %H %M %S")

        elif isinstance(o,c1):

            return  o.__dict__

        else:

            return  json.JSONEncoder.default(self,o)

class c1:

    def __init__(self,name,addr):

        self.name = name

        self.addr = addr

    def say(self):

        print("hello")

 

data_dict = {

    "d1" : "112",

    "d2" : datetime.now(),

    "d3" : c1("lu","cq")

}

# c = c1("lu","cq")

# print(c.__dict__)

ret = json.dumps(data_dict,cls=MyJsonEncoder)

print(ret)

 

posted @ 2020-12-19 14:29  渔歌晚唱  阅读(157)  评论(0)    收藏  举报