• Django学习 之后端视图与ajax


    .Ajax简介

    在此之前你一定需要先学习下JavaScript JSON 可见:

    前端学习 之 JavaScript 之 JSON

    1、简单介绍

    我们以前知道的前端向后端发送数据的方式有:

      GET:地址栏、a标签、Form表单

      POST:Form表单

    那么现在我们在学习一种:那就是ajax

    ajax:也是前端向后端发送数据的一种方式

    AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

    AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。

    同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;

    异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

    Ajax的特点(优点)

      异步交互: 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

      局部刷新:    整个过程中页面没有刷新,只是刷新页面中的局部位置而已!

    二.jQuery实现Ajax

    前提是在Django框架上,并已经做相关的基础配置后。

    前端代码:

    <body>
    {% csrf_token %}
    <p><input type="text" class="user" placeholder="用户名"></p>
    <p><input type="password" placeholder="密码" class="pwd"></p>
    <button id="ajaxTest">AJAX 测试</button>
     <script src="/static/js/jquery.js"></script>
    <script>
        $("#ajaxTest").click(function () {
            var username = $(".user").val();
            var password = $(".pwd").val();
            console.log(username, password);
            $.ajax({
                url: "/jq_ajax/",
                type: "POST",
                data: {
                    csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
                    user: username,
                    pwd: password,
                },
                success: function (res) {
                    alert("hahaha")
                    //未来接收服务端返回值,来进行做判断做的相应的反应
                    if (res == "ok"){
                        alert("okla")
                    }else{
                        alert("buok.")
                    }
                }
            })
        })
    </script>
    </body>
    View Code

    后端代码:

    def jq_ajax(request):
    
        # if request.method == "GET":
    
     
    
        if request.is_ajax():
    
            username = request.POST.get("user")
    
            password = request.POST.get("pwd")
    
            print(username, password)
    
            return HttpResponse("okddd")
    
     
    
    return render(request, "jq_ajax.html")
    views.py

    .Ajax案例

    1.用户名是否已被注册

    在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回true或false,返回true表示这个用户名已经被注册过,返回false表示没有注册过。客户端得到服务器返回的结果后,确定是否在用户名文本框后显示“用户名已被注册”的错误信息!

    2.基于Ajax进行登录验证

    用户在表单输入要注册用户名,用户单击框外,网页通过Ajax提交给服务器,服务器验证用户名是否存在后返回响应信息,客户端通过响应信息做出相应的提醒,可以注册不提醒,否则在页面上显示登录用户名已经被使用!

    .Ajax实现一个计算案例

    前端代码为:

    <body>

    <h3>计算案例</h3>

    {% csrf_token %}

    <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"> <button id="btn1">计算</button>

    <span id="err"></span>

    <script src="/static/js/jquery.js"></script>

    <script>

        $("#btn1").click(function () {

            var i1 = $("#i1").val()

            var i2 = $("#i2").val()

            $.ajax(

                {

                    url:"/add_test/",

                    type: "post",

                    data:{

                        csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),

                        i1:i1,

                        i2:i2,

                    },

                    success : function (ret) {

                        {#var ret = JSON.parse(ret);   //在django后端用的是JsonResponse就不用反序列化了#}

                        console.log(ret,typeof ret);

                        if (ret.status){

                            $("#i3").val(ret.msg);

                        }else {

                            $("#err").text(ret.msg);

                            // 过三秒后自动消失

                            setTimeout(function () {

                                $("#err").text("");

                            },3000)

                        }

                        {#$("#i3").val(res)#}

                    }

                }

            )

        })

    </script>

    </body>

    后端django视图函数为:

    from django.http import JsonResponse

    import json

    def add_test(request):

        if request.is_ajax():

            ret = {"status": 1, "msg": None}

            num1 = request.POST.get("i1")

            num2 = request.POST.get("i2")

            try:

                res = int(num1) + int(num2)

                ret['msg'] = res

            except ValueError as e:

                ret['status'] = 0

                ret['msg'] = "请核对输入的数据的合法性"

            # return HttpResponse(json.dumps(ret))  

    //如果用到 JsonResponse就不需要序列化了

            return JsonResponse(ret)

        return render(request, "add_test.html")

    .基于Ajax上传json数据

    1.前端模板代码

    <body>

    {% csrf_token %}

    <h3>json 数据</h3>

    <p><input type="text" class="user" placeholder="用户名"></p>

    <p><input type="password" placeholder="密码" class="pwd"></p>

    <button id="ajaxTest">AJAX json 测试</button>

    <script src="/static/js/jquery.js"></script>

    <script>

            $("#ajaxTest").click(function () {

            var user = $(".user").val();

            var pwd = $('.pwd').val();

            $.ajax({

                url: "",

                type: 'POST',

                //注意T大写

                contentType: "json",

                headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf

                // json 前端的序列化方式

                data: JSON.stringify({

                    user: user,

                    pwd: pwd,

                    {#csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),#}

                }),

                success: function (ret) {

                    console.log(ret)

                }

            })

        })

    </script>

    </body>

    2.后端视图代码

    def json_test(request):

        if request.is_ajax():

            print(request.POST)  # json时,post为空

            print(request.body)  # 如果前端没有序列化就是原生请求体内容,如果序列化的就是字典(其实是byte类型)

            data_str = request.body.decode()

            data = json.loads(data_str)

            print(data, type(data))  # 是字典类型

            # print(data.get('user'), type(data))

            return HttpResponse("ok")

    return render(request, "json_test.html")

    总结:

    前端:

        $.ajax({

            url: "", # 默认往当前url提交

            type: "post", #请求方式

            contentType: "json",

            headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf

            data: JSON.stringify({

             key1: val1,

                key2: val2,

                ...

            },

                success: function(ret){

                    console.log(ret)

                }

        })

    后端:

        request.POST     # 为空

        request.body    # b'{"user":"alex","pwd":"123"}'

            1. 转换成字符串

            2. 反序列化  # dict1 = json.loads(request.body.decode())

    .基于form表单上传文件

    1.前端模板代码

    <body>
    
    <h3>文件上传</h3>
    
    <form action="" method="post" enctype="multipart/form-data">
    
        {% csrf_token %}
    
        <input type="file" name="f_name">
    
        <input type="submit" value="上传">
    
    </form>
    
    </body>
    View Code

    2.后端视图代码

    import os

    def upload(request):

        if request.method == "GET":

            return render(request, 'upload.html')

        else:

            print(request.POST)   # <class 'str'> 没有意义

            # print(request.body) #  enctype="multipart/form-data"   ,会报错

            print(request.FILES.get('f_name'), type(request.FILES.get('f_name')))

    # 类型是一个对象

            file_obj = request.FILES.get('f_name')

            print(file_obj.name)

            with open(os.path.join("media",file_obj.name),mode="wb") as fp:

                for i in file_obj:

                    fp.write(i)

            return HttpResponse("ok")

     .基于Ajax请求上传文件

    1.前端模板代码

    <body>

    <h3>ajax 文件上传</h3>

        {% csrf_token %}

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

        <input type="button" value="上传" id="btn1">

    <script src="/static/js/jquery.js"></script>

    <script>

        $("#btn1").click(function () {

            // 封装数据

            let formdata = new FormData();

            formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());

            // f_name 传到后端当字典的键,另外一个则是一个对象

            formdata.append('f_name', $("#file_id")[0].files[0]);

            // 处理ajax请求

            $.ajax({

                url: "",

                type: "POST",

                processData: false,  // 告诉jQuery不要去处理发送的数据

                contentType: false,  // 告诉jQuery不要去设置Content-Type请求头

                data: formdata,

                // 成功后返回的数据

                success: function (ret) {

                    console.log(ret)

                }

            })

        })

    </script>

    </body>

    获取页面的文件对象步骤:

    2.后端视图代码

    def upload_ajax(request):

        if request.method == "GET":

            return render(request, "upload_ajax.html")

        else:

            print(request.POST)

            # print(type(request.POST.get("fi_name1")))  #<class 'str'> 没有意义

            # print(request.body)   #  enctype="multipart/form-data"   ,会报错

            print(request.FILES)

            print(request.FILES.get('f_name'))

            print(type(request.FILES.get('f_name')))

            file_obj = request.FILES.get('f_name')

            print(file_obj.name)

            with open(os.path.join("media", file_obj.name), "wb") as f:

                for i in file_obj:

                    f.write(i)

            return HttpResponse("ok")

    后端视图代码基本和基础表单上传文件的一样。

    .ContentType 类型

    ContentType指的是请求体的编码类型,常见的类型共有3种:

    1.application/x-www-form-urlencoded(默认类型)

        这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):

    POST http://www.example.com HTTP/1.1

    Content-Type: application/x-www-form-urlencoded;charset=utf-8

    user=hsz&age=22

    2.multipart/form-data(用于form上传文件时)

    这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:

    POST http://www.example.com HTTP/1.1

    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA

    Content-Disposition: form-data; name="user"

    hsz

    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA

    Content-Disposition: form-data; name="file"; filename="chrome.png"

    Content-Type: image/png

    PNG ... content of chrome.png ...

    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

    这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。

        这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

        上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。

    随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

    3.application/json(用于json)

    application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

        JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

  • 相关阅读:
    sprin AOP
    springDI注解
    Spring学习
    cookie、session、token三者之间的关系
    解决报错:Cannot find module 'webpack-cli/bin/config-yargs'
    Vue全家桶-前端工程化
    Vue全家桶-前端路由
    Vue
    Git
    Ajax
  • 原文地址:https://www.cnblogs.com/hszstudypy/p/11180553.html
Copyright © 2020-2023  润新知