欢迎来到Cecilia陈的博客

孤独,是人一生最好的修行。

15 Django Ajax

一、Ajax 介绍

Ajax是一种异步提交,就是在当前页面时,不刷新当前页面的前提下,将数据提交到另一个页面

Ajax可以局部刷新页面,在一个页面下,不整体刷新页面,而是可以将当前页面的某一个部分刷新

此处回忆一下同步异步/阻塞非阻塞

同步异步:描述的任务的提交方式

同步:提交任务之后 原地等待任务的返回结果 期间不干日他的事情

异步::提交任务之后 不原地等待 直接执行下一行代码 任务结果的返回通过回调机制

阻塞非阻塞:程序的运行状态------了解程序运行的状态图

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

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

Ajax是一门 JS 技术,基于原生 JS 开发,但用原生的 JS 写代码太过于繁琐,我们用 JavaSquery是实现

提示:JavaSquery是基于javascript方法封装的。。。。

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

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

二、Ajax 实例

展示一个前端页面 ,页面有三个输入框,一个提交按钮,前面两个输入框输入内容,点击按钮,同过Ajax实现点击按钮向后端提交数据,实现将前两个输入框中的数据计算和返回给第三个输入框中显示

# add_num.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <title>Title</title>
</head>
<body>
<input id="i1" type="text">+<input id="i2" type="text">=<input id="i3" type="text">
<button>Ajax提交</button>

<script>
    {#1.先找到button这个对象,绑定点击事件#}
    $('button').click(function () {
        {#2. 触发ajax事件#}
        $.ajax({
            {#1. url:用来控制提交数据的地址,不写默认的是当前的地址#}
            url:'',
            {#2. type:用来控制向地址提交的请求,可以小写#}
            type:'post',
            {#3. 用来向后端提交的数据#}
            data:{num1:$('#i1').val(),num2:$('#i2').val()},
            {#4. 接收从后端返回的数据,也就是异步返回的结果#}
            success:function(data){
                {#将结果给第三个输入框#}
                $('#i3').val(data)
            }

        })
    })
</script>
</body>
</html>
# views.py文件

def add_num(request):
    # 判断是否为Ajax请求
    if request.is_ajax():
        if request.method == 'POST':
            num1 = request.POST.get('num1')
            num2 = request.POST.get('num2')
            data = int(num1)+int(num2)
            print(data)
            return HttpResponse(data)
    return render(request,'add_num.html')
# url.py文件
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 通过Ajax向后端传数据将结果计算返回
    url(r'^add/$',views.add_num,name='add_page'),
]

三、contentType 交互的数据格式

我们知道form表单,默认的向后端提交数据的编码格式是urlencoded

urlencoded:

()=()&()=()这种就是符合urlencoded数据格式

  • django后端针对()=()&()=()的urlencoded数据格式会自动解析,将结果打包给request.POST 用户只需要从request.POST即可获取对应信息

formdata:

  • django后端针对formdata格式类型数据 也会自动解析,但是不会方法request.POST中而是给你放到了request.FILES中

ajax默认的提交数据的编码格式也是urlencoded

总结: django后端针对不同的编码格式数据 会有不同的处理机制以及不同的获取该数据的方法

四、Ajax传json格式数据

注意:在前后端进行数据交互的时候,一定要表名所发的是什么数据,是什么格式的,并且一定要遵守,表明是什么格式数据,就一定要发与之对应的数据格式。

django后端针对前端页面发送过来的 json 数据不会自动解析,会直接原封不动的给你放到request.body中,需要你手动处理,获取数据

# json.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <title>Title</title>
</head>
<body>

<input id="i1" type="text">
<input id="i1" type="text">
<button>提交</button>

<script>
    $('button').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:JSON.stringify({'name':'cecilia','pwd':'123'}),
            contentType:'application/json',
            success:function (data) {
                alert(data)
            }
        })
    })
</script>
</body>
</html>
#views.py文件
import json
def up_json(request):
    if request.is_ajax():
        if request.method == 'POST':
            json_bytes = request.body
            json_str = json_bytes.decode('utf8')
            json_dic = json.loads(json_str)
            print(json_dic,type(json_dic))
    return render(request,'json.html')

注意:当前端向后端发送的数据不是json格式的时候,django是默认不给看request.body中的内容的,一定要牢记,当前端向后端发送json格式数据的时候,所有的数据信息都是保存在request.body中的

在上图中可以看到,我们已经在前端页面中表明了我发的是json格式的数据,所以他提交的数据已经不在是向get和post的请求的那种()=()&()=()的形式了,所以在post自然是获取不到任何数据的了

如上图,我们点击view score的时候,我们可以看到浏览器也默认用application/json的形式来接收前端发送的数据的

五、Ajax向后端传文件

Ajax向后端传文件,需要用到内置对象Formdata,该对象既可以传普通的键值,也可以传文件

# upload_file.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <title>Title</title>
</head>
<body>
<input type="text" name="username" id="t1">
<input type="text" name="password" id="t2">
<input type="file" name="myfile" id="t3">上传文件
<button>提交</button>
<Script>
    $('button').click(function () {
         // 1.先生成一个formdata对象
        var myFormData = new FormData();
        // 2.朝对象中添加普通的键值
        myFormData.append('username',$("#t1").val());
        myFormData.append('password',$("#t2").val());
        // 3.朝对象中添加文件数据
        // 1.先通过jquery查找到该标签
        // 2.将jquery对象转换成原生的js对象
        // 3.利用原生js对象的方法 直接获取文件内容
        myFormData.append('myfile',$('#t3')[0].files[0]);
        $.ajax({
            url:'',
            type:'post',
            data:myFormData,  // 直接丢对象
            // ajax传文件 一定要指定两个关键性的参数
            contentType:false,  // 不用任何编码 因为formdata对象自带编码 django能够识别该对象
            processData:false,  // 告诉浏览器不要处理我的数据 直接发就行
            success:function (data) {
                alert(data)
            }
        })
    })
</Script>
</body>
</html>
# views.py文件
def upload_file(request):
    # 判断请求是否为Ajax请求
    if request.is_ajax():
        if request.method == 'POST':
            print(request.POST) # 这里只是收到了普通的键值对
            print(request.FILES) # 上传的文件的对象在这里
            return  HttpResponse('收到')

    return render(request,'upload_file.html')

注意:

  1. 利用formdata对象 能够简单的快速传输数据 (普通键值 + 文件)

  2. 有几个参数

    data:formdata # 对象
    contentType:false # 不用任何编码 因为formdata对象自带编码 django能够识
    processData:false # 告诉浏览器不要处理我的数据 直接发就行
    

六、给前端返回一个字典

将用户表的数据 查询出来 返回给前端
给前端的是一个大字典 字典里面的数据的一个个的字段

# dict.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <title>Title</title>
</head>
<body>
{{user_list}}

{#这是最原始的利用模板语法来接收的大字典#}
{#{% for user_obj in user_list %}#}
{#    <p>username:{{ user_obj.username }}&nbsp;age:&nbsp;{{ user_obj.age }}&nbsp;gender:&nbsp;{{ user_obj.gender }}</p>#}
{#{% endfor %}#}

</body>
</html>
# views.py文件
from app01 import models
from django.core import serializers
def back_dic(request):
    user_obj_list = models.UserInfo.objects.all()
    # 1.原始的方式向前端页面传送字典
    # user_list = []
    # for user_obj in user_obj_list:
    #     user_list.append({
    #         'username':user_obj.username,
    #         'age':user_obj.age,
    #         'gender':user_obj.get_gender_display()
    #     })

    # 2. 利用serializers这个模块来帮我们很简单的将对象变为字典
    '''
    serializers:模块有两个参数
                1.format:代表序列成什么格式的数据
                2.queryset:要序列化的对象
    '''
    user_list = serializers.serialize('json',user_obj_list)
    return  render(request,'dict.html',locals())

七、Ajax + sweetalert

下面我们要做的一个案例就是这个sweetalert的一个二次确认框

img

# sweet.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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>
    <link rel="stylesheet" href="{% static 'sweetalert/dist/sweetalert.css' %}">
    <script src="{% static 'sweetalert/dist/sweetalert.js' %}"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1 ">
    <title>Title</title>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
        <h2>数据展示</h2>
            <table class="table table-bordered table-hover table-striped">
                <thead>
                    <tr>
                        <td>序号</td>
                        <td>姓名</td>
                        <td>年龄</td>
                        <td>性别</td>
                        <td class="text-center">编辑</td>
                    </tr>
                </thead>
                <tbody>
                    {% for user_obj in user_obj_list %}
                        <tr>
                            <td>{{forloop.counter }}</td>
                            <td>{{user_obj.username }}</td>
                            <td>{{user_obj.age}}</td>
                            <td>{{user_obj.get_gender_display}}</td>
                            <td>
                                <a href="#" class="btn btn-success">编辑</a>
                                <a href="#" class="btn btn-warning cancel"  del_id="{{ user_obj.pk }}">删除</a>
                            </td>
                        </tr>
                    {% endfor %}

                </tbody>
            </table>
        </div>
    </div>
</div>
<script>
    $('.cancel').click(function () {
        var $btn = $(this);
        swal({
          title: "你确定要删吗?",
          text: "你要是删了,你就准备好跑路吧!",
          type: "warning",
          showCancelButton: true, //这是确定俺就
          confirmButtonClass: "btn-danger",
          confirmButtonText: "对,老子就要删!", //确定按钮的文本
          cancelButtonText: "算了,算了!", //这是取消删除的文本内容
          closeOnConfirm: false,
          showLoaderOnConfirm: true//实现确定按钮后的加载后删除
        },
        function(){
            $.ajax({
                url:'',
                type:'post',
                data:{'delete_id':$btn.attr('delete_id')},
                success:function (data) {
                    if (data.code){
                        swal(data.msg, "你可以回去收拾行李跑路了.", "success");
                        // 1.直接刷新页面
                        {#window.location.reload()#}
                        // 2.通过DOM操作 实时删除
                        $btn.parent().parent().remove()
                    }else{
                        swal("发生了未知错误!", "我也不知道哪里错了.", "info");
                    }
                }
            });
        });
    })
</script>
</body>
</html>
# views.py文件
import time
from django.http import JsonResponse
def sweetalert(request):
    # 如果是get请求,就把用户对象返回给前端页面
    user_obj_list = models.UserInfo.objects.all()
   
    # 如果是POST请求,就删除需要删除的用户对象
    if request.method == 'POST':
        # 先定义一个字典,作为返回给前端页面的
        back_dic = {"code":True,'msg':''}
        delete_id = request.POST.get('delete_id')
        models.UserInfo.objects.filter(pk=delete_id).delete()
        back_dic['msg'] = '后端传来的:真的被我删了'
        time.sleep(3)# 这里是实现一个加载一段时间后删除
        return JsonResponse(back_dic)
    return render(request,'sweet.html',locals())

补充:

1.上述的样式类部分渲染的样式来自于bootstrap中,所有建议在使用上述样式时,将bootstrap的js和css也导入了,这样的情况下,页面效果就不会有任何问题

2.弹出的上述模态框中,可能字体会被图标掩盖一部分,可通过调整字体的上外边距来解决

img

八、Ajax 实例

7.1 input框失去焦点事件

在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回这个用户名是否已经被注册过。

# register.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <title>Title</title>
    <style>
        .aa{
            margin-top: 20px;
        }
        .bb{
            display: none;
        }
    </style>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-sm-2 col-sm-offset-5" style="background-color: #dca7a7;margin-top: 50px">
            <div>
                <input class="form-control aa" type="text" name='username' value="输入用户名" id="i1">
            </div>
            <p><span class="bb aa" style="color: red">用户名已存在</span></p>
            <div>
                <input class="form-control aa" type="text" name='pwd' value="输入密码" id="i2">
            </div>
{#            <div>#}
{#                <input class="form-control aa"  type="text" name='repwd' value="确认密码" id="i3">#}
{#            </div>#}
            <div class="text-center">
                <input class="aa" type="radio" name='gender' value="1" id="i4">男
                <input class="aa" type="radio" name='gender' value="2" id="i5" checked>女
            </div>

            <div class="text-center">
                <button class="btn aa">注册</button>
            </div>

        </div>
    </div>
</div>
<script>
    // 用户名输入框的失去焦点事件
    $('#i1').blur(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{'username':$(this).val()}, //this代表的是当前的jq对象
            success:function (data) {
                back_dic=JSON.parse(data);//反序列化从后端传回来的数据
                if (back_dic['flag']){ 
                    // 如果条件存在,就将标签的bb类属性去掉
                    $('p>span').removeClass('bb');
                }
            }
        })
    })
</script>
</body>
</html>
# views.py文件

def register(request):
    if request.method == 'POST':
        # 先定义一个字典,用于给前端返回数据
        back_dic = {'flag': False}
        # 拿到前端的post请求携带的参数
        username = request.POST.get('username')
        # 从数据库中取这个username名的对象
        user_obj = models.UserInfo.objects.filter(username=username).first()
        if user_obj:
            # 如果这个对象存在
            back_dic['flag'] = True
            import json
            # 将返回序列化号的json格式的数据返回给前端页面
            return HttpResponse(json.dumps(back_dic))
    return render(request,'register.html')
posted @ 2019-10-28 20:32  Cecilia陈  阅读(142)  评论(0编辑  收藏  举报