Ajax
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
优点:
- AJAX使用Javascript技术向服务器发送异步请求
- AJAX无须刷新整个页面
基于Ajax的登录验证
用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功,则跳转到首页,否则,在页面上显示相应的错误信息。
HTML文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Ajax登录验证</title> <script src="/static/jquery-3.3.1.js"></script> </head> <body> <from> 用户名 <input type="text" id="user"> 密码 <input type="password" id="pwd"> <input type="button" class="login-btn" value="提交"> <span class="error"></span> </from> </body> <script> $('.login-btn').click(function () { $.ajax({ url: '/auth_login/', type: 'post', data: { 'user': $('#user').val(), 'pwd': $('#pwd').val(), }, success: function (data) { console.log(data); console.log(typeof data); {# 把接收的字符转换成js能别的json数据#} var data = JSON.parse(data); console.log(data); console.log(typeof data); console.log(data.user) if (data.user) { location.href = 'https://www.baidu.com' } else { $('.error').html(data.msg).css({'color':'red','margin-left':'10px'}) } } }) }) </script> </html>
后端代码
def auth_login(request): print(request.POST) username = request.POST.get('user') pwd = request.POST.get('pwd') auth = user.objects.filter(name=username,pwd=pwd).first() ret = {'user
':None,'msg':None} if auth: ret['user'] = auth.name else: ret['msg'] ='username or password wrong!' return HttpResponse(json.dumps(ret))
基于from表单的文件上传
请求头ContentType
ContentType指的是请求体的编码类型,常见的类型共有3种:
1 application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype
属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。:
<from> 用户名 <input type="text" id="user"> 密码 <input type="password" id="pwd"> <input type="button" class="login-btn" value="提交"> <span class="error"></span> </from>
上面的from表单中,没有设置enctype属性.通过F12来查看请求信息的时候,我们可以看到:Content-Type:application/x-www-form-urlencoded; charset=UTF-8
2 multipart/form-data
这是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype
等于 multipart/form-data。直接来看一个请求示例:
<form action="" method="post" enctype="multipart/form-data" > 文件名 <input type="file" name="header-ico" id="file"> <input type="submit" class="sub-btn" > </form>
请求信息:Content-Type: multipart/form-data; boundary=----WebKitFormBoundary0LhrB6nJGlWvdFz9
3 application/json
application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。
文件上传 完整的例子:
HTML
file_input.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>基于form表单的文件上传</title> <script src="/static/jquery-3.3.1.js"></script> </head> <body> <form action="" method="post" enctype="multipart/form-data" > 文件名 <input type="file" name="header-ico" id="file"> <input type="submit" class="sub-btn" > </form> </body> </html>
Django代码
views.py
def file_input(request): if request.method=='POST': print(request.POST) print('文件信息:',request.FILES) file_obj = request.FILES.get('header-ico') with open(file_obj.name,'wb')as f: for line in file_obj: f.write(line) return HttpResponse('ok') return render(request,'file_input.html')
基于Ajax的文件上传
jQuery获取文件的方式:
''' $('文件id或class')[0].files[0]:获取的是一个文件对象.它的属性有: name:文件完整的名称,包含后缀名 lastModified:最后修改时间,格式为时间戳格式 lastModifiedDate: 最后修改的时间,格式为日期型 webkitRelativePath:文件路径 size:文件大小,格式为字节,转换为KB需要除以1024 type:文件类型 '''
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>基于form表单的文件上传</title> <script src="/static/jquery-3.3.1.js"></script> </head> <body> <hr> <h3>基于ajax的文件上传</h3> <form action="" method="post"> 用户名 <input type="text" id="user"> 文件名 <input type="file" id="ajax_file"> <input type="button" class="btn" value="上传"> <input type="button" class="sub-btn" value="测试" onclick="javascript:check()"> </form> </body> <script> $('.btn').click(function () { var files_obj = $('#ajax_file')[0].files[0]; console.log(files_obj.size); var file_size = files_obj.size; if (file_size/1024>512){ alert('上传的文件大于500KB,请重新上传!'); console.log('上传失败!'); return false }else { console.log('上传成功!'); } {#以下是固定格式,如果是使用ajax来上传文件,必须要按照以下格式来写,新建一个fromdata对象,#} {# 并在ajax中添加2个参数:contentType:false,processData:false.processData:是否对数据进行预处理,contentType:表示预处理时使用的编码格式#} var fromdata = new FormData(); fromdata.append('user',$('#user').val()); fromdata.append('header',$('#ajax_file')[0].files[0]); {# 这里的header-ico是views里,取文件对象时用到的 #} $.ajax({ url:'', type:'post', contentType:false, processData:false, data:fromdata, success:function (data) { console.log('数据',data) } }) }); {#检测文件大小#} function check() { var files_obj = $('#ajax_file')[0].files[0]; console.log(files_obj.size); for (key in files_obj) { console.log(key,files_obj[key]); } var file_size = files_obj.size; size_kb = Math.round(file_size/1024); {#alert(file_size);#} {#alert('文件大小:'+size_kb+"kb");#} if (size_kb>512){ alert('上传的文件大于500KB,请重新上传!'); $('#ajax_file').val(''); console.log('文件太大!'); return false }else { console.log('文件大小符合!'); } } {#当前文件框发生变化时,调用check函数检测文件大小#} $('#ajax_file').change(function () { {#alert('文件筐已经发生变化')#} check() }) </script> </html>
views.py
def file_input(request): if request.method=='POST': # print('文件报头:', request.body) print(request.POST) # print('文件报头:', request.body) # 这里遇到一个坑,一直把request.body放到了request.POST后面.导致文件无法上传,且报错django.http.request.RawPostDataException: You cannot access body after reading from request's data stream # 猜想应该是读取信息的时候,先读取出body,才读取Post,顺序错了。就是说POST数据在body中,不能比body先读取 print('文件信息:',request.FILES) file_obj = request.FILES.get('header') print(file_obj) with open(file_obj.name,'wb')as f: for line in file_obj: f.write(line) return HttpResponse('ok') return render(request,'file_input.html')