Ajax 准备知识: JSON
什么是 JSON ?
JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
JSON 是轻量级的文本数据交换格式
JSON 独立于语言 *
JSON 具有自我描述性, 更易理解
* JSON 使用 JavaScript 语法来描述数据对象, 但是 JSON 仍然独立于语言和平台. JSON 解析器和 JSON 库支持许多不同的编程语言.
啥都别多说了, 上图吧!
合格的 JSON 对象(JSON 只认双引的字符串格式):
- ["one", "two", "three"]
- {
- "one": 1, "two": 2, "three": 3
- }
- {
- "names": ["张三", "李四"]
- }
- [ {
- "name": "张三"
- }, {
- "name": "李四"
- } ]
不合格的 JSON 对象:
- { name: "张三", 'age': 32 } // 属性名必须使用双引号
- [32, 64, 128, 0xFFF] // 不能使用十六进制值
- { "name": "张三", "age": undefined } // 不能使用 undefined
- { "name": "张三",
- "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
- "getName": function() {return this.name;} // 不能使用函数和日期对象
- }
stringify 与 parse 方法
JavaScript 中关于 JSON 对象和字符串转换的两个方法:
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象(JSON 只认双引的字符串格式)
- JSON.parse('{"name":"Howker"}');
- JSON.parse('{name:"Stack"}') ; // 错误
- JSON.parse('[18,undefined]') ; // 错误
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串.
JSON.stringify({"name":"Tonny"})
和 xml 的比较
JSON 格式于 2001 年由 Douglas Crockford 提出, 目的就是取代繁琐笨重的 xml 格式.
JSON 格式有两个显著的优点: 书写简单, 一目了然; 符合 JavaScript 原生语法, 可以由解释引擎直接处理, 不用另外添加解析代码. 所以, JSON 迅速被接受, 已经成为各大网站交换数据的标准格式, 并被写入 ECMAScript 5, 成为标准的一部分.
xml 和 JSON 都使用结构化方法来标记数据, 下面来做一个简单的比较.
用 xml 表示中国部分省市数据如下:
- <?xml version="1.0" encoding="utf-8"?>
- <country>
- <name > 中国</name>
- <province>
- <name > 黑龙江</name>
- <cities>
- <city > 哈尔滨</city>
- <city > 大庆</city>
- </cities>
- </province>
- <province>
- <name > 广东</name>
- <cities>
- <city > 广州</city>
- <city > 深圳</city>
- <city > 珠海</city>
- </cities>
- </province>
- <province>
- <name > 台湾</name>
- <cities>
- <city > 台北</city>
- <city > 高雄</city>
- </cities>
- </province>
- <province>
- <name > 新疆</name>
- <cities>
- <city > 乌鲁木齐</city>
- </cities>
- </province>
- </country>
xml 格式数据
用 JSON 表示如下:
- {
- "name": "中国",
- "province": [{
- "name": "黑龙江",
- "cities": {
- "city": ["哈尔滨", "大庆"]
- }
- }, {
- "name": "广东",
- "cities": {
- "city": ["广州", "深圳", "珠海"]
- }
- }, {
- "name": "台湾",
- "cities": {
- "city": ["台北", "高雄"]
- }
- }, {
- "name": "新疆",
- "cities": {
- "city": ["乌鲁木齐"]
- }
- }]
- }
JSON 格式数据
由上面的两端代码可以看出, JSON 简单的语法格式和清晰的层次结构明显要比 xml 容易阅读, 并且在数据交换方面, 由于 JSON 所使用的字符要比 xml 少得多, 可以大大得节约传输数据所占用得带宽.
Ajax 简介
Ajax(Asynchronous JavaScript And xml)翻译成中文就是 "异步的 Javascript 和 XML". 即使用 JavaScript 语言与服务器进行异步交互, 传输的数据为 xml(当然, 传输的数据不只是 xml).
Ajax 不是新的编程语言, 而是一种使用现有标准的新方法.
Ajax 最大的优点是在不重新加载整个页面的情况下, 可以与服务器交换数据并更新部分网页内容.(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
Ajax 不需要任何浏览器插件, 但需要用户允许 JavaScript 在浏览器上执行.
同步交互: 客户端发出一个请求后, 需要等待服务器响应结束后, 才能发出第二个请求;
异步交互: 客户端发出一个请求后, 无需等待服务器响应结束, 就可以发出第二个请求.
示例
页面输入两个整数, 通过 Ajax 传输到后端计算出结果并返回.
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- </head>
- <body>
- <input type="text" id="i1">
- +
- <input type="text" id="i2">
- =
- <input type="text" id="i3">
- <button id="b1">
- Ajax Test
- </button>
- <script src="/static/jquery-3.3.1.min.js">
- </script>
- <script>
- $('#b1').click(function() {
- $.Ajax({
- url: '',
- type: 'POST',
- data: {
- i1: $('#i1').val(),
- i2: $('#i2').val()
- },
- success: function(data) {
- $('#i3').val(data)
- }
- })
- })
- </script>
- </body>
- </HTML>
HTML 部分代码
- def ajax_test(request):
- if request.method=='POST':
- i1=request.POST.get('i1')
- i2=request.POST.get('i2')
- ret=int(i1)+int(i2)
- return HttpResponse(ret)
- return render(request,'ajax_test.html')
views.py
- from django.conf.urls import url
- from app01 import views
- urlpatterns=[
- url(r'^ajax_test/',views.ajax_test),
- ]
urls.py
Ajax 常见应用情景
搜索引擎根据用户输入的关键字, 自动提示检索关键字.
还有一个很重要的应用场景就是注册时候的用户名的查重.
其实这里就使用了 Ajax 技术! 当文件框发生了输入变化时, 使用 Ajax 技术向服务器发送一个请求, 然后服务器会把查询到的结果响应给浏览器, 最后再把后端返回的结果展示出来.
整个过程中页面没有刷新, 只是刷新页面中的局部位置而已!
当请求发出后, 浏览器还可以进行其他操作, 无需等待服务器的响应!
当输入用户名后, 把光标移动到其他表单项上时, 浏览器会使用 Ajax 技术向服务器发出请求, 服务器会查询名为 lemontree7777777 的用户是否存在, 最终服务器返回 true 表示名为 lemontree7777777 的用户已经存在了, 浏览器在得到结果后显示 "用户名已被注册!".
整个过程中页面没有刷新, 只是局部刷新了;
在请求发出后, 浏览器不用等待服务器响应结果就可以进行其他操作;
Ajax 的优缺点
优点:
Ajax 使用 JavaScript 技术向服务器发送异步请求;
Ajax 请求无须刷新整个页面;
因为服务器响应内容不再是整个页面, 而是页面中的部分内容, 所以 Ajax 性能高;
两个关键点: 1. 局部刷新, 2. 异步请求
jQuery 实现的 Ajax
最基本的 jQuery 发送 Ajax 请求示例:
- <!DOCTYPE HTML>
- <HTML lang="en">
- <head>
- <meta charset="UTF-8">
- <title>
- Title
- </title>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <style>
- .hide { display: none; }
- </style>
- </head>
- <body>
- <p>
- <input type="text" class="user">
- <span class="hide" style="color: red">
- 用户名已存在
- </span>
- </p>
- <script src="/static/jquery-3.3.1.min.js">
- </script>
- {# 下面这一项是基于 jQuery 的基础上自动给我们的每一个 Ajax 绑定一个请求头信息, 类似于 form 表单提交 post 数据必须要有的
- csrf_token 一样 #} {# 否则我的 Django 中间件里面的校验 csrf_token 那一项会认为你这个请求不是合法的, 阻止你的请求
- #}
- <script src="/static/setup_Ajax.js">
- </script>
- <script>
- // 给 input 框绑定一个失去焦点的事件
- $('.user').blur(function() {
- //$.Ajax 为固定用法, 表示启用 Ajax
- $.Ajax({
- //url 后面跟的是你这个 Ajax 提交数据的路径, 向谁提交, 不写就是向当前路径提交
- url: '',
- //type 为标定你这个 Ajax 请求的方法
- type: 'POST',
- //data 后面跟的就是你提交给后端的数据
- data: {
- 'username': $(this).val()
- },
- //success 为回调函数, 参数 data 即后端给你返回的数据
- success: function(data) {
- ret = JSON.parse(data);
- if (ret['flag']) {
- $('p>span').removeClass('hide');
- }
- }
- })
- });
- </script>
- </body>
- </HTML>
请一定点开看一看
views.py:
- def index(request):
- if request.method=='POST':
- ret={'flag':False}
- username=request.POST.get('username')
- if username=='JBY':
- ret['flag']=True
- import JSON
- return HttpResponse(JSON.dumps(ret))
- return render(request,'index.html')
views.py
$.Ajax 参数
data 参数中的键值对, 如果值值不为字符串, 需要将其转换成字符串类型.
- $("#b1").on("click", function () {
- $.Ajax({
- url:"/ajax_add/",
- type:"GET",
- data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
- success:function (data) {
- $("#i3").val(data);
- }
- })
- })
JS 实现 Ajax(了解)
- var b2 = document.getElementById("b2");
- b2.onclick = function () {
- // 原生 JS
- var xmlHttp = new XMLHttpRequest();
- xmlHttp.open("POST", "/ajax_test/", true);
- xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
- xmlHttp.send("username=q1mi&password=123456");
- xmlHttp.onreadystatechange = function () {
- if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
- alert(xmlHttp.responseText);
- }
- };
- };
- View Code
Ajax 请求如何设置 csrf_token
不论是 Ajax 还是谁, 只要是向我 Django 提交 post 请求的数据, 都必须校验 csrf_token 来防伪跨站请求, 那么如何在我的 Ajax 中弄这个 csrf_token 呢, 我又不像 form 表单那样可以在表单内部通过一句 {% csrf_token %} 就搞定了......
方式 1
通过获取隐藏的 input 标签中的 csrfmiddlewaretoken 值, 放置在 data 中发送.
- $.Ajax({
- url: "/cookie_ajax/",
- type: "POST",
- data: {
- "username": "Tonny",
- "password": 123456,
- "csrfmiddlewaretoken": $("[name ='csrfmiddlewaretoken']").val() // 使用 jQuery 取出 csrfmiddlewaretoken 的值, 拼接到 data 中
- },
- success: function (data) {
- console.log(data);
- }
- })
方式 2
通过获取返回的 cookie 中的字符串 放置在请求头中发送.
注意: 需要引入一个 jQuery.cookie.JS 插件.
- $.Ajax({
- url: "/cookie_ajax/",
- type: "POST",
- headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 从 Cookie 取 csrf_token, 并设置 Ajax 请求头
- data: {"username": "Q1mi", "password": 123456},
- success: function (data) {
- console.log(data);
- }
- })
- View Code
方式 3
或者用自己写一个 getCookie 方法:
- function getCookie(name) {
- var cookieValue = null;
- if (document.cookie && document.cookie !== '') {
- var cookies = document.cookie.split(';');
- for (var i = 0; i < cookies.length; i++) {
- var cookie = jQuery.trim(cookies[i]);
- // Does this cookie string begin with the name we want?
- if (cookie.substring(0, name.length + 1) === (name + '=')) {
- cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
- break;
- }
- }
- }
- return cookieValue;
- }
- var csrftoken = getCookie('csrftoken');
- View Code
每一次都这么写太麻烦了, 可以使用 $.ajaxSetup()方法为 Ajax 请求统一设置.
- function csrfSafeMethod(method) {
- // these HTTP methods do not require CSRF protection
- return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
- }
- $.ajaxSetup({
- beforeSend: function (xhr, settings) {
- if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
- xhr.setRequestHeader("X-CSRFToken", csrftoken);
- }
- }
- });
将下面的文件配置到你的 Django 项目的静态文件中, 在 HTML 页面上通过导入该文件即可自动帮我们解决 Ajax 提交 post 数据时校验 csrf_token 的问题,(导入该配置文件之前, 需要先导入 jQuery, 因为这个配置文件内的内容是基于 jQuery 来实现的)
更多细节详见: Djagno 官方文档中关于 CSRF 的内容 https://docs.djangoproject.com/en/1.11/ref/csrf/
练习(用户名是否已被注册)
功能介绍
在注册表单中, 当用户填写了用户名后, 把光标移开后, 会自动向服务器发送异步请求. 服务器返回这个用户名是否已经被注册过.
案例分析
页面中给出注册表单;
在 username input 标签中绑定 onblur 事件处理函数.
当 input 标签失去焦点后获取 username 表单字段的值, 向服务端发送 Ajax 请求;
django 的视图函数中处理该请求, 获取 username 值, 判断该用户在数据库中是否被注册, 如果被注册了就返回 "该用户已被注册", 否则响应 "该用户名可以注册".
答案就在前面的示例中, 看你能不能找到了......
序列化
Django 内置的 serializers
什么意思呢? 就是我的前段想拿到由 ORM 得到的数据库里面的一个个用户对象, 我的后端想直接将实例化出来的数据对象直接发送给客户端, 那么这个时候, 就可以用 Django 给我们提供的序列化方式
- def ser(request):
- #拿到用户表里面的所有的用户对象
- user_list=models.User.objects.all()
- #导入内置序列化模块
- from django.core import serializers
- #调用该模块下的方法, 第一个参数是你想以什么样的方式序列化你的数据
- ret=serializers.serialize('json',user_list)
- return HttpResponse(ret)
补充一个 SweetAlert 插件示例
点击下载 Bootstrap-sweetalert 项目 https://github.com/lipis/bootstrap-sweetalert .
- $("#b55").click(function () {
- swal({
- title: "你确定要删除吗?",
- text: "删除可就找不回来了哦!",
- type: "warning",
- showCancelButton: true, // 是否显示取消按钮
- confirmButtonClass: "btn-danger", // 确认按钮的样式类
- confirmButtonText: "删除", // 确认按钮文本
- cancelButtonText: "取消", // 取消按钮文本
- closeOnConfirm: false, // 点击确认按钮不关闭弹框
- showLoaderOnConfirm: true // 显示正在删除的动画效果
- },
- function () {
- var deleteId = 2;
- $.Ajax({
- url: "/delete_book/",
- type: "post",
- data: {"id": deleteId},
- success: function (data) {
- if (data.code === 0) {
- swal("删除成功!", "你可以准备跑路了!", "success");
- } else {
- swal("删除失败", "你可以再尝试一下!", "error")
- }
- }
- })
- });
- })
上面这个二次确认的动态框样式, 你也可以直接应用到你的项目中
提醒事项:
1. 上述的样式类部分渲染的样式来自于 Bootstrap 中, 所有建议在使用上述样式时, 将 Bootstrap 的 JS 和 CSS 也导入了, 这样的情况下, 页面效果就不会有任何问题
2. 弹出的上述模态框中, 可能字体会被图标掩盖一部分, 可通过调整字体的上外边距来解决
来源: http://www.bubuko.com/infodetail-3210535.html