day058 ajax,介绍及其使用场景,操作示例

本节内容:

1、Ajax简介
2、基于jQuery的ajax实现
3、案例
4、请求头ContentType(看完后,看后面的文件上传实例来看)
5、文件上传

一、Ajax简介

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

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

1、ajax的优点

1、ajax使用Javascript技术向服务器发送异步请求(异步)
2、可以局部刷新(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
(实际上是:偷偷的发送请求,偷偷的响应,通过绑定事件及限定范围的刷新)

2、应用场景:注册时输入用户名,光标移动就会验证,提示用户

二、基于jQuery的ajax实现

1、ajax的请求流程

第一步:绑定一个事件,触发ajax,ajax请求将相关数据发送到服务器
第二步:服务器根据url找到对应的视图函数,执行后返回结果给回调函数
第三步:回调函数执行逻辑后,将最终结果返回给前端(浏览器)

2、ajax示例,携带参数,input计算及发送json数据

views.py文件示例

from django.shortcuts import render,HttpResponse

# Create your views here.

import time
import json
from django.http import JsonResponse # 使用自带的json类,就不用我们手动json

def index(request):
    #time.sleep(5)

    return render(request,"index.html")

def ajax_handle(request):
    # time.sleep(5)
    return HttpResponse("Yuan!")

def ajax_handle2(request):
    print(request.POST)
    print(request.GET)
    return HttpResponse("data has received!")

def cal(request):
    res={"state":1000,"data":None,"msg":None}
    try:
        num1 = request.POST.get("num1") # 拿到前端发送的数字进行计算
        num2 = request.POST.get("num2")
        ret = str(int(num1)+int(num2))
        res["data"]=ret  # 修改数据,将计算的结果赋值给该键值对
    except Exception as e:
        res["state"]=1001
        res["msg"]="请输入合法的字符"
    return JsonResponse(res)  # 使用json类自动发送json字符串给前端
Python

index.html文件示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
</head>
<body>
{% csrf_token %}
<h3>INDEX</h3>


<hr>
<button class="ajax">ajax</button>
<p class="con"></p>

<hr>

<button class="ajax2">携参ajax</button>
<hr>

<input type="text" class="num1"> + <input class="num2" type="text"> = <input class="result" type="text">
<input class="cal" type="button" value="计算">


<script>
    // ajax简单使用
    (".ajax").click(function () {         // 发送Ajax请求         .ajax({
            url:"/ajax_handle/",  {# 请求路径 #}
            type:"get", {# 请求方式#}
            success:function (res) {  {# 请求成功后,执行的回调函数`#}
                console.log(res);
                (".con").html(res);             }         })     });      // ajax的携带参数访问     (".ajax2").click(function () {
        // 发送Ajax请求
        .ajax({             url:"/ajax_handle2/",             type:"post", {# 注意要加上csrf-token,Django默认都有#}             data:{                 a:1,                 b:2,                 csrfmiddlewaretoken:("[name='csrfmiddlewaretoken']").val()
            },
            success:function (res) {
                console.log(res);
            }
        })
    });

    // 携参示例
    (".cal").click(function () { {#  绑定点击事件  #}        let num1=(".num1").val(); {#  拿到用户输入的两个要计算的值  #}
       let num2=(".num2").val();        .ajax({
           url:"/cal/",  {#  请求路径,可以理解为,执行视图函数的对应的路径  #}
           type:"post", {#  post方式发送请求  #}
           data:{
               num1:num1,
               num2:num2,
               csrfmiddlewaretoken:("[name='csrfmiddlewaretoken']").val()            },            success:function (res) {                {#let response=JSON.parse(res)#}   {#  如果是自己手动在后端发送json字符串,要我们手动反序列化  #}                {# JSON.stringify()       这个就是前端的序列化,将数据变成json  #}                if (res.state=="1000"){                    (".result").val(res.data)
               }else{
                   alert(res.msg)
               }
           }
       })
    });
</script>
</body>
</html>
HTML

三、案例及作业

1、登录成功跳转个人首页,失败局部刷新提示用户

login.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
    <script src="/static/jquery-3.1.js"></script>
</head>
<body>
<h3>欢迎来到登录页面</h3>
{% csrf_token %}
<div class="col-md-4 col-md-offset-3">
    <label for="user">账号</label>
    <input type="text" id="user" placeholder="请输入您的账号" class="form-control">
</div>

<div class="col-md-4 col-md-offset-3">
    <label for="pwd">密码</label>
    <input type="password" id="pwd" placeholder="请输入你的密码" class="form-control">
</div>

<div class="col-md-4 col-md-offset-3">
    <br>
    <button class="ajax1 btn btn-default ">确认</button>
    <button class="ajax2 btn btn-default ">取消</button>
    <p class="con"></p>
</div>

<script>

    (".ajax1").click(function () {         .ajax({
            url:"/login/",
            type:"post",
            data:{        {# 这一步发送数据给服务器 #}
                user:("#user").val(),                 pwd:("#pwd").val(),
                csrfmiddlewaretoken:("[name='csrfmiddlewaretoken']").val()  {#  可以在settings文件中取消  #}             },             success:function (res) {  {# 服务器处理成功后,返回数据到这一步给前端 #}                 if (res.user) {                     location.href="/books/"  {# 让浏览器重新发送新的页面请求,类似redirect #}                 }else{                     {# #}                     (".con").html(res.msg).css("color","red");   {# 显示错误信息 #}
                    setTimeout(function () {   {## 定时一秒后,将错误提示去掉#}
                        $(".con").html("")
                    },1000)
                }
            }
        })
    })
</script>
</body>
</html>
HTML

views.py视图文件

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
import json
from book import models
from django.http import JsonResponse

def login(requeset):
    if requeset.method == "GET":
        return render(requeset,"login.html")
    else:
        res={"user":None,"msg":None}
        user = requeset.POST.get("user") # 拿到用户名
        pwd = requeset.POST.get("pwd")  # 拿到用户的登录密码,进行比对
        user_obj=models.UserInfo.objects.filter(user=user,pwd=pwd).first()  # 跟数据库的数据进行比对,
        if user_obj:
            res["user"]="alex"
        else:
            res["msg"]="用户名或密码错误!"
        return JsonResponse(res)

Python

2、基于ajax删除已有书籍,局部刷新

books.html文件(部分)

<tbody class="tbody">
            {% for book in queryset %}
                <tr>
                    <td>{{ forloop.counter }}</td>   {# forloop.counter,提供自动计数,保证删除是,Id可以跟着变动#}
                    <td>{{ book.title }}</td>
                    <td>{{ book.price }}</td>
                    <td>{{ book.publish }}</td>
                    <td>{{ book.pub_date|date:"Y-m-d " }}</td>
                    <td>
{#      通过多表查询得到作者名字,因为有可能有多个作者,所以要用for循环取出#}
                        {% for author in book.authors.all %}
                        <span>{{ author.name }}</span>
                        {% endfor %}
                    </td>
                    <td>
                        <button class="ajax2"  pk="{{ book.pk }}">ajax删除</button>
                        <a href="/books/delete/{{%20book.pk%20}}">删除</a>
{#      在生成显示页面的时候,book.pk就每次都更新了,点击的时候,就会对应的跳转#}
                        <a href="/books/edit/{{%20book.pk%20}}">编辑</a>
                    {#      a标签默认GET请求方式 #}
                    </td>
                </tr>
            {% endfor %}

            </tbody>

<script>
    (".ajax2").click(function () {         // 发送ajax请求         let num = (this).attr("pk");  {# 自定义一个值,用当前的ID赋值给其,在这里取出   #}
        let tr = (this).parent().parent();
        .ajax({             url:"/del_ajax/", {# 如何获取动态的url  #}                {#不写默认get请求 #}             data:{                 pk:num, {# 注意这里不能写(this),这个是js的语法,不是ajax的,值得名字随意,键要跟视图函数对齐,那边要取  #}
            },
            success:function (res) {
                if (res.state){
                    $tr.replaceWith("<tr><td style='color:red'> 删除成功!</td></tr>")
                }else{
                    alert("失败了")
                }
            }
        })
    })
</script>
HTML

views.py视图函数

from django.shortcuts import render,HttpResponse,redirect

from book import models
from django.http import JsonResponse

def del_ajax(request):
    res={"state":True}
    try:
        pk=request.GET.get("pk")  # 拿到主键ID
        models.Book.objects.filter(pk=pk).delete() # 根据主键从数据库中删除
    except Exception as e:
        res["state"]=False  # 如果不能删除,返回False状态进行报错
    return JsonResponse(res)
Python

3、案例

1、用户名是否已被注册

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

客户端得到服务器返回的结果后,
确定是否在用户名文本框后显示“用户名已被注册”的错误信息!

2、基于Ajax进行登录验证

用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,

客户端通过响应信息确定是否登录成功,成功,则跳转到首页,

否则,在页面上显示相应的错误信息。

四、请求头ContentType(看完后,看后面的文件上传实例来看)

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

1、application/x-www-form-urlencoded(默认的,Django默认按这个解析)

这应该是最常见的 POST 提交数据的方式了。
浏览器的原生 

<

form> 表单,如果不设置 enctype 属性,
那么最终就会以 application/x-www-form-urlencoded 方式提交数据。

请求类似于下面这样(无关的请求头在本文中都省略掉了):
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

user=yuan&age=22
Bash

2、multipart/form-data(用于提交文件)

这又是一个常见的 POST 数据提交的方式。
我们使用表单上传文件时,
必须让form表单的 enctype 等于 multipart/form-data。
直接来看一个请求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="user"

yuan
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
Bash
这个例子稍微复杂点。
首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。
然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。

消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,
紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。

如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。
关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。

这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式
(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。
其实 enctype 还支持 text/plain,不过用得非常少)。
Bash

3、application/json(使用json字符串进行数据传输,现在也很常用)

application/json 这个 Content-Type 作为响应头大家肯定不陌生。

实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。
服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。
原文地址:https://www.cnblogs.com/yipianshuying/p/10252605.html