Django与Ajax

Ajax简介

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

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

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

Ajax基本语法结构

$.ajax({
	代码块
})

使用Ajax的例子,页面输入两个整数,在不刷新浏览器的情况下传输到后端计算出结果

urls.py:
url(r'^ajax_test/', views.ajax_test),

views.py:
from django.shortcuts import render,HttpResponse
# Create your views here.
def ajax_test(request):
    if request.method == 'POST':
        d1 = request.POST.get('d1')
        d2 = request.POST.get('d2')
        d3 = int(d1) + int(d2)
        return HttpResponse(d3)
    return render(request,'ajax_test.html')
ajax_test.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>

<input type="text" id="d1"> + <input type="text" id="d2"> =
<input type="text" id="d3">
<button id="d4">点我发送ajax数据</button>

<script>
    // 重点
    $('#d4').click(function () {
        $.ajax({
            url:'', //数据提交的后端地址,跟form表单的action参数一样
            type:'post', //提交方式为post,默认也是get请求
            data:{'d1':$('#d1').val(),'d2':$('#d2').val()}, //提交的数据
            success:function (data) {       //形参data就是异步提交给后端,后端通过计算返回的结果,回调函数
                $('#d3').val(data)      // 回调之后做的事情,设置值。
            }
        })
    })
</script>
</body>
</html>

如果使用了ajax,视图层的三板斧都不会再与前端页面交互,而是与回调函数的形参data交互。

前后端传输的编码格式

发送请求的前端标签

我们所学过的向后端发送请求的前端标签都有哪些?

  • a标签: get请求,get请求也可以携带参数,?xxx=111&yyy=222
  • form表单:get/post请求
  • ajax:get/post请求

针对这些前端发送post请求的我们来研究一下它们的数据在前端的编码格式:

前端交互是一个数据编码格式,针对不同的数据,后端会进行不同的处理。

比如说django后端有

  • request.POST
  • request.FILES

那么为什么只要是POST请求,就会交给request.POST进行处理,如果是文件请求,就会交给request.FILES进行处理,我们带着这些疑问来往下看。

前端三种数据格式

在前端呐,有三种数据格式:

  1. urlencoded
  2. formdata
  3. application/json

针对上面所学过的向后端发送请求的前端标签来看

form表单发送三种数据格式的情况

form表单只能够发送两种数据格式的数据:1和2

1.form表单post请求默认的编码格式是urlencoded

在浏览器-->检查-->network可以看到,我们form表单在提交数据的时候,有如下信息

Request Headers:	# 请求头
Content-Type:application/x-www-form-urlencoded; charset=UTF-8	# 数据编码格式-urlencoded

Form Data:# 携带的数据
d1=232323&d2=23232132

在我们后端django中针对urlencoded数据,会自动解析并封装到request.POST方法中。

2.form表单如果发送文件

Request Headers:	# 请求头
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhjKCHQHDmcE62iMQ	# 数据编码格式,-form-data

Form Data:#针对form-data格式的数据,在浏览器是无法查看的。

发送到后端django,文件对象会自动解析到 request.POST 和 request.FILES 中,前者记录文件名,后者记录对象。

3.form表单无法发送json格式的数据,如果发的话,只能借助于ajax

ajax三种编码格式都能够发送

ajax能够发送三种数据格式的数据:1、2和3

1.ajax默认的编码格式也是urlencoded,django后端也是将数据封装到request.POST中

那么我们刚才看了form表单发送这些默认编码格式的数据,还有一个发送json格式的需要借助于ajax,请继续往下看

2.Ajax传输json格式数据

urls.py:
url(r'^form_test/', views.form_test),

views.py:
def form_test(request):
    if request.method == "POST":
        print(request.body)
        json_bytes = request.body
        print(json.loads(json_bytes),type(json.loads(json_bytes)))
        # 反序列化为python字典格式
    return render(request,'form_test.html')

打印结果:
b'{"username":"qinyj","pwd":123}'	# request.body
{'username': 'qinyj', 'pwd': 123} <class 'dict'>	# 反序列化之后的

form_test.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>

<form action="" method="post">

    username: <input type="text" name="username" id="d1">
    password: <input type="text" name="password" id="d2">
    # 这里不要用form表单的提交,为什么呢,因为form表单提交的默认数据编码格式是urlencoded,也会将json格式的数据封装到后端request.body中
</form>
<button id="d3">点我发送json格式</button>

<script>
    $('#d3').click(function () {
        $.ajax({
            url:'',
            type:'post',
            contentType:'application/json', //需要指定编码格式为json
            data:JSON.stringify({'d1':$('#d1').val(),'d2':$('#d2').val()}), // 需要前端发送JSON字符串,JSON。stringify序列化即可。
            success:function (data) {
                alert(123)      // 此弹框仅仅演示,没有任何用户
            }
        })
    })
</script>
</body>
</html>

django后端针对前端json格式的数据,不会做任何处理,数据怎么来的,原封不动的封装到request.body中(基于网络传输二进制的json字符串),需要自己处理格式

3.Ajax传输文件数据

views.py:

def form_test(request):
    if request.method == "POST":
        print(request.POST)
        print(request.FILES)
        # 前端上传文件之后打印结果
        # < QueryDict: {'username': ['qinyj']} >
        # < MultiValueDict: {'myfile': [ < InMemoryUploadedFile: Devops工具链.png(image / png) >]} >
    return render(request,'form_test.html')
form_test.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>

<form action="">
    file: <input type="file" name="file" id="d1">
</form>
<button id="d4">点我发送文件格式的数据</button>

<script>
    $('#d4').click(function () {
        // 先生成一个内置对象
        var MyFormData = new FormData();
        // 添加普通的键值对
        MyFormData.append('username','qinyj');
        // 添加文件数据
        MyFormData.append('myfile',$('#d1')[0].files[0]);

        $.ajax({
            url:'',
            type:'post',
            data:MyFormData,
            // 发送文件必须要指定的两个参数
            contentType:false,  // 不适用任何编码,MyFormData对象内部自带编码,django后端能够识别。
            processData:false,  // 不处理任何数据
            success:function (data) {

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

django 能够识别前端ajax发送过来的文件对象,并放入对应的方法中request.FILE去解析。

序列化的概念

在前端分离的场景下,发送给前端json格式的字符串形式,再写上说明文档,方便数据交互

我们可以手动在后端将数据转成json字符串格式,django非常友好,帮我们想到了这一点,需要借助一个模块来完成。

from django.core import serializers

urls.py:
url(r'^get_data/', views.get_data),
views.py:

# 需要导入模块
from django.core import serializers
from app01 import models

def get_data(request):
    # 从数据库中查出来所有的信息,
    # 序列化目的,将数据整合成一个大字典形式,
    user_querset = models.User.objects.all()
    res = serializers.serialize('json',user_querset)
    return HttpResponse(res)

# 前端页面接收到的json数据:
[{"model": "app01.user", "pk": 1, "fields": {"username": "qinyj", "password": 123, "gender": 1}}, {"model": "app01.user", "pk": 2, "fields": {"username": "jack", "password": 123, "gender": 2}}]

Ajax常见应用场景

搜索框中根据用户输入的关键字,自动提示检索关键字

用户的注册时候的查重

sweetalert插件

点击下载Bootstrap-sweetalert项目

上述弹窗效果代码链接 https://lipis.github.io/bootstrap-sweetalert/

模板层

需要引入sweetalert.js文件:
将下载好的项目里面的dist文件夹放到static目录中即可,就只需要用到这个文件夹中的内容
<link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
<script src="{% static 'dist/sweetalert.min.js' %}"></script>
<a href="#" class="btn btn-danger del">删除</a>
给删除按钮添加一个点击事件:
<script>
    $(".del").click(function () {
        {#先拿到当前被点击的对象#}
        var $btn = $(this);
        {#去找删除按钮效果代码 #}
        swal({
                title: "你确定?",
                text: "你如果删除了,你就准备跑路吧",
                type: "warning",
                showCancelButton: true,
                confirmButtonClass: "btn-danger",
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                closeOnConfirm: false,
                closeOnCancel: false,
                {#让操作有个延时的...的操作#}
                showLoaderOnConfirm: true
            },
            function (isConfirm) {
                if (isConfirm) {
                    {#朝后端发送ajax请求 做一些操作#}
                    $.ajax({
                        url:'',
                        type:'post',
                        data:{'delete_id':$btn.attr('delete_id')},
                        success:function (data) {
                            if (data.code==200){
                                swal("准备跑路吧", data.msg, "success");
                                {#通过DOM操作,操作标签 移除标签#}
                                $btn.parent().parent().remove()

                            } else {
                                swal("Error", "出现了未知Bug", "warning");
                            }
                        }
                    });
                } else {
                    swal("取消", "我怂了)", "error");
                }
            });
    })
</script>

视图层

import time
from django.http import JsonResponse
def boot_list(request):
    # 判断是否是ajax请求,如果是的话走下面的判断。
    if request.is_ajax():
        # 若ajax与服务器进行交互,通常后端是返回给ajax一个字典信息的。
        back_dic = {'code':200,'msg':''}
        delete_id = request.POST.get('delete_id')
        time.sleep(1)
        models.Book.objects.filter(pk=delete_id).delete()
        back_dic['msg'] = "删除成功"
        return JsonResponse(back_dic)
posted @ 2019-11-30 14:33  GeminiMp  阅读(140)  评论(0编辑  收藏  举报