ajax
一 什么叫ajax
Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
三 廖雪峰的介绍
AJAX不是JavaScript的规范,它只是一个哥们“发明”的缩写:Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求。
如果仔细观察一个Form的提交,你就会发现,一旦用户点击“Submit”按钮,表单开始提交,浏览器就会刷新页面,然后在新页面里告诉你操作是成功了还是失败了。如果不幸由于网络太慢或者其他原因,就会得到一个404页面。
这就是Web的运作原理:一次HTTP请求对应一个页面。
如果要让用户留在当前页面中,同时发出新的HTTP请求,就必须用JavaScript发送这个新请求,接收到数据后,再用JavaScript更新页面,这样一来,用户就感觉自己仍然停留在当前页面,但是数据却可以不断地更新。
用JavaScript写一个完整的AJAX代码并不复杂,但是需要注意:AJAX请求是异步执行的,也就是说,要通过回调函数获得响应。
四 对ajax异步的理解
1 打个比方吧,通常情况下,用户注册,那么用户首先得填写好表单,然后点提交,这样表单就会向服务发出一个请求,则服务器处理代码,如果用户存在,则返回一个信息。总之,就是所有的数据需要你点提交后,信息才会发送!
而AJAX就相当于是模拟了一个信息发送请求,你可以在很多网站上注册的时候会发现,比如用户名输入“123”,那么它可能会提示你该用户已经存在,而给你的感觉是页面并没刷新,也就是并没有提交表单,而用户名又是存放在数据库内的,也就是说要查询用户名是否存在,就必须得发送表单的里的用户名,然后再在数据库中去查询。
而这个过程就是用了AJAX来处理的,用户输入用户名,当表单的焦点发生变化的时候,则会触发AJAX,然后AJAX模拟一个GET或者POST请求给服务器,服务器就会处理传递过来的数据!而服务器在处理数据的时候,你可以做其它的,比较你可以填写密码或者其它的!
2 与同步的区别
这个要跟同步的概念一起理解,举个同步的例子
就是当你浏览页面的时候,你点击一个按钮或者链接,那么这个界面就会向服务器发送请求,此时你眼前的界面就是一片空白,直到请求的数据返回页面上才有东西显示。就是一个操作要等前一个做完才可以开始。
而异步则不同,比如一个注册页面
你填写名字,密码,邮箱之类的信息,界面看上去什么都没有变化,但是其实你注册的这个界面已经向服务器发送了一个请求来验证你的用户名是否已经存在。就是后台与界面可以进行数据交互,而界面则可以继续保持一直跟用户交互而不受影响。
五$.ajax()方法
$.ajax() 返回其创建的 XMLHttpRequest 对象。大多数情况下你无需直接操作该函数,除非你需要操作不常用的选项,以获得更多的灵活性。
http://www.w3school.com.cn/jquery/ajax_ajax.asp
$.ajax({ url:"/model_add_class/", type:'post', data:{'classname':input1}, success:function (date) { if (date==='OK'){ location.href='/class_list/' } else{ $('#error_message').text(date).parent().parent().addClass('has-error') } } } )
六 ajax应用场景
ajax应用场景是一个系统应用场景,通过JavaScript控制界面,驱动方式为表单驱动。
1 表单驱动的交互
传统的表单提交,在文本框输入内容后,点击按钮,后台处理完毕后,页面刷新,再回头检查是否刷新结果正确。使用Ajax,在点击submit按钮后,立刻进行异步处理,并在页面上快速显示了更新后的结果,这里没有整个页面刷新的问题
2深层次的树的导航
深层次的级联菜单(树)的遍历是一项非常复杂的任务,使用JavaScript来控制显示逻辑,使用Ajax延迟加载更深层次的数据可以有效的减轻服务器的负担。
我们以前的对级联菜单的处理多数是这样的:
为了避免每次对菜单的操作引起的重载页面,不采用每次调用后台的方式,而是一次性将级联菜单的所有数据全部读取出来并写入数组,然后根据用户的操作用 JavaScript来控制它的子集项目的呈现,这样虽然解决了操作响应速度、不重载页面以及避免向服务器频繁发送请求的问题,但是如果用户不对菜单进行 操作或只对菜单中的一部分进行操作的话,那读取的数据中的一部分就会成为冗余数据而浪费用户的资源,特别是在菜单结构复杂、数据量大的情况下(比如菜单有 很多级、每一级菜又有上百个项目),这种弊端就更为突出。
如果在此案中应用Ajax后,结果就会有所改观:
在初始化页面时我们只读出它的第一级的所有数据并显示,在用户操作一级菜单其中一项时,会通过Ajax向后台请求当前一级项目所属的二级子菜单的所有数据,如 果再继续请求已经呈现的二级菜单中的一项时,再向后面请求所操作二级菜单项对应的所有三级菜单的所有数据,以此类推……这样,用什么就取什么、用多少就取 多少,就不会有数据的冗余和浪费,减少了数据下载总量,而且更新页面时不用重载全部内容,只更新需要更新的那部分即可,相对于后台处理并重载的方式缩短了 用户等待时间,也把对资源的浪费降到最低。
3用户间的交流响应
在众多人参与的交流讨论的场景下,最不爽的事情就是让用户一遍又一遍刷新页面以便知道是否有新的讨论出现。新的回复应该以最快的速度显示出来,而把用户从分神的刷新中解脱出来,Ajax是最好的选择。
4类似投票等场景
对于类似这样的场景中,如果提交过程需要达到40秒,很多的用户就会直接忽略过去而不会参与,但是Ajax可以把时间控制在1秒之内,从而更多的用户会加入进来。
5过滤场景
对数据使用过滤器,按照时间排序,或者按照时间和名称排序,开关过滤器等等。任何要求具备很高交互性数据操纵的场合都应该用JavaScript,而不是用一系列的服务器请求来完成。在每次数据更新后,再对其进行查找和处理需要耗费较多的时间,而Ajax可以加速这个过程。
6文本输入场景
在文本框等输入表单中给予输入提示,或者自动完成,可以有效的改善用户体验,尤其是那些自动完成的数据可能来自于服务器端的场合,Ajax是很好的选择。
博客地址:什么时候应该用ajax http://blog.csdn.net/gebi_msdn/article/details/1682210
七 在csrf_token存在使用ajax实现验证登录名,密码
ajax是基于jquery实现的
login.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <title>Title</title> {# <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">#} </head> <body> <form action="{% url 'mylogin' %}" method="post"> {% csrf_token %} 姓名<p><input type="text" name="username"></p> 密码<p><input type="password" name="password"></p> <input type="button" value="提交"><span class="error"></span> </form> <script src="/static/jquery-3.2.1.min.js"></script> {#<script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>#} <script> $(document).ready(function () { $(':button').on('click', function () { #$(':button') input选择器 $.ajax({ url: '{% url 'mylogin' %}', type:'post', data: { #data 在这里出现两次错误了 username: $(':text').val(), password: $(':password').val(), csrfmiddlewaretoken: $('[name=csrfmiddlewaretoken]').val() #属性选择器 [] }, success: function (date) { var date = JSON.parse(date); if (date.status) { location.href = '/index/' #js代码实现跳转页面 } else $('.error').text('用户名或密码错误!'); setTimeout(function () { #第一个参数可以是个函数 $('.error').text('') }, 2000) } }) }) }); </script> </body> </html>
views.login()
def login(request): if request.is_ajax(): #判断是否是ajax请求 name=request.POST.get('username') pwd=request.POST.get('password') if name=='zuo' and pwd=='123': date={'status':1} else: date={'status':0} import json # return json.dumps(date) return HttpResponse(json.dumps(date)) #任何一个视图函数都必须返回一个HttpResponse对象 return render(request,'login.html')
八 contentType属性
request.body的数据是二进制格式的字符串
默认值: "application/x-www-form-urlencoded"。默认值适合大多数情况。
Django 视图函数会自动从request.body中取出。可以用request.POST/GET取值。
如果你明确地传递了一个 content-type 给 $.ajax() 那么它必定会发送给服务器(即使没有数据要发送)。比如是contentType:"application/json"。除了 "application/x-www-form-urlencoded"格式,Django均不能自动懂request.body中取值,均许自己手动取值。
示例:
<script> $('h3').click(function () { $.ajax({ url:'', type:'', data:JSON.stringify({ #data格式要跟着contentType变 name:'xxx', password:'xxx' }), contentType:"application/json", success:function () { } }) }) </script>
对应的视图函数就随之改动为:
def login(request): if request.is_ajax(): date=request.body #从request.body 中取值,为数据是二进制字符串格式 import json date=date.decode('utf-8') dic=json.loads(date)
如果是contentType不是默认的格式,随之而来的就有另一个问题。form表单提交时{%csrf_token%},视图函数并不能取到name="csrfmiddlewaretoken"的input框。
这时需要用另一种方式提交csrf_token。
先介绍一个现象。form表单中没有添加{%csrf_token%}
<form action="/login/" method="post"> <p><input type="text"></p> <p><input type="button" value="提交"></p> </form>
在不做任何操作,不点击任何按钮,不触发任何事件。谷歌浏览器,页面——检查——Network 。左侧Name选中login/,右侧Cookies中浏览器中Request Cookies依然有 csrftoken。
于是乎,有这样一种方式,用jQuery操作获取浏览器的Cookies值。这需要下载文件jQuery Cookie文件。网站:http://plugins.jquery.com/cookie/。或者<script src='cdn地址'></script>。
其格式如下:
<script src="/static/jquery.cookie.js"></script> <script> $.ajax({ url:'', type:'', data:{}, headers:{'X-CSRFToken':$.cookie('csrftoken')} #key值名称是固定的。 }) </script>
适用于:用ajax提交数据时,contentType不是默认格式,此时Django中间件并不能从form表单中取出csrf_token值,避免页面禁止访问。
九 ajax 操作函数
w3c地址:http://www.w3school.com.cn/jquery/jquery_ref_ajax.asp
1 serialize
serialize() 方法通过序列化表单值,创建 URL 编码文本字符串。
创建以标准 URL 编码表示的文本字符串。它的操作对象是代表表单元素集合的 jQuery 对象。
如果要表单元素的值包含到序列字符串中,元素必须使用 name 属性
示例:
<html> <head> <script type="text/javascript" src="/jquery/jquery.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("button").click(function(){ $("div").text($("form").serialize()); }); }); </script> </head> <body> <form action=""> First name: <input type="text" name="FirstName" value="Bill" /><br /> Last name: <input type="text" name="LastName" value="Gates" /><br /> </form> <button>序列化表单值</button> <div></div> </body> </html>
十 ajax 实现登录中的一些说明
前端代码
success:function (data) { if (data.user){ location.href="/index/" } else { console.log(typeof data) $(".error").text(data.error_msg).css("color","red") setTimeout(function () { $(".error").text("") },1000) }
输出:
object
success接收到的data是jquery对象,明白了吗!
所以下面 data.error_msg 用句点符调用,而不是data['error_msg']调用!
视图函数代码
loginResponse={"user":None,"error_msg":""} if valid_code_str.upper()==valid_code.upper(): user=auth.authenticate(username=user,password=pwd) if user: auth.login(request,user) # 设置session loginResponse["user"]=user.username else: loginResponse["error_msg"]="username or password error" else: loginResponse["error_msg"]="valid code error!" print(JsonResponse(loginResponse),type(JsonResponse(loginResponse))) return JsonResponse(loginResponse)
输出:
<JsonResponse status_code=200, "application/json"> <class 'django.http.response.JsonResponse'>
导入JsonResponse类是HttpResponse类的一个子类。用户帮助创建JSON 编码的响应。它从父类继承大部分行为。第一个参数应该是dict实例。
官方文档网址:http://python.usyiyi.cn/documents/django_182/ref/request-response.html