Bootstrap

四十六、AJAX

一 AJAX简介

AJAX(Asynchronous JavaScript And XML)异步的JavaScript和XML。

AJAX最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

  • 同步交互:客户端发送一个请求,需要等待服务器响应之后才能发送第二个请求。
  • 异步交互:客户端发送请求后,不需要等待响应结果就可以发送其他请求。

示例:在前端页面输入两个数字,通过Ajax发送到后端计算后返回到前端展示。

templates/sum.html 代码:

<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <input type="text" id="d1"> + <input type="text" id="d2"> = <input type="text" id="d3">
            </div>
        </div>
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <button class="btn btn-success btn-xs" id="d4">计算</button>
            </div>
        </div>
    </div>

    <script>
    	<!--给计算按钮绑定一个点击事件-->
        $('#d4').click(function () {
            $.ajax({
                url: '',  <!--提交数据的路径 相当于form表单中的action参数-->
                type: 'post', <!--指定提交方式-->
                data: {'i1': $('#d1').val(), 'i2': $('#d2').val()},<!--提交给后端的数据-->
                success:function (args) {<!--回调函数 参数args就是后端返回的数据-->
                    $('#d3').val(args)
                }
            })
            
        })
    </script>
</body>

urls.py 代码:

path('sum/', views.two_sum)

views.py 代码

def two_sum(request):
    if request.method == 'POST':
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')
        res = int(i1) + int(i2)
        return HttpResponse(str(res))
    return render(request, 'sum.html')

绑定一个失去焦点事件:

<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <input type="text" id="d1" class="c1"> + <input type="text" id="d2" class="c1"> = <input type="text" id="d3">
            </div>
        </div>
    </div>
    <script>
        $('.c1').blur(function () {
            $.ajax({
                url: '',
                type: 'post',
                data: {'i1': $('#d1').val(), 'i2': $('#d2').val()},
                success:function (args) {
                    $('#d3').val(args)
                }
            })
        })
    </script>
</body>
def two_sum(request):
    if request.method == 'POST':
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')
        if i1 and i2:
            res = int(i1) + int(i2)
            return HttpResponse(str(res))
        else:
            return HttpResponse('输入不完整')
    return render(request, 'sum.html')

二 数据编码格式

可以朝后端发送post请求的方式有两种,form表单和Ajax请求。

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

  • urlencoded
  • formdata
  • json

2.1 form表单中

  • 默认的数据编码是urlencoded
  • 数据格式:username=jasper&password=123
  • Django后端会针对符合urlencoded编码格式的数据帮你解析封装到request.POST中
  • 如果编码格式改为formdata,那么针对普通的键值对还是解析到request.POST中,而文件则解析到request.FILES中。
  • form表单无法发送json格式数据

2.2 Ajax中

  • 默认编码也是urlencoded
  • 数据格式:username=jasper&pwd=123
  • Django后端会针对符合urlencoded编码格式的数据帮你解析封装到request.POST中

Ajax发送json格式数据

  • contentType参数指定为application/json
  • 数据必须是json格式的
  • Django后端不会处理json格式的数据,需要到request.body获取并处理
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">ajax测试:
                <input type="text" id="d1" name="test">
                <button class="btn btn-success btn-group-sm" id="d2">提交ajax请求</button>
            </div>
        </div>
    </div>

    <script>
        $('#d2').click(function () {<!--给input标签绑定一个单击事件-->
            $.ajax({
                url:'',
                type:'post',
                data: JSON.stringify({'input':$('#d1').val()}),<!--数据必须是json格式-->
                contentType:'application/json',<!--数据格式必须是'application/json'-->
                success: function (args) {
                    console.log(this.data, typeof this.data)
                }
            })
        })
    </script>
</body>
path('ajax/', views.ajax),
def ajax(request):
    if request.method == "POST":
        print(request.POST)  # <QueryDict: {}>
        print(request.FILES)  # <MultiValueDict: {}>
        print(request.body)  # b'{"data":"ajax\xe6\xb5\x8b\xe8\xaf\x95"}'
        import json
        res = json.loads(request.body)
        print(res, type(res))  # {'data': 'ajax测试'} <class 'dict'>
    return render(request, 'ajax.html')

三 Ajax携带文件数据

Ajax发送文件需要借助js内置对象FromData

<body>
<div class="row">
    <div class="col-md-8">
        用户名:<input type="text" name="username" id="name">
        密码:<input type="password" name="password" id="pwd">
        <input type="file" name="file" id="file">
        <button class="btn btn-success" id="d1">提交</button>
    </div>
</div>

<script>
    $('#d1').click(function () {
        // 1. 先产生一个FormData对象
        let fromData = new FormData();
        // 2. 添加普通键值对
        fromData.append('username', $('#name').val())
        fromData.append('password', $('#pwd').val())
        // 3. 添加文件对象
        fromData.append('file', $('#file')[0].files[0])
        console.log(111)
        // 4. 将对象通过ajax发送给后端
        $.ajax({
            url: '',
            type: 'post',
            data: fromData,  //数据就是对象
            contentType: false,  //不需要任何数据格式 Django后端会自动识别formData对象
            processData: false,  //不对数据进行任何处理
            success: function (args) {

            }


        })
    })
</script>
</body>
def ajax_file(request):
    if request.method == 'POST':
        print(request.POST)  # <QueryDict: {'username': ['17391767493'], 'password': ['111']}>
        print(request.FILES)
        # <MultiValueDict: {'file': [<InMemoryUploadedFile: 国庆作业安排.xls (application/vnd.ms-excel)>]}>
    return render(request, 'file.html')

四 回调函数

  • 后端在跟Ajax交互时,应该返回json格式字符串而不是其他的东西。
  • 前端针对HttpResponse和JsonResponse返回的数据处理策略不同。前者不会自动反序列化,而后者会自动反序列化。如果想让前者也能自动反序列化,需要加一个参数dataType:‘JSON’
<body>
    <input type="text" id="d1">
    <button class="btn" id="d2">ajax请求</button>

    <script>
        $('#d2').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data: '',
                success:function (args) {
                    console.log(args, typeof args)
                    $('#d1').val(args)
                }
            })
        })
    </script>
</body>
def callback(request):
    if request.method == 'POST':
        return HttpResponse("{'name': 'jasper', 'age': 18}")
    return render(request, 'callback.html')

在这里插入图片描述

def callback(request):
    if request.method == 'POST':
        from django.http import JsonResponse
        return JsonResponse({'name': 'jasper', 'age': 18})
    return render(request, 'callback.html')

在这里插入图片描述

五 序列化

首先,从djang.core导入它,然后调用它的serialize方法,这个方法至少接收两个参数,第一个是你要序列化成为的数据格式,这里是‘jsonl’,第二个是要序列化的数据对象,数据通常是ORM模型的QuerySet,一个可迭代的对象。

def ser(request):
    user_list = models.Book.objects.all()
    from django.core import serializers
    res = serializers.serialize('json', user_list)
    return HttpResponse(res)
;