Django与ajax详细

目录

一、什么是Ajax

二 基于jquery的Ajax实现

ajax----->服务器------>ajaxkedudaun  

三 案例

四 文件上传

请求头ContentType

基于Form表单上传文件

基于Ajax上传文件

五 Ajax提交json格式数据的几种方式

六、在Django中返回给前端json格式数据的几种方式

七、Django内置的serializers(把对象序列化成json字符串)


一、什么是Ajax

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。

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

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

AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

具体应用场景:
比如我们在某个网站注册账户的时候, 我们已输入就会有提示, 我们的输入是否合法, 是否重复, 但是在输入之前是没有的, 这运用的就是ajax进行处理的

优点:

  • AJAX使用Javascript技术向服务器发送异步请求

  • AJAX无须刷新整个页面

二 基于jquery的Ajax实现

<button class="send_Ajax">send_Ajax</button>

<script>

// 使用jquery 设置点击事件发送ajax请求

$(".send_Ajax").click(function(){



$.ajax({

// 在里面进传入相应的参数

// 可以请求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>

 

ajax----->服务器------>ajaxkedudaun  

 

三 案例

案例一、 通过Ajax,实现前端输入两个数字,服务器做加法,返回到前端页面
在Django的 views中写上处理ajax请求的视图响应函数

  1. def test_ajax(requests):
    
    n1=int(requests.POST.get('n1'))
    
    n2=int(requests.POST.get('n2'))
    
    return HttpResponse(n1+n2)

     

在前端 前端中的js代码, 其中的步骤和上面的一样

使用jquery做一个点击事件来发送全国的csvn

$("#submit").click(function () {

$.ajax({

url: '/test_ajax/',

type: 'post',

data: {

n1: $("#num1").val(),

n2: $("#num2").val()

},

success: function (data) {

console.log(data)

$("#sum").val(data)

},



})

})

 

在html中的代码

<input type="text" id="num1">+<input type="text" id="num2">=<input type="text" id="sum">

<button id="submit">计算</button>

 

 案例二 基于Ajax进行登录验证

用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功,则跳转到首页,否则,在页面上显示相应的错误信息

首先定义好视图响应函数:
定义视图响应函数的时候, 要先和前台沟通好数据格式, 发送数据的格式, 路由的设置等等一系列问题

def auth(request):

# 设置一个字典

back_dic={'user':None,'message':None}

# 根据后台发送数据的方式获取我们需要的信息

name=request.POST.get('user')

password=request.POST.get('password')

print(name)

print(password)

# 根据获取到的信息和从数据库中拿出来的信息进行比对,得到最终结果然后返回给前台

user=models.user.objects.filter(name=name,password=password).first()

print(user)

# print(user.query) # 可以打印出来查信息的sql语句

# 这里我们只做了简单的校验

if user:

back_dic['user']=user.name

back_dic['message']='成功'

else:

back_dic['message']='用户名或密码错误'

import json

# 使用json 返回给前台一个json格式的数据

return HttpResponse(json.dumps(back_dic))

 

 

前端写在script标签中的js代码, 用来发送 ajax请求

<script>

$("#submit3").click(function () {

$.ajax({

url: '/auth/',

type: 'post',

data: {

'user': $("#id_name").val(),

'password': $('#id_password').val()

},



success: function (data) {

{#console.log(data)#}

var data=JSON.parse(data)

if (data.user){

location.href='https://www.baidu.com'

}else {

$(".error").html(data.message).css({'color':'red','margin-left':'20px'})

}

}





})

}

)</script>

 

traditional:true--->可以序列化一层列表,多层不行,要转成json格式上传

四 文件上传

请求头ContentType

1 application/x-www-form-urlencoded

这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):

POST http://www.example.com HTTP/1.1

Content-Type: application/x-www-form-urlencoded;charset=utf-8



user=onion&age=22

 

以第一种Content Type格式发送数据的时候, 或者如果不指定编码格式,不管是form表单还是ajax传送数据时默认的编码就是unlencode,会把data这个字典转成 key1=value1&key2=valeu2 这种方式,放到request的body体里面, 然后Django会对这种格式的数据做处理, 放到POST的字典里面, 所以在视图响应函数中直接使用request.POST.get()来获取到这种方式进行数据交互

2 multipart/form-data

这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:

POST http://www.example.com HTTP/1.1

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA



------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition: form-data; name="user"



yuan

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition: form-data; name="file"; filename="chrome.png"

Content-Type: image/png



PNG ... content of chrome.png ...

------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

 

这个例子稍微复杂点。首先生成了一个 boundary (边界,分界线)用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。

这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。

随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

3 application/json

application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。当需要提交的数据层次非常深的时候,就可以把数据 JSON 序列化之后再进行提交。也可以把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

基于Form表单上传文件

<form action="/file_put/" method="post" enctype="multipart/form-data">

用户名:<input type="text" name="name">

头像:<input type="file" name="avatar" id="avatar1">

<input type="submit" value="提交">

</form>

 

必须指定 enctype="multipart/form-data"

视图函数:

def file_put(request):

if request.method=='GET':

return render(request,'file_put.html')

else:

# print(request.POST)

# print(request.POST)

print(request.body) # 原始的请求体数据

print(request.GET) # GET请求数据

print(request.POST) # POST请求数据

print(request.FILES) # 上传的文件数据

# print(request.body.decode('utf-8'))

print(request.body.decode('utf-8'))



print(request.FILES)

file_obj=request.FILES.get('avatar')

print(type(file_obj))

with open(file_obj.name,'wb') as f:

for line in file_obj:

f.write(line)

return HttpResponse('ok')

 

 

基于Ajax上传文件

processData:false,     //告诉jQuery不要去处理发送的数据
contentType:false,     // 告诉jQuery不要去设置Content-Type请求头

$("#ajax_button").click(function () {

var formdata=new FormData()

formdata.append('name',$("#id_name2").val())

formdata.append('avatar',$("#avatar2")[0].files[0])

$.ajax({

url:'',

type:'post',

processData:false, //告诉jQuery不要去处理发送的数据

contentType:false,// 告诉jQuery不要去设置Content-Type请求头

data:formdata,

success:function (data) {

console.log(data)



}



})

})

 

浏览器请求头为:

Content-Type:

multipart/form-data; boundary=----WebKitFormBoundaryA5O53SvUXJaF11O2

五 Ajax提交json格式数据的几种方式

在前端提交json格式数据的时候要注意前端发送数据到服务器的时候,服务器对不同编码格式的数据不同的处理方式:
在前端编码格式对服务器处理数据时的影响:

  • 发送的数据只要是urlencoded编码:   Http请求的body体中的数据格式为:key1=value1&key2=valeu2

  • 指定编码格式为json格式:Http请求的body体中的数据格式为:"{"key1":"value1","key2":"valeu2"}",数据到后端需要自己处理

  • 提交到服务器的数据都在 request.body 里,取出来自行处理

指定格式的时候还可以指定编码的格式:

contentType: 

'application/json;charset=utf-8'

,

 

指定发送给后台的数据格式使用contentType来指定, 指定接收后台数据的格式通过datatype来指定:
指定接收后台传回来的数据为json格式时, 如果传回来的数据不是json格式的时候, 在前端的数据解析就会出现问题,  数据就不会正常渲染到页面中,

$("#btn").click(function () {

var dic ={'name': $("#name").val(),'pwd':$("#pwd").val()}

$.ajax({

url: '/file/',

type: 'post',

dataType:'json', // 指定接收后台传回来的数据是json格式的数据时,才会正常解析

data:dic,

success: function (data) {

alert(data.name)

}

})

})

 

方式一:
在ajax请求中,定义一个字典, 并指定发送数据的格式为json, 并且还需要使用JSON.stringify()来将定义的字典转换成json字符串格式进行发送.,这样在Django服务器的request.body总会接收到一个json格式的字符串,只有body体中有数据, Django不会将数据进行处理放进POST或者GET字典中, 这个时候导入json模块进行反序列化(json.load(request.bady))即可将其转换为字典类型, 然后就可以当做一般的字典使用了.

$("#ajax_test").click(function () {

var dic={'name':'eric','age':18}

$.ajax({

url:'',

type:'post',

contentType:'application/json', //一定要指定格式





data:JSON.stringify(dic), //转换成json字符串格式

success:function (data) {

console.log(data)

}



})



})

 

方式二:

借助于formdata对象, formdata是js中的类FormData实例化出来的,  使用的时候实例化出来对象之后, 直接将要发送给后台的数据使用append方法传进去就可以了, append中的第一个参数是key第二个参数是value, value的值可以是输入框的值,也可以是一个文件对象或者, 该对象会将添加入的数据转成json格式, 要注意的是一定要指定processData:false,  contentType:false这两个参数为false, 如果不指定ajax会默认进行处理, 使用formdate的对象的好处是将数据发送回后台的时候,和使用form表单发送的http请求时没有区别的, 同时又因为本身是ajax请求, 可以实现异步提交和局部刷新; 在后台可以按照常规方式获取数据进行处理

$("#ajax_button").click(function () {

var formdata=new FormData()

formdata.append('name',$("#id_name2").val())

formdata.append('avatar',$("#avatar2")[0].files[0])

$.ajax({

url:'',

type:'post',

processData:false, //告诉jQuery不要去处理发送的数据

contentType:false,// 告诉jQuery不要去设置Content-Type请求头

data:formdata,

success:function (data) {

console.log(data)



}



})

})

 

总结:
      如果前端传的格式是json格式,django不会处理body中的内容,需要自己在后台取出来之后进行处理
      只有前端传的格式是urlencoded,或者form-data格式,django才会给处理,处理方式是从body体中取出来放到POST或者GET字典中, 然后在后台根据对应的请求方式进行取值就可以了

六、在Django中返回给前端json格式数据的几种方式

在views中接收到请求, 并经过对数据进行逻辑处理之后,返回给前端的时候, 想要返回一个json格式的数据的方式:

方式一:
利用Django中的JsonResponse
利用这种方式返回数据的时候,在前端接收到的数据就是一个object对象, 也就是我们说的字典对象, 可以在前端直接使用点语法进行取值使用, 原理就是在使用JsonResponse返回数据的时候, JsonResponse在响应头中指定了contentType为'application/json', 在ajax收到数据的时候, 就会根据这个响应头将后天返回的数据进行处理, 处理成一个object对象供自己使用

from django.http import JsonResponse

def login(request):

dic={'status':100,'msg':None}

if request.method == 'GET':

return render(request, 'login.html')

# if request.is_ajax():

if request.method=='POST':

name=request.POST.get('name')

pwd=request.POST.get('pwd')

if name=='lqz' and pwd=='123':

dic['msg'] = '登陆成功'

# 想让前端跳转

# dic['url']='http://www.baidu.com'

dic['url']='/test/'

else:

# 返回json格式字符串

dic['status']=101

dic['msg']='用户名或密码错误'

return JsonResponse(dic)

 

方式二:

使用json模块直接返回一个json格式的字符串, 这种方式在前端ajax接收到响应之后,不会进行转换, 因为在后台我们只是将数据序列化了一下, 返回的实质上还是HttpResponse回去一个字符串, 只不过格式是json格式的, 要想在前端想字典一样使用, 需要在前端使用JSON.parse()进行处理, 处理过后数据就变成了一个object, 就可以按照点语法在前端正常使用了.

import json

from django.http import JsonResponse

def login(request):

dic={'status':100,'msg':None}

if request.method == 'GET':

return render(request, 'login.html')

# if request.is_ajax():

if request.method=='POST':

name=request.POST.get('name')

pwd=request.POST.get('pwd')

if name=='eric' and pwd=='123':

dic['msg'] = '登陆成功'

# 想让前端跳转

# dic['url']='http://www.baidu.com'

dic['url']='/test/'

else:

# 返回json格式字符串

dic['status']=101

dic['msg']='用户名或密码错误'

return HttpResponse(json.dumps(dic))

 

总结:
    1 后端如果返回JsonResponse,前端的ajax内部会自动将json格式字符串转换成字典
    2 后端如果返回HttpResponse,前端的ajax内部不会给你自动转换,拿到的data是字符串类型,需要手动JSON.parse(data)来转成字典

七、Django内置的serializers(把对象序列化成json字符串)

from django.core import serializers





from django.core import serializers

def test(request):

book_list = Book.objects.all()

ret = serializers.serialize("json", book_list)

return HttpResponse(ret)



# 如果不想序列化某些字段, 可以只返回时指定fields, 例如:



data = serializers.serialize('json', users, fields=('username', 'id'))

 

 

posted @ 2020-11-17 20:13  Οo白麒麟оΟ  阅读(860)  评论(0编辑  收藏  举报