Django Ajax序列化与反序列化

JavaScript/前端
360
0
0
2023-02-15

序列化与反序列是最常用的功能,有时我们需要将一个表单组打包成Json格式等然后再提交给服务端,这样可以提高效率节约带框,如下是Django配合Ajax实现的序列化与反序列化,文件上传等操作。

Ajax序列化与反序列化: 前端Ajax通过序列化发送JSON数据,后端通过反序列化接收数据并处理数据.

<!-- name: index.html -->
<div>
    <p><input type="text" name="username" placeholder="输入用户名"></p>
    <p><input type="password" name="password" placeholder="输入用户密码"></p>
    <p><button class="Send_AJAX">发送数据</button><span class="ErrorTag"></span></p>
</div>

<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(".Send_AJAX").click(function () {
        var username = $('input[name="username"]').val();
        var passowrd = $('input[name="password"]').val();

        $.ajax({
            url:"/_ajax/",
            type:"POST",
            contentType:"application/json;charset=utf-8",
            data:JSON.stringify({ username: username, password: passowrd }), // 序列化
            success:function (data) {
                var data = JSON.parse(data);        // 反序列化
                if(!data["flag"]){
                    $(".ErrorTag").html("用户名或密码错误");
                }else{
                    $(".ErrorTag").html("密码输入正确");
                }
            },
            error:function (data) {
                alert('未知错误,数据通信失败!');
            }
        });
    })
</script>

视图层

# name: views.py
from django.shortcuts import render,HttpResponse
import json

def index(request):
    return render(request,"index.html")

def _ajax(request):
    data = request.body.decode("utf-8")
    json_data = json.loads(data)         # 加载返回的json数据
    host = request.get_host()            # 得到远程主机IP地址
    port = request.get_port()            # 得到远程主机端口
    response = {}
    username = json_data.get("username")
    password = json_data.get("password")

    if username == "admin" and password == "123123":
        response['flag'] = True
    else:
        response['flag'] = False
    return HttpResponse(json.dumps(response))

路由层

# name: urls.py
from django.contrib import admin
from django.urls import path

from MyWeb import views
urlpatterns = [
    path("",views.index),
    path('_ajax/',views._ajax),
]

Ajax局部序列化与全局序列化: 实现前端标签的局部序列化与全局序列化功能.

<!--name: index.html-->
<form action="/_Ajax/" method="post" id="myForm">
    <input type="text" name="username" value="默认数据"></input>
    <select name="grade" id="grade">
        <option value="1">一年级</option>
        <option value="2">二年级</option>
    </select>

    <input name="sex" type="radio" checked="checked" value="1"></input>
    <input name="sex" type="radio" value="0" /></input>
    <input name="hobby" type="checkbox" value="1" />游泳</input>
    <input name="hobby" type="checkbox" value="2" />跑步</input>
    <input name="btn" id="btn" type="button" value="提交数据"></input>
</form>

<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $("#btn").click(function(){
        $.ajax({
            url: "./_Ajax/",
            type: "POST",
            //data: $("#myForm").serialize(),                 // 序列化整个myForm表单
            data: $("#myForm").serialize(":text,:checkbox"),  // 只序列化其中的两个
            success:function (data) {
                var data = JSON.parse(data);
                if(data["status"] == "ok")
                {
                    alert("后端已经接收到了.")
                }
            }
        })
    })
</script>

视图层

# name: views.py
from django.shortcuts import render,HttpResponse
import json

def index(request):
    return render(request,"index.html")

def _Ajax(request):
    username = request.POST.get("username")
    grade = request.POST.get("grade")
    sex = request.POST.get("sex")
    hobby = request.POST.get("hobby")
    print("用户名:{} 年级:{} 性别:{} 爱好:{}".format(username,grade,sex,hobby))

    return HttpResponse(json.dumps({"status":"ok"}))

路由层

# name: urls.py
from django.contrib import admin
from django.urls import path

from MyWeb import views
urlpatterns = [
    path("",views.index),
    path('_ajax/',views._ajax),
]

ajax实现伪Socket: 伪socket实现的方式就是通过短轮询的方式实现,前端一直请求后台接口。

index.html
    <script src="https://lyshark.com/cdn/jquery/3.5.1/jquery.min.js" type="text/javascript"></script>
    <link rel="stylesheet" href="https://lyshark.com/cdn/xterm/xterm.css" />
    <script src="https://lyshark.com/cdn/xterm/xterm.js"></script>

    <div class="panel panel-primary">
        <div class="panel-footer">
            <input type="text" id="command" placeholder="执行命令" style="width:400px;height:40px"/>
            <input type="button" value="执行命令" onclick="sendData()">
        </div>
    </div>
    <script type="text/javascript">
        $(
            <!--设置定时器-->
            function () {
                fetchData();
                setInterval(fetchData, 100);
            }
        );

        <!-- 接收数据走GET-->
        function fetchData(){
            $.ajax({
                url:"/_ajax/",
                type:"GET",
                dataType: 'json',
                success:function (recv) {
                    console.log(recv.response);
                }
            })
        }

        <!-- 发送数据默认走POST-->
        function sendData()
        {
            var command = $("#command").val();
            console.log(command);
            $.ajax({
                url:"/_ajax/",
                type:"POST",
                contentType:"application/json;",
                data: JSON.stringify({"command":command}),
                success:function (send) {

                }
            })
    }
    </script>
</head>

视图层

views.Py

from django.shortcuts import render,HttpResponse
import json

def index(request):
    return render(request,"index.html")

def _ajax(request):
    if request.method == "GET":
            return HttpResponse(json.dumps({"response": "abcde"}))
    else:
        data = request.body.decode("utf-8")
        json_data = json.loads(data)

        command = json_data.get("command")
        print(command)
        return HttpResponse("ok")

路由层

urls.Py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('_ajax/',views._ajax)
]

Ajax 同源跨域操作: 针对同源策略的跨域读取数据

<p class="ShowList"></p>
<input type="button" value="跨域获取数据" onclick="Ajax()" />

<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
    function Ajax() {
        $.ajax({
            url: "http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403",
            contentType: "GET",
            dataType: "jsonp",
            jsonp: "callback",
            jsonpCallback: "list",       // 此处的List必须与网站中的callback一致
            success:function (data) {
                var week_list = data.data;
                $.each(week_list,function (key,value) {
                    //console.log(key,value);   // 0 {week: "周日", list: Array(19)}
                    var str = value.week;
                    //console.log(str)             // 周日 周一 周二
                    //$(".ShowList").append(str);  // 给上方标签插入数据
                    $.each(value.list,function (k,v) {
                        //console.log(k,v);  //{time: "1730", name: "《地宝当家》", link: "http://xxx.cn"}
                        var name = v.name;    // 取出电台名字
                        var link = v.link;    // 取出它的地址
                        $(".ShowList").append(name,link,"</br>");  // 获取到电台节目
                    });
                });
            }
        });
    }
</script>

Ajax实现文件上传操作: 简单实现文件上传功能。

<!--name: index.html-->
<input type="file" id="upload">
<p><button class="btn">上传文件</button><span class="alert"></span></p>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(".btn").click(function(){
        var formData = new FormData();
        formData.append("file",$("#upload")[0].files[0]);
        $.ajax({
            url: "/put_file/",
            type: "POST",
            data:formData,
            contentType: false,
            processData: false,
            success:function (data) {
                $(".alert").html("上传成功")
            }
        })
    })
</script>

视图层

# name:views.py
from django.shortcuts import render,HttpResponse

def index(request):
    return render(request,"index.html")
def put_file(request):
    if request.method == "POST":
        file_obj = request.FILES.get("file")
        with open(file_obj.name,"wb") as f:
            for item in file_obj:
                f.write(item)
        return HttpResponse("上传完成")

Ajax局部序列化: 通过Ajax序列化功能实现用户登录后验证是否正确,并返回结果到前台.

首先是前端index.html其引入Jquery库,并使用Ajax与后端通信.

<div>
    <p><input type="text" name="username" placeholder="输入用户名"></p>
    <p><input type="password" name="password" placeholder="输入用户密码"></p>
    <p><button class="send_ajax">发送数据</button><span class="ErrorTag"></span></p>
</div>

<script src="https://cdn.lyshark.com/jquery/3.5.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $(".send_ajax").click(function () {
        var username = $('input[name="username"]').val();
        var passowrd = $('input[name="password"]').val();
        $.ajax({
            url:"/_ajax/",
            type:"POST",
            contentType:"application/json;charset=utf-8",
            data:JSON.stringify({ username: username, password: passowrd }), // 序列化
            success:function (data) {
                var data = JSON.parse(data);                                // 反序列化
                if(!data["flag"]){
                    $(".ErrorTag").html("用户名或密码错误");
                }else{
                    $(".ErrorTag").html("密码输入正确");
                }
            },
            error:function (data) {
                alert('未知错误,数据通信失败!');
            }
        });
    })
</script>

其次是后端,通过views.py中的两个方法对用户发送的数据进行验证,并返回JSON格式的回执信息.

from django.shortcuts import render,HttpResponse
import json

def index(request):
    return render(request,"index.html")

def _ajax(request):
    data = request.body.decode("utf-8")
    json_data = json.loads(data)         # 加载返回的json数据
    host = request.get_host()            # 得到远程主机IP地址
    port = request.get_port()            # 得到远程主机端口
    response = {}
    username = json_data.get("username")
    password = json_data.get("password")

    if username == "admin" and password == "123123":
        response['flag'] = True
    else:
        response['flag'] = False
    return HttpResponse(json.dumps(response))

最后是urls.py路由层,分别添加两个路由选项.

from django.contrib import admin
from django.urls import path
from MyWeb import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',views.index),
    path('_ajax/',views._ajax)
]

Ajax全局序列化: 全局序列化的主要作用是批量提交数据,可使用serialize进行全局提交.

前端index.html代码如下,基本上没有太大变化.

<form action="/_ajax/" method="post" id="myForm">
    <input type="text" name="username" value="默认数据"></input>

    <select name="grade" id="grade">
        <option value="1">一年级</option>
        <option value="2">二年级</option>
    </select>

    <input name="sex" type="radio" checked="checked" value="1"></input>
    <input name="sex" type="radio" value="0" /></input>
    <input name="hobby" type="checkbox" value="1" />游泳</input>
    <input name="hobby" type="checkbox" value="2" />跑步</input>

    <input name="btn" id="btn" type="button" value="提交数据"></input>
</form>

<script src="https://cdn.lyshark.com/jquery/3.5.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
    $("#btn").click(function(){
        $.ajax({
            url: "./_ajax/",
            type: "POST",
            data: $("#myForm").serialize(),                      // 序列化整个myForm表单
            // data: $("#myForm").serialize(":text,:checkbox"),  // 只序列化其中的两个
            success:function (data) {
                var data = JSON.parse(data);
                if(data["status"] == "ok")
                {
                    alert("后端已经接收到了.")
                }
            }
        })
    })
</script>

后台中的views.py视图函数需要变化一下,我们可以根据自己的需要接收不同的参数,路由不变.

from django.shortcuts import render,HttpResponse
import json

def index(request):
    return render(request,"index.html")

def _ajax(request):
    username = request.POST.get("username")
    grade = request.POST.get("grade")
    sex = request.POST.get("sex")
    hobby = request.POST.get("hobby")
    
    print("用户名:{} 年级:{} 性别:{} 爱好:{}".format(username,grade,sex,hobby))
    
    return HttpResponse(json.dumps({"status":"ok"}))

Ajax 实现上传文件: 文件上传需要使用Ajax中的FormData这个对象,来实现文件上传功能.

前端index.html代码需要需改为如下样子.

<input type="file" id="upload">
<p><button class="btn">上传文件</button><span class="alert"></span></p>
<script src="https://cdn.lyshark.com/jquery/3.5.1/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript">
    $(".btn").click(function(){
        var formData = new FormData();
        formData.append("file",$("#upload")[0].files[0]);
        $.ajax({
            url: "/_ajax/",
            type: "POST",
            data:formData,
            contentType: false,
            processData: false,
            success:function (data) {
                $(".alert").html("上传成功")
            }
        })
    })
</script>

后端views.py视图则需要接受参数并打开文件实现上传,上传后的名字由request.FILES字段取得.

from django.shortcuts import render,HttpResponse

def index(request):
    return render(request,"index.html")

def _ajax(request):
    if request.method == "POST":
        file_obj = request.FILES.get("file")
        with open(file_obj.name,"wb") as f:
            for item in file_obj:
                f.write(item)
        return HttpResponse("上传完成")

Ajax 实现在线编辑器: 使用Ajax配合codemirror框架实现的在线文本编辑器.

前端index.html代码如下.

 <link rel="stylesheet" href="https://cdn.lyshark.com/codemirror/codemirror.css"/>
<script src="https://cdn.lyshark.com/codemirror/codemirror.js"></script>
<script src="https://cdn.lyshark.com/jquery/3.5.1/jquery.min.js" type="text/javascript"></script>

<div>
    <textarea className="form-control" id="code" name="code"></textarea>

    <p>输入文件路径: <input type="text" name="file_path" placeholder="输入文件路径"></p>
    <p><button class="open_ajax">打开文件</button></p>
    <p><button class="save_ajax">保存文件</button></p>
</div>

<script type="text/javascript" charSet="utf-8">
    var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
        theme: "neat",        // 设置主题
        lineNumbers: true,	  // 显示行号
        indentUnit: 4,         // 缩进单位为4
        styleActiveLine: true, // 当前行背景高亮
        matchBrackets: true,   // 括号匹配
        mode: 'htmlmixed',     // HMTL混合模式
        lineWrapping: true,    // 自动换行
        foldGutter: true,
        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
    });
    editor.setSize('500px', '400px');    // 设置框架大小
    editor.setValue("");                 // 给代码框赋值
    editor.getValue();                   // 获取代码框的值
</script>

<script type="text/javascript" charSet="utf-8">
    // 执行打开文件
     $(".open_ajax").click(function () {
            var file_path = $('input[name="file_path"]').val();
            $.ajax({
                url:"/_ajax/",
                type:"POST",
                contentType:"application/json;charset=utf-8",
                data:JSON.stringify({ type: "open", file_path: file_path }),
                success:function (data) {
                    editor.undo();
                    editor.setValue(data);
                },
                error:function (data) {
                    editor.setValue("error");
                }
            });
        })

     // 执行保存文件的过程
     $(".save_ajax").click(function(){
         var file_path = $('input[name="file_path"]').val();
         $.ajax({
                url:"/_ajax/",
                type:"POST",
                contentType:"application/json;charset=utf-8",
                data:JSON.stringify({ type:"save", file_path: file_path ,save_data: editor.getValue() }),
                success:function (data) {
                    editor.setValue("save as success");
                },
                error:function (data) {
                    editor.setValue("error");
                }
            });
     })
</script>

后端views.py视图层代码.

from django.shortcuts import render,HttpResponse
import json

def index(request):
    return render(request,"index.html")

def _ajax(request):
    data = request.body.decode("utf-8")
    json_data = json.loads(data)

    type = json_data.get("type")
    file_path = json_data.get("file_path")

    if (type == "open"):
        with open(file_path,"r") as fp:
            ref = fp.readlines()
        return HttpResponse(ref)

    elif(type == "save"):
        save_data = json_data.get("save_data")
        with open(file_path,"w") as fp:
            fp.write(save_data)
        return HttpResponse("ok")
    return HttpResponse("none")