一 Ajax简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
优点:
- AJAX使用Javascript技术向服务器发送异步请求
- AJAX无须刷新整个页面
二 AJAX的异步请求
设计路由
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('add_book/',views.add_book), path('query_book/',views.query_book), #ajax相关 path('ajax_sleep/',views.ajax_sleep), path('ajax_test/',views.ajax_test), #前端页面 path('ajax_temp/',views.ajax_temp), ]
views视图文件
def ajax_sleep(request): import time time.sleep(3) return HttpResponse("sleep 3 senond") def ajax_test(request): return HttpResponse("test...") def ajax_temp(request): return render(request,"ajax_temp.html")
html文件
root@darren-virtual-machine:~/PycharmProjects/orm_demo# vim templates/ajax_temp.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> $("#btn1").click(function () { $.ajax({ url:"/ajax_sleep/", type:"GET", success:function (data) { console.log(data); } } ) }) $("#btn2").click(function () { $.ajax({ url:"/ajax_test/", type:"GET", success:function (data) { console.log(data); } } ) }) </script>> </body> </html>
访问http://127.0.0.1:8000/ajax_temp/,先点击ajax_sleep然后点击test,这时在sleep中间正在执sleep代码,但是在点击test,也会执行,先于sleep输出,说明是一个异步操作,同时点击test后,页面并不会刷新,是一个局部刷新的动作
三 实现ajax的一个计算案例
制作一个如下页面,当在前面输入两个数字,点击提交触发后,会把结果填在第三个框里
设计路由
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('add_book/',views.add_book), path('query_book/',views.query_book), #ajax相关 path('ajax_sleep/',views.ajax_sleep), path('ajax_test/',views.ajax_test), #前端页面 path('ajax_temp/',views.ajax_temp), #ajax求和 path('ajax_sum/',views.ajax_sum), ]
view视图
def ajax_sum(request): if request.is_ajax(): num1 = request.POST.get("num1") num2 = request.POST.get("num2") total = int(num1) + int(num2) return HttpResponse(total)
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button> </div> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> $("#btn1").click(function () { $.ajax({ url:"/ajax_sleep/", type:"GET", success:function (data) { console.log(data); } } ) }) $("#btn2").click(function () { $.ajax({ url:"/ajax_test/", type:"GET", success:function (data) { console.log(data); } } ) }) {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, }, success:function (data) { $("#i3").val(data); } }) }) </script> </body> </html>
访问http://127.0.0.1:8000/ajax_temp/
403报错
是由于crfs影响,添加crfs
修改html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button> </div> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), }, success:function (data) { $("#i3").val(data); } }) }) </script> </body> </html>
再次访问,并输入计算值,点击计算
ajax请求流程
当输入非数字计算
调试信息
File "/root/PycharmProjects/orm_demo/app01/views.py", line 131, in ajax_sum total = int(num1) + int(num2) ValueError: invalid literal for int() with base 10: 'qq' [08/Apr/2020 03:48:19] "POST /ajax_sum/ HTTP/1.1" 500 14677
view视图文件
from django.shortcuts import render,HttpResponse from app01 import models from django.http import JsonResponse def ajax_sum(request): if request.is_ajax(): num1 = request.POST.get("num1") num2 = request.POST.get("num2") ret = {"status":1,"msg":None} try: total = int(num1) + int(num2) ret["msg"] = total except Exception as e: ret['status'] = 0 ret["msg"] = "请输入数字" #需要使用到数据结构,使用json方式传过去,先要导入jsonhttponse return JsonResponse(ret)
html调整
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span> {#多加一个span标签#} </div> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), },
{#默认传输的值是1,就会把传过来的msg值输入,挡status值为0时,就会把自定义的提示显示,和view视图文件对应#} success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); } } }) }) </script> </body> </html>
输入非数字时,会有提示
问题,当再次输入正确格式,提示不会小时,
使用定时器解决,显示2秒后消失
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span> </div> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), }, success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); setTimeout(function () { $("#s1").text(""); },2000) } } }) }) </script> </body> </html>
访问后,输入错误值,两秒后消失
四 基于Ajax上传json数据
url设计
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('add_book/',views.add_book), path('query_book/',views.query_book), #ajax相关 path('ajax_sleep/',views.ajax_sleep), path('ajax_test/',views.ajax_test), #前端页面 path('ajax_temp/',views.ajax_temp), #ajax求和 path('ajax_sum/',views.ajax_sum), #ajax上传json数据 path('ajax_json/',views.ajax_json), ]
views视图文件
视图响应时,必须是HttpResponse 或者 HttpResponse,不能是render或者redict
def ajax_json(request): import json print(request.POST) print(request.body) data = json.loads(request.body.decode()) print(data) return HttpResponse("Ok")
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> <button id="btn4">上传json数据</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span> </div> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 异步案例 #} $("#btn1").click(function () { $.ajax({ url:"/ajax_sleep/", type:"GET", success:function (data) { console.log(data); } } ) }) $("#btn2").click(function () { $.ajax({ url:"/ajax_test/", type:"GET", success:function (data) { console.log(data); } } ) }) {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), }, success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); setTimeout(function () { $("#s1").text(""); },2000) } } }) }); $("#btn4").click(function () { $.ajax({ url:"/ajax_json/", type: "POST", contentType:"json", headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf data: JSON.stringify({ a:100, b:200, user:"darren", }), success:function (data) { console.log(data) } }) }) </script> </body> </html>
访问点击提交json数据
得到结果
调试输出
<QueryDict: {}> b'{"a":100,"b":200,"user":"darren"}' {'a': 100, 'b': 200, 'user': 'darren'}
在使用视图文件时,当使用HttpResponse返回时,前端代码需要使用json的数据,必须需要使用JSON.parse(data){}反序列化才能使用
当使用JsonResponse(ret)返回时,可以直接使用,例如sum案例
五 基于form表单上传文件
下载一张图片到桌面备用,test111.png
url文件
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('add_book/',views.add_book), path('query_book/',views.query_book), #ajax相关 path('ajax_sleep/',views.ajax_sleep), path('ajax_test/',views.ajax_test), #前端页面 path('ajax_temp/',views.ajax_temp), #ajax求和 path('ajax_sum/',views.ajax_sum), #ajax上传json数据 path('ajax_json/',views.ajax_json), #form表单上传 path('upload/',views.upload), ]
views
import os def upload(request): if request.method == "POST": print(request.POST) print(request.FILES) #print(request.body) 报错 file_obj = request.FILES.get('file_name') name = file_obj.name with open(os.path.join("media", name), "wb") as f: for i in file_obj: f.write(i) return HttpResponse('上传成功')
html写一个form表单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> <button id="btn4">上传json数据</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span> </div> <hr> <h3>form表单上传文件</h3> <form action="/upload/" method="POST" enctype="multipart/form-data"> {% csrf_token %} <input type="text" name="user"> <input type="file" name="file_name"> <input type="submit"> </form> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 异步案例 #} $("#btn1").click(function () { $.ajax({ url:"/ajax_sleep/", type:"GET", success:function (data) { console.log(data); } } ) }) $("#btn2").click(function () { $.ajax({ url:"/ajax_test/", type:"GET", success:function (data) { console.log(data); } } ) }) {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), }, success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); setTimeout(function () { $("#s1").text(""); },2000) } } }) }); $("#btn4").click(function () { $.ajax({ url:"/ajax_json/", type: "POST", contentType:"json", headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf data: JSON.stringify({ a:100, b:200, user:"darren", }), success:function (data) { console.log(data) } }) }) </script> </body> </html>
root@darren-virtual-machine:~/PycharmProjects/orm_demo# mkdir media
访问,选择文件
点击submit,上传成功
调试输出
<QueryDict: {'csrfmiddlewaretoken': ['JA1GUiIv2LZCvSTxFjP8IOMaW7MNb3q3tjI5nOtFyXv6RETZxqq729rBOTFlFkE5'], 'user': ['']}> <MultiValueDict: {'file_name': [<InMemoryUploadedFile: test111.jpeg (image/jpeg)>]}>
服务器查看
root@darren-virtual-machine:~/PycharmProjects/orm_demo# ll media/
六 基于Ajax请求上传文件
修改html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> <button id="btn4">上传json数据</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span> </div> <hr> <h3>form表单上传文件</h3> {# <form action="/upload/" method="POST" enctype="multipart/form-data"> #} {% csrf_token %} <input type="text" id="user" name="user"> <input type="file" id="file1" name="file_name"> <button id="btn5">ajax上传文件</button> {# <input type="submit"> #} {# </form> #} <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 异步案例 #} $("#btn1").click(function () { $.ajax({ url:"/ajax_sleep/", type:"GET", success:function (data) { console.log(data); } } ) }) $("#btn2").click(function () { $.ajax({ url:"/ajax_test/", type:"GET", success:function (data) { console.log(data); } } ) }) {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), }, success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); setTimeout(function () { $("#s1").text(""); },2000) } } }) }); $("#btn4").click(function () { $.ajax({ url:"/ajax_json/", type: "POST", contentType:"json", headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf data: JSON.stringify({ a:100, b:200, user:"darren", }), success:function (data) { console.log(data) } }) }) </script> </body> </html>
调试
添加ajax
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <button id="btn1">ajax_sleep</button> <button id="btn2">ajax_test</button> <button id="btn4">上传json数据</button> {% csrf_token %} <hr> <div> <input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="btn3">计算</button><span id="s1"></span> </div> <hr> <h3>form表单上传文件</h3> {# <form action="/upload/" method="POST" enctype="multipart/form-data"> #} {% csrf_token %} <input type="text" id="user" name="user"> <input type="file" id="file1" name="file_name"> <button id="btn5">ajax上传文件</button> {# <input type="submit"> #} {# </form> #} <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script> {# 异步案例 #} $("#btn1").click(function () { $.ajax({ url:"/ajax_sleep/", type:"GET", success:function (data) { console.log(data); } } ) }) $("#btn2").click(function () { $.ajax({ url:"/ajax_test/", type:"GET", success:function (data) { console.log(data); } } ) }) {# 计算案例 #} $('#btn3').click(function () { var num1 = $("#i1").val(); var num2 = $("#i2").val(); $.ajax({ url: "/ajax_sum/", type: "POST", data:{ num1:num1, num2:num2, csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(), }, success:function (data) { if (data.status){ $("#i3").val(data.msg); }else{ $("#s1").text(data.msg); setTimeout(function () { $("#s1").text(""); },2000) } } }) }); $("#btn4").click(function () { $.ajax({ url:"/ajax_json/", type: "POST", contentType:"json", headers: {"X-CSRFToken": $("[name='csrfmiddlewaretoken']").val()}, // 在请求头中添加csrf data: JSON.stringify({ a:100, b:200, user:"darren", }), success:function (data) { console.log(data) } }) }) {# ajax上传文件 #} $("#btn5").click(function () { var formdata = new FormData(); formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); formdata.append("file_name",$("#file1")[0].files[0]); $.ajax({ url: "/upload/", type: "POST", processData: false, // 告诉jQuery不要去处理发送的数据 contentType: false, // 告诉jQuery不要去设置Content-Type请求头 data: formdata, success:function (data) { console.log(data) } }) }) </script> </body> </html>
修改图片名为test222
点击ajax上传文件
检查服务器文件
root@darren-virtual-machine:~/PycharmProjects/orm_demo# ll media/
七 请求头ContentType
ContentType指的是请求体的编码类型,常见的类型共有3种:
- application/x-www-form-urlencoded应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置
enctype
属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。 - multipart/form-data是另一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的
enctype
等于 multipart/form-data。 - application/json:这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。