• 058.Python前端Django与Ajax



    一 Ajax简介

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

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

    AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

    优点:

    1. AJAX使用Javascript技术向服务器发送异步请求
    2. AJAX无须刷新整个页面

    二 AJAX的异步请求

    设计路由

    复制代码
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add_book/',views.add_book),
        path('query_book/',views.query_book),
        #ajax相关
        path('ajax_sleep/',views.ajax_sleep),
        path('ajax_test/',views.ajax_test),
        #前端页面
        path('ajax_temp/',views.ajax_temp),
    ]
    复制代码

    views视图文件

    复制代码
    def ajax_sleep(request):
        import  time
        time.sleep(3)
        return HttpResponse("sleep 3 senond")
    
    def ajax_test(request):
        return HttpResponse("test...")
    
    def ajax_temp(request):
        return render(request,"ajax_temp.html")
    复制代码

    html文件

    root@darren-virtual-machine:~/PycharmProjects/orm_demo# vim templates/ajax_temp.html

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    
    <script>
        $("#btn1").click(function () {
            $.ajax({
                url:"/ajax_sleep/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
        $("#btn2").click(function () {
            $.ajax({
                url:"/ajax_test/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
    </script>>
    </body>
    </html>
    复制代码

    访问http://127.0.0.1:8000/ajax_temp/,先点击ajax_sleep然后点击test,这时在sleep中间正在执sleep代码,但是在点击test,也会执行,先于sleep输出,说明是一个异步操作,同时点击test后,页面并不会刷新,是一个局部刷新的动作

    三 实现ajax的一个计算案例

    制作一个如下页面,当在前面输入两个数字,点击提交触发后,会把结果填在第三个框里

    设计路由

    复制代码
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add_book/',views.add_book),
        path('query_book/',views.query_book),
        #ajax相关
        path('ajax_sleep/',views.ajax_sleep),
        path('ajax_test/',views.ajax_test),
        #前端页面
        path('ajax_temp/',views.ajax_temp),
        #ajax求和
        path('ajax_sum/',views.ajax_sum),
    ]
    复制代码

    view视图

    复制代码
    def ajax_sum(request):
        if request.is_ajax():
            num1 = request.POST.get("num1")
            num2 = request.POST.get("num2")
            total = int(num1) + int(num2)
            return HttpResponse(total)
    复制代码

    html 

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    
    <script>
        $("#btn1").click(function () {
            $.ajax({
                url:"/ajax_sleep/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
    
        $("#btn2").click(function () {
            $.ajax({
                url:"/ajax_test/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                },
                success:function (data) {
                    $("#i3").val(data);
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    访问http://127.0.0.1:8000/ajax_temp/

     

    403报错

    是由于crfs影响,添加crfs

    修改html

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button>
    
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
                success:function (data) {
                    $("#i3").val(data);
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    再次访问,并输入计算值,点击计算

     ajax请求流程

    当输入非数字计算

    调试信息

      File "/root/PycharmProjects/orm_demo/app01/views.py", line 131, in ajax_sum
        total = int(num1) + int(num2)
    ValueError: invalid literal for int() with base 10: 'qq'
    [08/Apr/2020 03:48:19] "POST /ajax_sum/ HTTP/1.1" 500 14677

    view视图文件

    复制代码
    from django.shortcuts import render,HttpResponse
    from app01 import models
    from django.http import JsonResponse
    
    def ajax_sum(request):
        if request.is_ajax():
            num1 = request.POST.get("num1")
            num2 = request.POST.get("num2")
            ret = {"status":1,"msg":None}
            try:
                total = int(num1) + int(num2)
                ret["msg"] = total
            except Exception as e:
                ret['status'] = 0
                ret["msg"] = "请输入数字"
            #需要使用到数据结构,使用json方式传过去,先要导入jsonhttponse
            return JsonResponse(ret)
    复制代码

    html调整

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span>  {#多加一个span标签#}
    
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
            {#默认传输的值是1,就会把传过来的msg值输入,挡status值为0时,就会把自定义的提示显示,和view视图文件对应#} success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); } } }) }) </script> </body> </html>
    复制代码

    输入非数字时,会有提示

    问题,当再次输入正确格式,提示不会小时,

    使用定时器解决,显示2秒后消失

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span>
    
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
                success:function (data) {
                    if (data.status){
                        $("#i3").val(data.msg);
                    }else{
                        $("#s1").text(data.msg);
                        setTimeout(function () {
                            $("#s1").text("");
                        },2000)
                    }
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    访问后,输入错误值,两秒后消失

    四 基于Ajax上传json数据

    url设计

    复制代码
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add_book/',views.add_book),
        path('query_book/',views.query_book),
        #ajax相关
        path('ajax_sleep/',views.ajax_sleep),
        path('ajax_test/',views.ajax_test),
        #前端页面
        path('ajax_temp/',views.ajax_temp),
        #ajax求和
        path('ajax_sum/',views.ajax_sum),
        #ajax上传json数据
        path('ajax_json/',views.ajax_json),
    ]
    复制代码

    views视图文件

    视图响应时,必须是HttpResponse 或者 HttpResponse,不能是render或者redict

    复制代码
    def ajax_json(request):
        import json
        print(request.POST)
        print(request.body)
        data = json.loads(request.body.decode())
        print(data)
        return  HttpResponse("Ok")
    复制代码

    html文件

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    <button id="btn4">上传json数据</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span>
    
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 异步案例 #}
        $("#btn1").click(function () {
            $.ajax({
                url:"/ajax_sleep/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
    
        $("#btn2").click(function () {
            $.ajax({
                url:"/ajax_test/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
                success:function (data) {
                    if (data.status){
                        $("#i3").val(data.msg);
                    }else{
                        $("#s1").text(data.msg);
                        setTimeout(function () {
                            $("#s1").text("");
                        },2000)
                    }
                }
            })
        });
        $("#btn4").click(function () {
            $.ajax({
                url:"/ajax_json/",
                type: "POST",
                contentType:"json",
                headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf
                data: JSON.stringify({
                    a:100,
                    b:200,
                    user:"darren",
                }),
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    访问点击提交json数据

    得到结果

    调试输出

    <QueryDict: {}>
    b'{"a":100,"b":200,"user":"darren"}'
    {'a': 100, 'b': 200, 'user': 'darren'}

    在使用视图文件时,当使用HttpResponse返回时,前端代码需要使用json的数据,必须需要使用JSON.parse(data){}反序列化才能使用

    当使用JsonResponse(ret)返回时,可以直接使用,例如sum案例

    五 基于form表单上传文件

    下载一张图片到桌面备用,test111.png

    url文件

    复制代码
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add_book/',views.add_book),
        path('query_book/',views.query_book),
        #ajax相关
        path('ajax_sleep/',views.ajax_sleep),
        path('ajax_test/',views.ajax_test),
        #前端页面
        path('ajax_temp/',views.ajax_temp),
        #ajax求和
        path('ajax_sum/',views.ajax_sum),
        #ajax上传json数据
        path('ajax_json/',views.ajax_json),
        #form表单上传
        path('upload/',views.upload),
    ]
    复制代码

    views

    复制代码
    import  os
    def upload(request):
        if request.method == "POST":
            print(request.POST)
            print(request.FILES)
            #print(request.body)  报错
            file_obj = request.FILES.get('file_name')
            name = file_obj.name
            with open(os.path.join("media", name), "wb") as f:
                for i in file_obj:
                    f.write(i)
            return HttpResponse('上传成功')
    复制代码

    html写一个form表单

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    <button id="btn4">上传json数据</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span>
    
    </div>
    <hr>
    <h3>form表单上传文件</h3>
    <form action="/upload/" method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="text" name="user">
        <input type="file" name="file_name">
        <input type="submit">
    </form>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 异步案例 #}
        $("#btn1").click(function () {
            $.ajax({
                url:"/ajax_sleep/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
    
        $("#btn2").click(function () {
            $.ajax({
                url:"/ajax_test/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
                success:function (data) {
                    if (data.status){
                        $("#i3").val(data.msg);
                    }else{
                        $("#s1").text(data.msg);
                        setTimeout(function () {
                            $("#s1").text("");
                        },2000)
                    }
                }
            })
        });
        $("#btn4").click(function () {
            $.ajax({
                url:"/ajax_json/",
                type: "POST",
                contentType:"json",
                headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf
                data: JSON.stringify({
                    a:100,
                    b:200,
                    user:"darren",
                }),
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    root@darren-virtual-machine:~/PycharmProjects/orm_demo# mkdir media

    访问,选择文件

    点击submit,上传成功

    调试输出

    <QueryDict: {'csrfmiddlewaretoken': ['JA1GUiIv2LZCvSTxFjP8IOMaW7MNb3q3tjI5nOtFyXv6RETZxqq729rBOTFlFkE5'], 'user': ['']}>
    <MultiValueDict: {'file_name': [<InMemoryUploadedFile: test111.jpeg (image/jpeg)>]}>

    服务器查看

    root@darren-virtual-machine:~/PycharmProjects/orm_demo# ll media/

    六 基于Ajax请求上传文件

    修改html

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    <button id="btn4">上传json数据</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span>
    
    </div>
    <hr>
    <h3>form表单上传文件</h3>
    {#  <form action="/upload/" method="POST" enctype="multipart/form-data"> #}
        {% csrf_token %}
        <input type="text" id="user" name="user">
        <input type="file" id="file1" name="file_name">
    <button id="btn5">ajax上传文件</button>
    {#    <input type="submit"> #}
    {# </form> #}
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 异步案例 #}
        $("#btn1").click(function () {
            $.ajax({
                url:"/ajax_sleep/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
    
        $("#btn2").click(function () {
            $.ajax({
                url:"/ajax_test/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
                success:function (data) {
                    if (data.status){
                        $("#i3").val(data.msg);
                    }else{
                        $("#s1").text(data.msg);
                        setTimeout(function () {
                            $("#s1").text("");
                        },2000)
                    }
                }
            })
        });
        $("#btn4").click(function () {
            $.ajax({
                url:"/ajax_json/",
                type: "POST",
                contentType:"json",
                headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf
                data: JSON.stringify({
                    a:100,
                    b:200,
                    user:"darren",
                }),
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    调试

    添加ajax

    复制代码
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <button id="btn1">ajax_sleep</button>
    <button id="btn2">ajax_test</button>
    <button id="btn4">上传json数据</button>
    {% csrf_token %}
    <hr>
    <div>
        <input type="text" id="i1"> + <input type="text" id="i2"> =
        <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span>
    
    </div>
    <hr>
    <h3>form表单上传文件</h3>
    {#  <form action="/upload/" method="POST" enctype="multipart/form-data"> #}
        {% csrf_token %}
        <input type="text" id="user" name="user">
        <input type="file" id="file1" name="file_name">
    <button id="btn5">ajax上传文件</button>
    {#    <input type="submit"> #}
    {# </form> #}
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        {# 异步案例 #}
        $("#btn1").click(function () {
            $.ajax({
                url:"/ajax_sleep/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
    
        $("#btn2").click(function () {
            $.ajax({
                url:"/ajax_test/",
                type:"GET",
                success:function (data) {
                    console.log(data);
                }
                }
            )
        })
        {# 计算案例 #}
        $('#btn3').click(function () {
            var num1 = $("#i1").val();
            var num2 = $("#i2").val();
            $.ajax({
                url: "/ajax_sum/",
                type: "POST",
                data:{
                    num1:num1,
                    num2:num2,
                    csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
                },
                success:function (data) {
                    if (data.status){
                        $("#i3").val(data.msg);
                    }else{
                        $("#s1").text(data.msg);
                        setTimeout(function () {
                            $("#s1").text("");
                        },2000)
                    }
                }
            })
        });
        $("#btn4").click(function () {
            $.ajax({
                url:"/ajax_json/",
                type: "POST",
                contentType:"json",
                headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf
                data: JSON.stringify({
                    a:100,
                    b:200,
                    user:"darren",
                }),
                success:function (data) {
                    console.log(data)
                }
            })
        })
        {# ajax上传文件 #}
        $("#btn5").click(function () {
            var formdata = new FormData();
            formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
            formdata.append("file_name",$("#file1")[0].files[0]);
            $.ajax({
                url: "/upload/",
                type: "POST",
                processData: false,  // 告诉jQuery不要去处理发送的数据
                contentType: false,  // 告诉jQuery不要去设置Content-Type请求头
                data: formdata,
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
    </body>
    </html>
    复制代码

    修改图片名为test222

    点击ajax上传文件

    检查服务器文件

    root@darren-virtual-machine:~/PycharmProjects/orm_demo# ll media/

    七 请求头ContentType

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

    1.  application/x-www-form-urlencoded应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
    2.  multipart/form-data是另一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。
    3.  application/json:这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。 

     

    学习记录,小白一枚
  • 相关阅读:
    160-13. 罗马数字转整数
    159-118. 杨辉三角
    158-190. 颠倒二进制位
    157-461. 汉明距离
    156-412. Fizz Buzz
    155-278. 第一个错误的版本
    154-108. 将有序数组转换为二叉搜索树
    153-101. 对称二叉树
    152-234. 回文链表
    秒杀程序架构演进
  • 原文地址:https://www.cnblogs.com/wangsirde0428/p/14322905.html
Copyright © 2020-2023  润新知