Ajax简介
什么是Ajax
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
Ajax应用场景
登录注册时的校验,以百度为例
当输入框失去焦点时,触发事件,浏览器发送Ajax请求,服务端进行校验,返回数据给浏览器,显示相应的错误信息
此过程中,整个页面是没有刷新的,同时请求发出后我们还可以进行其他操作,因此是异步的,这就体现了Ajax的两大特点: 异步请求
和 局部刷新
Ajax流程
Ajax请求的流程如下
- 客户端触发异步操作
- 创建新的XMLHttpRequest对象,这是ajax的核心
- 通过send()方法实现与server的连接
- 服务器端接收请求,并处理
- 返回处理的结果,这个结果可以是XML文档、也可以是josn字符串(一般情况下josn就可以处理大部分的结果、而且相对的比较好操作)
- 在客户端去接收服务器传回来的结果,并且通过javascript进行你想要的处理
小结
Ajax特点
- 异步请求
- 局部刷新
实例
Ajax登录验证
准备工作
新建一个项目ajaxDemo,创建一个APP,命名为app1
新建一个数据库ajaxdemo,增加User表模型
models.py
from django.db import models# Create your models here.class User(models.Model): ???username = models.CharField(max_length=32) ???password = models.CharField(max_length=32)
配置urls
urls.py
from django.contrib import adminfrom django.urls import path, re_pathfrom app1 import viewsurlpatterns = [ ???path('admin/', admin.site.urls), ???path('login/', views.login), ???path('index/', views.index),]
编写视图函数
views.py
from django.shortcuts import render, HttpResponse, redirectfrom app1 import modelsimport json# Create your views here.def login(request): ???if request.method == "POST": ???????username = request.POST.get('username') ???????password = request.POST.get('password') ???????response = {"status": False, "username": None, 'msg': None} ???????user_obj = models.User.objects.filter(username=username, password=password).first() ???????if user_obj: ???????????response['status'] = True ???????????response['username'] = username ???????else: ???????????response['msg'] = '用户名或密码错误' ???????# 注意发送之前要序列化 ???????return HttpResponse(json.dumps(response, ensure_ascii=False)) ???else: ???????return render(request, 'login.html')def index(request): ???return render(request, 'index.html')
编写HTML页面
login.html
<!DOCTYPE html><html lang="en"><head> ???<meta charset="UTF-8"> ???<title>用户登录</title> ???<script src="/static/plugins/js/jquery.js"></script></head><body><form action=""> ???{% csrf_token %} ???<p>用户名:<input type="text" name="username"></p> ???<p>密码:<input type="text" name="password"></p> ???<input type="button" class='btn' value="登录"> ???<span class="error"></span></form><script> ???$('.btn').on('click', function () { ???????$.ajax({ ???????????url: '/login/', ???????????//注意这里的方式是type,不是method!!! ???????????type: 'post', ???????????data: { ???????????????username: $("[name='username']").val(), ???????????????password: $("[name='password']").val(), ???????????????csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(), ???????????}, ???????????//成功之后执行回调函数 ???????????success:function (data) { ???????????//反序列化 ???????????console.log(data); ???????????//console.log(typeof data); ???????????data = JSON.parse(data); ???????????if (data['status'] == true) { ???????????????//登录成功跳转到个人主页 ???????????????window.location.href = '/index/'; ???????????} else { ???????????????//登录失败显示错误信息 ???????????????$('.error').html(data['msg']).css('color','red'); ???????????} ???????} ???????}) ???})</script></body></html>
index.html
<!DOCTYPE html><html lang="en"><head> ???<meta charset="UTF-8"> ???<title>个人主页</title></head><body><h3>欢迎来到个人主页</h3></body></html>
密码正确时
密码错误时
小结
Ajax语法
发送Ajax请求的语法为:$.ajax({ ?})
,大括号里放Ajax请求的四要素
Ajax请求四要素
- url: 发送请求的网址
- type:请求的类型,注意不是method
- data: 要发送的数据,是一个javascript对象,可以带上csrfmiddlewaretoken键值对
- 响应状态(通常是success)及回调函数
需要注意的地方
- 前端页面发送Ajax请求时要带上csrfmiddlewaretoken,否则会返回403
- 视图函数里登录成功后不能直接跳转,应返回一个字典(记录状态)交给前端页面完成跳转
- 返回字典之前要序列化(json.dumps())
- 前端页面跳转使用
window.location.href = ‘/index/‘
ajax还有其他参数,可以设置,如下:
<button class="send_Ajax">send_Ajax</button><script> ??????$(".send_Ajax").click(function(){ ??????????$.ajax({ ??????????????url:"/handle_Ajax/", ??????????????type:"POST", ??????????????data:{username:"Yuan",password:123}, ??????????????success:function(data){ ??????????????????console.log(data) ??????????????}, ???????? ??????????????error: function (jqXHR, textStatus, err) { ???????????????????????console.log(arguments); ???????????????????}, ??????????????complete: function (jqXHR, textStatus) { ???????????????????????console.log(textStatus); ???????????????}, ??????????????statusCode: { ???????????????????'403': function (jqXHR, textStatus, err) { ?????????????????????????console.log(arguments); ????????????????????}, ???????????????????'400': function (jqXHR, textStatus, err) { ???????????????????????console.log(arguments); ???????????????????} ???????????????} ??????????}) ??????})</script>
响应错误时,会执行error中的代码。
当 AJAX 请求正在进行时,执行complete的代码。它可以做一个请求等待的效果!
ajax文件上传
首先来看form表单上传文件
上传文件
修改urls.py,增加路径file_upload
from django.contrib import adminfrom django.urls import path, re_pathfrom app1 import viewsurlpatterns = [ ???path('admin/', admin.site.urls), ???path('login/', views.login), ???path('index/', views.index), ???path('file_put', views.file_upload),]
修改views.py,增加视图函数file_upload
def file_upload(request): ???if request.method == "POST": ???????print(request.POST) ???????return HttpResponse('ok') ???return render(request, 'file_upload.html')
在templates里面增加页面file_put.html
<!DOCTYPE html><html lang="en"><head> ???<meta charset="UTF-8"> ???<title>Title</title></head><body><h3>form表单文件上传</h3><form action="" method="post" enctype="multipart/form-data"> ???{% csrf_token %} ???<input type="text" name="user"> ???<input type="file" name="img"><br/><br/> ???<input type="submit"></form></body></html>
注意:enctype的类型不同,发送数据格式也会不同。
form表单enctype默认为application/x-www-form-urlencoded。它的数据格式为key1=value1&key1=value1形式。
它不能发送图片,那么需要指定为multipart/form-data才可以!
选中一个文件,提交
pycharm控制台打印的信息
<QueryDict: {'csrfmiddlewaretoken': ['MiMUVVMla9s9TJ6CVYV4JUiQ6FJFlvU7GBs7RiMEQOfcm2jlybLSEOZBLvZVuEIP'], 'user': ['']}>
可以看到request.POST里面并没有文件的信息,这是因为Django把文件单独封装到另一个属性里面了,这就是request.FILS
修改视图函数
def file_upload(request): ???if request.method == "POST": ???????print(request.POST) ???????print(request.FILES) ???????return HttpResponse('ok') ???return render(request, 'file_upload.html')
查看pycharm控制台打印的信息
<QueryDict: {'csrfmiddlewaretoken': ['NDVAZXADXpgRUA3IcHXRU3egH3oK8Ql0HWBNVkAWD43UnTgrPUNFPXV1mTE0hZ9I'], 'user': ['']}><MultiValueDict: {'img': [<InMemoryUploadedFile: 闭嘴.gif (image/gif)>]}>
这次得到了img信息,它的类型为MultiValueDict。描述了图片的文件名以及图片类型jpeg
存储文件
以上完成了从浏览器上传的部分,但是服务器接收之后还得对文件进行处理如存放等操作
修改file_upload视图函数
def file_upload(request): ???if request.method == "POST": ???????print(request.POST) ???????print(request.FILES) ?# 打印文件信息 ???????file_obj = request.FILES.get('img') ???????print(file_obj) ???????print(type(file_obj)) ?# 打印file_obj对象属性 ???????print(file_obj.name) ???????with open(file_obj.name, 'wb') as f: ???????????for line in file_obj: ???????????????f.write(line) ?# 写入文件 ???????return HttpResponse('ok') ???return render(request, 'file_upload.html')
重新上传,查看控制台打印信息
<QueryDict: {'csrfmiddlewaretoken': ['RmIJ3Eknj2NRN352dgz5F1JoQMgNC0NoLFoWZ1kGZHAUgmiLQtpTAVq9vCw3L9B6'], 'user': ['']}><MultiValueDict: {'img': [<InMemoryUploadedFile: 闭嘴.gif (image/gif)>]}>闭嘴.gif<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>闭嘴.gif
左侧目录下出现了一张图片
因为没有指定路径,所以默认是项目根目录
指定路径存储
在项目根目录下新建statics文件夹,再在statics目录下新建imgs文件夹
修改file_upload视图函数
def file_upload(request): ???if request.method == "POST": ???????print(request.POST) ???????print(request.FILES) ?# 打印文件信息 ???????file_obj = request.FILES.get('img') ???????print(file_obj) ???????print(type(file_obj)) ?# 打印file_obj对象属性 ???????print(file_obj.name) ???????with open('statics/imgs/' + file_obj.name, 'wb') as f: ???????????for line in file_obj: ???????????????f.write(line) ?# 写入文件 ???????return HttpResponse('ok') ???return render(request, 'file_upload.html')
再次上传文件,就保存在了指定的目录
再来看Ajax上传文件
利用Ajax和FormData实现页面无刷新的文件上传效果,主要用到了jQuery的ajax()方法和XMLHttpRequest Level 2的FormData接口。
修改视图函数file_upload
def file_upload(request): ???# form表单上传 ???# if request.method == "POST": ???# ????print(request.POST) ???# ????print(request.FILES) ?# 打印文件信息 ???# ????# ????file_obj = request.FILES.get('img') ???# ????print(file_obj) ???# ????print(type(file_obj)) ?# 打印file_obj对象属性 ???# ????print(file_obj.name) ???# ????# 图片读取出来是二进制形式 ???# ????with open('statics/imgs/' + file_obj.name, 'wb') as f: ???# ????????for line in file_obj: ???# ????????????f.write(line) ?# 写入文件 ???# ????# ????return HttpResponse('ok') ???# return render(request, 'file_upload.html') ???????# Ajax上传文件 ???if request.method == "POST": ???????print(request.POST) ???????print(request.FILES) ?# 打印文件信息 ???????????????file_obj = request.FILES.get('img') ?# 获取img对象 ???????print(file_obj, type(file_obj)) ???????print(file_obj.__dict__) ???????print(file_obj.name) ???????????????# 返回给ajax回调函数的数据 ???????response = {"status": False} ???????with open('statics/imgs/' + file_obj.name, 'wb') as f: ???????????for line in file_obj: ???????????????# write的返回值是写入的字符长度 ???????????????ret = f.write(line) ???????????????# 判断写入的文件是否为空,不为空时才把status置为True ???????????????if ret: ???????????????????response["status"] = True ???????return HttpResponse(json.dumps(response)) ?# 返回json数据 ???????
修改file_upload.html
<!DOCTYPE html><html lang="en"><head> ???<meta charset="UTF-8"> ???<title>Title</title> ???<script src="/static/plugins/js/jquery.js"></script></head><body>{#<h3>form表单文件上传</h3>#}{# 表单默认为application/x-www-form-urlencoded。它的数据格式为key1=value1&key1=value1形式。 #}{#<form action="" method="post" enctype="multipart/form-data">#}{# ???{% csrf_token %}#}{# ???<input type="text" name="user">#}{# ???<input type="file" name="img"><br/><br/>#}{# ???<input type="submit">#}{#</form>#}<h3>Ajax上传文件</h3>{% csrf_token %}<form action=""> ???<input type="text" id="username"> ???<input type="file" id="avatar"> ???<input type="button" id="ajax-submit" value="ajax提交"></form><script> ???$('#ajax-submit').click(function () { ???????var csrf = $("[name=csrfmiddlewaretoken]").val(); ???????console.log(csrf); ???????var formdata = new FormData; ???????//给当前FormData对象添加一个键值对 ???????formdata.append("csrfmiddlewaretoken", csrf); ???????formdata.append("username", $('#username').val()); ???????//$('#avatar')[0]表示input标签 ???????//$('#avatar')[0].files表示获取到的文件列表 ???????//$('#avatar')[0].files[0]表示文件对象 ???????//要上传其他类型的文件,把img改成file就行,当然views里面对应的也要改 ???????formdata.append('img', $('#avatar')[0].files[0]); ???????$.ajax({ ???????????url: '', //表示当前路径 ???????????type: 'post', ???????????//发送一个FormData对象 ???????????data: formdata, ???????????//告诉jQuery不处理数据,默认是true,会把数据转化成&uname=abc&pwd=123的形式 ???????????processData: false, ???????????//告诉jQuery不设置内容类型 ???????????contentType: false, ???????????success: function (data) { ???????????????data = JSON.parse(data); ???????????????if (data["status"] == true) { ???????????????????alert('上传成功!'); ???????????????????window.location.href='/file_upload/'; ???????????????} else { ???????????????????alert('上传失败!') ???????????????} ???????????} ???????}) ???})</script></body></html>
小结
form表单上传文件要点
- 需在form表单设置enctype="multipart/form-data"然后用submit提交
- 视图函数里用request.FILES.get(‘file‘)获取文件对象
- 服务端接收到文件对象后对其逐行读取并写入新文件
Ajax上传文件要点
- 使用FormData对象发送文件数据(把FormData对象设为data的值)
- FormData对象添加数据用
formdata.append(key,value)
的形式 - 需要加上
processData: false
和contentType: false
来告诉jQuery不处理数据,不设置内容类型
Django与Ajax
原文地址:https://www.cnblogs.com/zzliu/p/10603452.html