Django之Ajax

什么是Ajax?

  • ajax 全名: async javascript and XML(异步JavaScript和XML)
  • 是前后台交互的能⼒, 也就是我们客户端给服务端发送消息的⼯具,以及接受响应的⼯具
  • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
  • AJAX 是与服务器交换数据并更新部分网页的艺术,在不重新加载整个页面的情况下。
  • 是⼀个默认异步执⾏机制的功能,AJAX分为同步(async = false)和异步(async = true)

什么是同步请求?(false)

1  同步请求是指当前发出请求后,浏览器什么都不能做,
2  必须得等到请求完成返回数据之后,才会执行后续的代码,
3  相当于生活中的排队,必须等待前一个人完成自己的事物,后一个人才能接着办。
4  也就是说,当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面处于一个假死状态,
5  当这个AJAX执行完毕后才会继续运行其他代码页面解除假死状态

 什么是异步请求?(默认:true)

1 默认异步:异步请求就当发出请求的同时,浏览器可以继续做任何事,
2 Ajax发送请求并不会影响页面的加载与用户的操作,相当于是在两条线上,各走各的,互不影响。
3 一般默认值为true,异步。异步请求可以完全不影响用户的体验效果,
4 无论请求的时间长或者短,用户都在专心的操作页面的其他内容,并不会有等待的感觉。

Ajax 的优势

  • AJAX使用JavaScript技术向服务器发送异步请求;
  • AJAX请求无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高; 
  • 两个关键点:1.局部刷新,2.异步请求

应用场景

搜索引擎根据用户输入的关键字,自动提示检索关键字。

还有一个很重要的应用场景就是注册时候的用户名的查重。

其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。

  • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

当输入用户名后,把光标移动到其他表单项上时,浏览器会使用Ajax技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。

  • 整个过程中页面没有刷新,只是局部刷新了;
  • 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;

Ajax 的操作流程

具体操作流程:

  • 首先通过PHP页面将数据库中的数据取出
  • 取出后转成json格式的字符串,后利用ajax把字符串返还给前台
  • 再利用json.parse解析通过循环添加到页面上
  • 那么反之,前端的数据可以利用ajax提交到后台
  • 但是后台是没有办法直接把这些数据插入到数据库中,所以要先提交到PHP页面上
  • 最后再由PHP将数据插入到数据库中

基本语法

$('#subBtn').click(function (){
        //发送ajax请求
        $.ajax({
            url:'',    //后端地址,三种填写方式,与form标签的action一致
            type:'post',    //请求方式,默认也是get
            data:{'v1':$('#d1').val(),'v2':$('#d2').val()},    //获取两个框里面的数据
            success:function (args){     //后端返回结果之后自动触发,args接收后端返回的数据
                $('#d3').val(args)
            }

        })
    })

示例:

 # 路由层 urls.py 文件

from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('ab_ajax/',views.ab_ajax_func)

 # 视图层 views.py 文件

from django.shortcuts import render, HttpResponse


def ab_ajax_func(request):
    if request.method == 'POST':
        print(request.POST)
        v1 = request.POST.get('v1')
        v2 = request.POST.get('v2')
        res = int(v1) + int(v2)
        return HttpResponse(res)
    return render(request, 'abAjaxPage.html')

 # 模板层 abAjaxPage.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<input type="text" id="d1"> + <input type="text" id="d2"> = <input type="text" id="d3">
<button id="subBtn">计算</button>


<script>
    //给按键绑定点击事件
    $('#subBtn').click(function (){
        //发送ajax请求
        $.ajax({
            url:'',    //后端地址,三种填写方式,与form标签的action一致
            type:'post',    //请求方式,默认也是get
            data:{'v1':$('#d1').val(),'v2':$('#d2').val()},    //获取两个框里面的数据
            success:function (args){     //后端返回结果之后自动触发,args接收后端返回的数据
                $('#d3').val(args)
            }

        })
    })
</script>
</body>
</html>

前后端数据传输的编码格式

1.前端可以向后端发起post请求的方式

  • form 表单
  • ajax 请求

2.基于post请求, 前后端数据传输的主流编码格式有三种

  • urlencoded : 默认的编码格式, 提交的数据从request.POST中提取
  • form-data : 上传文件时使用的编码格式, 提交的数据从request.POST中提取, 上传的文件从request.FILES中提取
  • json : ajax发送的json格式数据, 在request.POST中取不到数据, 需要在request.body中提取数据

3.基于post请求, form表单传输数据默认的编码格式

  • 默认编码格式为 : urlencoded
  • 如果要上传文件需要在标签中指定 : enctype="multipart/form-data" 编码格式
  • 数据格式 : username=alex&password=123
  • 提交位置 : django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中, 文件提交到request.FILES中

4.基于post请求, ajax传输数据默认编码格式

  • 默认编码格式 : urlencoded
  • 如果要上传文件需要使用 Formdata 对象
  • 数据格式 : username=alex&password=123
  • 提交位置 : django后端会自动帮你解析封装到request.POST中, 文件提交到request.FILES中

5.json.loads( )是否可以转Bytes格式

  • 3.5之前不行, 需要我们手动将 Bytes 格式转成 str 类型, 然后再进行转换
  • 3.6以后可以, Bytes无需手动转 str 类型, 它内部会自动帮你转成 str, 再转成 json
  • 查看 json.loads( ) 的源码可以得到验证 :

 

 

 Ajax发送数据

Ajax发送json格式数据

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="d1">发送json格式数据</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:JSON.stringify({'name':'alex','age':18}),    # 告诉后端发送的是json格式数据
            contentType:'application/json',  //指定字符编码格式
            success:function (args){
                alert(args)
            }
        })
    })
</script>
</body>
</html>

后端拿到二进制格式的JSON格式字符串。Django针对json格式数据后端需要手动处理。

后端如何处理json格式字符串

# 视图层:

from django.shortcuts import render 

def ab_ajax_func(request):
    if request.method == 'POST':
        print(request.POST)    # <QueryDict: {}>
        print(request.FILES)    # <MultiValueDict: {}>
        print(request.body)    # b'{"name":"alex","age":18}'
        import json
        res = json.loads(request.body)   # json.loads()自带解码功能
        print(res,type(res))    # {'name': 'alex', 'age': 18} <class 'dict'>
        request.JSON =res    # 也可以将处理好的数据自己进行封装
        print(request.JSON)    # {'name': 'alex', 'age': 18}
    return render(request, 'abAjaxPage.html')

ajax发送json格式数据需要注意的点:

  • contentType 参数 指定成 : application/json
  • 数据必须是真正的json格式数据
  • Django后端不会处理json格式数据,需要到request.body获取并处理

Ajax发送文件数据

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>

<input type="file" id="d2">
<button id="d3">发送文件数据</button>
<script>
    $('#d3').click(function (){
        //1.先产生一个FormData对象
        let myFormDataObj = new FormData();
        //2.往该对象中添加普通数据
        myFormDataObj.append('name','alex');
        myFormDataObj.append('age',18);
        //3.往该对象中添加文件数据,$('#d2')取索引0,转为原生jQuery对象即原生标签对象,再用files[0]就获得用户传的文件对象
        myFormDataObj.append('file',$('#d2')[0].files[0])
        //4.发送ajax请求
        $.ajax({
            url:'',
            type:'post',
            data:myFormDataObj,
            //ajax发送文件数据固定的两个配制
       contentType:false,    //告诉浏览器不需要带任何编码,Django后端能够自动识别formdata对象,
            processData: false,  //告诉浏览器,不要对数据进行任何处理,原封不动发送到后端。

       success:function (args){

 
                alert(args)
            }
        })
    })
</script>

</body>
</html>

 # 视图层:

from django.shortcuts import render

def ab_ajax_func(request):
    if request.method == 'POST':
        print(request.POST)    # QueryDict: {'name': ['alex'], 'age': ['18']}>
        print(request.FILES)    # <MultiValueDict: {'file': [<InMemoryUploadedFile: 试卷.pdf (application/pdf)>]}>
    return render(request, 'abAjaxPage.html')

Ajax发送文件需要注意的点:

  •  需要利用内置对象FormData,普通键值对和文件都能发送
obj.append('name','alex');

obj.append('password',$('#pwd').val());

obj.append('file',$('#d2')[0].files[0])
  • 需要指定两个关键性的参数
1 contentType: false
2 processData: false
  • Django后端能够直接识别formdata对象,并且能够将内部的普通键值对自动解析并封装到你request.POST中,文件数据对象自动解析并封装到reuqest.FILES中

Ajax补充说明

1. 后端request.is_ajax()
  用于判断当前请求是否由ajax发出

2. 后端返回的三板斧都会被args接收,不再影响整个浏览器页面

3. 选择使用ajax做前后端交互的时候,后端一般返回的都是字典数据

 

字典数据前后端交互的几种方式

 1. 直接发送

 # 视图层:

from django.shortcuts import render, HttpResponse


def ab_ajax_func(request):
    if request.method == 'POST':
        user_dict = {'username': 'alex', 'hobby': 'reading'}
        return HttpResponse(request, user_dict)    # 将字典直接的发送给前端
    
    return render(request, 'AjaxPage.html')

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="d1">发送ajax请求</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'alex'},
            success:function (args){
                console.log(args);
                console.log(typeof args)
            }
        })

    })

2. 后端先转成json格式,再发送给前端

 # 视图层:

from django.shortcuts import render, HttpResponse


def ab_ajax_func(request):
    if request.method == 'POST':
        user_dict = {'username': 'alex', 'hobby': 'reading'}
        import json
        user_data = json.dumps(user_dict)    # 将字典转成jaon格式
        return HttpResponse(user_data)
    return render(request, 'AjaxPage.html')

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="d1">发送ajax请求</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'alex'},
            success:function (args){
                console.log(args)
                console.log(typeof args)
            }
        })

    })

结果:

 

 上述处理结果发现,返回的是json格式的字符串类型,在前端还是没有办法通过点的方式来取值,所以还需要在前端加上一步操作:

3. JOSN.parse()反序列化

# 视图层:

from django.shortcuts import render, HttpResponse


def ab_ajax_func(request):
    if request.method == 'POST':
        user_dict = {'username': 'alex', 'hobby': 'reading'}
        import json
        user_data = json.dumps(user_dict)    # 将字典转成jaon格式
        return HttpResponse(user_data)
    return render(request, 'AjaxPage.html')

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="d1">发送ajax请求</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'alex'},
            success:function (args){
                let userObj = JSON.parse(args);
                console.log(userObj);
                console.log(typeof userObj)
                console.log(userObj.username)
            }
        })

    })
</script>
</body>
</html>

4. dataType:'json'

ajax自动反序列化后端的json格式的bytes类型数据

 # 视图层:

from django.shortcuts import render, HttpResponse


def ab_ajax_func(request):
    if request.method == 'POST':
        user_dict = {'username': 'alex', 'hobby': 'reading'}
        import json
        user_data = json.dumps(user_dict)    # 将字典转成jaon格式
        return HttpResponse(user_data)
    return render(request, 'AjaxPage.html')

 

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="d1">发送ajax请求</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'alex'},
            dataType:'json',      {# 告诉前端发送过来的为json格式字符串 #}
            success:function (args){
                console.log(args);
                console.log(typeof args)
                console.log(args.username)
            }
        })

    })
</script>
</body>
</html>

结果:

 但是3、4两种操作在前后端都需要进行处理,太过麻烦,有没有简单一点的方法呢?

5. 后端通过JsonResponse处理

 # 视图层:

from django.shortcuts import render, HttpResponse

def ab_ajax_func(request):
    if request.method == 'POST':
        user_dict = {'username': 'alex', 'hobby': 'reading'}
        from django.http import JsonResponse
        return JsonResponse(user_dict)

    return render(request, 'AjaxPage.html')

 # 模板层:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
<button id="d1">发送ajax请求</button>
<script>
    $('#d1').click(function (){
        $.ajax({
            url:'',
            type:'post',
            data:{'name':'alex'},
            success:function (args){
                console.log(args);
                console.log(typeof args)
                console.log(args.username)
            }
        })

    })
</script>
</body>
</html>

结果:

 

posted @ 2022-12-19 22:16  莫~慌  阅读(178)  评论(0编辑  收藏  举报