视图之Ajax、Json

Ajax

同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;

异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

AJAX(Asynchronous Javascript And XML):异步的Javascript和XML。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(现在更多使用json数据)。AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应。

AJAX常见应用情景:搜索引擎根据用户输入的关键字,自动提示检索关键字;注册时候的用户名的查重,当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询用户是否存在。

优点:

  1. AJAX使用JavaScript技术向服务器发送异步请求;

  2. AJAX请求无须刷新整个页面;

  3. 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;

例:登陆认证页面,登陆失败不刷新页面,提示用户登陆失败,登陆成功自动跳转到网站首页。

<--login.html文件内容:--->
{% load static %} <--加载静态文件-->
...
<body>

<div>
    用户名:<input type="text" id="username">
    密码:<input type="text" id="pwd">
    {% csrf_token %}
    <button id="sub">提交</button>
    <span style="color: red;font-size: 12px;" id="error"></span>
</div>
<script src="{% static ‘jquery.js‘ %}"></script>
<script>
    $(‘#sub‘).click(function ({
        $.ajax({
            url:"{% url ‘login‘ %}",  // url反向解析,重定向路径,避免写硬代码。注意加上引号。如果要直接写地址,如url:"/login/",第一个 / 若不写会直接和当前浏览器的地址进行拼接,如果写了会使用ID地址和端口号与之进行拼接。
            type:‘post‘,            //post请求
            data:{username:$(‘#username‘).val(),pwd:$(‘#pwd‘).val(),csrfmiddlewaretoken:$(‘[name=csrfmiddlewaretoken]‘).val()},  //为后端传入数据

            success:function (data{   //data:后端返回的数据
                data = JSON.parse(data);
                if (data[‘status‘]){
                    location.href=data[‘home_url‘];
                }
                else {
                    $(‘#error‘).text(‘用户名或者密码错误!‘)
                }
            }
        })
    })
</script>
</body>
...

<--base.html文件内容:-->
...
<body>
<h1>
    欢迎
</h1>
</body>
...
# urls.py文件内容:
path(‘login/‘, views.login,name=‘login‘),
path(‘home/‘, views.home,name=‘home‘),


# view.py文件内容:
...
from django.http import JsonResponse
def login(request):
    res_dict = {‘status‘:None,‘home_url‘:None}
    if request.method == ‘GET‘:
        return render(request,‘login.html‘)
    else:
        uname = request.POST.get(‘username‘)
        pwd = request.POST.get(‘pwd‘)
        user_obj = models.UserInfo.objects.filter(name=uname,password=pwd).exists()
        import json
        if user_obj:
            res_dict[‘status‘] = True
            res_dict[‘home_url‘] = reverse(‘home‘)
            res_json_dict = json.dumps(res_dict)

            return HttpResponse(res_json_dict,content_type=‘application/json‘# 直接返回字典格式是不可以的,必须转换成json字符串,需要改变响应头中的content类型,当前端ajax拿到数据后,通过data_type或者content_type发现发送来的是个json格式的数据,那么ajax就自动将这个数据反序列化得到了js的数据对象,然后通过对象可以直接操作数据。若不改变,则还需要在前端页面反序列化。
        else:
            res_dict[‘status‘] = False
            return JsonResponse(res_dict) # JsonResponse自动dump数据和传递content_type类型。
def home(request):
    return render(request,‘base.html‘

ajax里面写$(this)时要注意:如果你想在不刷新页面的情况下来添加某些dom对象,并且这个对象也需要绑定事件的话,需要用on来给和他相同的标签对象来绑定事件。

settings配置文件里面加上APPEND_SLASH=False:即当请求用户路径的时,不自动处理路径最后面的/,如果这个值为True,假如写了一个url为path(‘index/‘,views.test),当用户请求127.0.0.1:8000/index时,django会让浏览器重新再发一次请求,并且在这个路径后面加上/,即127.0.0.1:8000/index/,此时和我们的url就能匹配上了,如果设置成false,那么用户在输入127.0.0.1:8000/index,没有最后那个斜杠的路径时,就无法和url匹配上了。但是注意,django只能重定向让浏览器再发一个get请求,当用post方法提交数据的时,就像上面ajax里那个url必须和后端配置的url对应。

Ajax的使用

基于jQuery的实现

<button class="send_Ajax">send_Ajax</button>
<script>
       $(".send_Ajax").click(function(){
           $.ajax({
               url:"",
               type:""// POST/GET
               data:{a:"a",b:"b"}, 
               success:function(data){},

               errorfunction (jqXHR, textStatus, err{},

               completefunction (jqXHR, textStatus{},

               statusCode: {
                    ‘403‘function (jqXHR, textStatus, err{},

                    ‘400‘function (jqXHR, textStatus, err{},
                   ......
                }
           })
       })
</script>

ajax参数

请求参数

data:当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。

processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;如果为false, 那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString(),最后得到一个[object,Object]形式的结果。

contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串:注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象。

traditional::一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]}, traditional为false会对数据进行深层次迭代。

响应参数

dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;dataType的可用值:html|xml|json|text|script

headers:自定制请求头。

Ajax请求设置csrf_token

方式1:通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

$.ajax({
  data: {
    "csrfmiddlewaretoken": $("[name = ‘csrfmiddlewaretoken‘]").val()  // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
  }
})

方式2

$.ajaxSetup({
    data: {csrfmiddlewaretoken‘{{ csrf_token }}‘ },
});

方式3

通过获取返回的cookie中的字符串放置在请求头中发送。 注意:需要引入一个jquery.cookie.js插件。

<script src="{% static ‘js/jquery.cookie.js‘ %}"></script>

$.ajax({
headers:{"X-CSRFToken":$.cookie(‘csrftoken‘)}, 
})

`content_type`:

  1. 响应头默认为:text/html; charset=utf-8

  2. 请求头默认为:application/x-www-form-urlencoded; charset=utf-8即向后端的请求格式为urlencoded,与GET请求提交数据的请求格式相同,但数据位置不同,GET请求数据放在urlhou,urlencoded数据放在了请求体中。数据发送至后端后,Django内部调用了内置的解析器(接口的十大组件之一)将其解析。

  3. 可在ajax中指定contentType类型:

 $.ajax({
            ...
            contentType:"`application/json"  //指定发送json格式
             data:Json.stringify({"k":"1","k2":"2"})  // data参数中的键值对,如果值不为字符串,需要将其转换成字符串类型。
            success:function (data{}
  1. ContentType指的是请求体的编码类型,常见的类型共有3种:
  • application/x-www-form-urlencoded:浏览器的原生
    表单,如果不设置 enctype 属性,那么最终就会以默认格式application/x-www-form-urlencoded方式提交数据,ajax默认也是这个。
  • multipart/form-data:使用表单上传文件时,必须让 表单的 enctype 等于 multipart/form-data。
  • application/json:用来告诉服务端消息主体是序列化后的 JSON 字符串。
  1. 服务端接受到数据之后,通过contenttype类型的值来使用不同的方法解析数据,django不能解析contenttype值为json的数据格式,但可以解析application/x-www-form-urlencoded 和multipart/form-data,如果传json类型的数据,需要自己来写一个解析数据的方法。

Django内置的serializers做序列化

源码:

def books_json(request):
    book_list = models.Book.objects.all()[0:10]
    from django.core import serializers
    ret = serializers.serialize("json", book_list)
    return HttpResponse(ret)

Json

JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation),但JSON 仍然独立于语言和平台,是轻量级的文本数据交换格式,具有自我描述性,更易理解。

视图之Ajax、Json

json数据类型和python数据类型的对比:

视图之Ajax、Json
json数据类型和python数据类型的对比

上面的这几种数据类型进行json.dumps序列化之后都是字符串,注意是由单引号括起的,数据里面的单引号,序列化后会变成双引号。python中的datetime等时间日期类型、集合类型等是不能进行json序列化的,因为json没有对应的格式。

import json
from datetime import datetime
from datetime import date

# 对含有日期格式数据的json数据进行转换
class JsonCustomEncoder(json.JSONEncoder):
    def default(self, field):
        if isinstance(field,datetime):
            return field.strftime(‘%Y-%m-%d %H:%M:%S‘)
        elif isinstance(field,date):
            return field.strftime(‘%Y-%m-%d‘)
        else:
            return json.JSONEncoder.default(self,field)


d1 = datetime.now()

dd = json.dumps(d1,cls=JsonCustomEncoder)
print(dd)

不合格的json对象:

name"张三"‘age‘32 }  // 属性名必须使用双引号
[32641280xFFF// 不能使用十六进制值
"name""张三""age"undefined }  // 不能使用undefined
"name""张三",
  "birthday"new Date(‘Fri, 26 Aug 2011 07:13:10 GMT‘),
  "getName":  function({return this.name;}  // 不能使用函数和日期对象
}

// JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象 
JSON.parse(‘{"name":"张三"}‘);
JSON.parse(‘{name:"张三"}‘) ;   // 错误
JSON.parse(‘[18,undefined]‘) ;   // 错误

// JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 
JSON.stringify({"name":"张三"})

JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。JSON 格式书写简单;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。

视图之Ajax、Json

上一篇:http常见的状态码总结


下一篇:暴风雨的礼物·MySQL07:权限及如何设计数据库