Ajax 实战(一)

简介

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

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

优点

  • 异步
  • 局部刷新:不需要刷新整个页面,节省了资源的消耗,给用户的体验极佳

常见应用场景

入门案例

'''
需求:
实现简单的计算器,加法举例
通过Ajax,实现前端输入两个数字,服务器做加法,返回到前端页面
'''
'''urls.py'''
path('', views.test_Ajax)
'''views.py'''
from django.shortcuts import render, HttpResponse def test_Ajax(request):
if request.method == 'POST':
num1 = int(request.POST.get('num1')) # 获取前端提交的数据
num2 = int(request.POST.get('num2'))
print(num1, num2)
return HttpResponse(num1 + num2) # 返回给前端
return render(request, 'sum.html')
'''sum.html'''
'''html结构'''
<div class="container">
<div class="row">
<h1 class="text-center">Ajax</h1>
<div class="col-md-6 col-lg-offset-3 ">
<input type="text" id="d1" class="active form-control">
<p class="text-center">+</p>
<input type="text" id="d2" class="sucess form-control">
<p class="text-center">=</p>
<input type="text" id="d3" class="info form-control">
<br>
<button id='btn' class="btn btn-success btn-block">calculate</button>
</div>
</div>
</div>
'''js实现'''
<script>
{#绑定点击事件#}
$('#btn').click(function () {
{#获取input元素内输入的值#}
var num1 = $('#d1').val()
var num2 = $('#d2').val() $.ajax({
url: '', //ajax请求的地址
method: 'post', //请求方式
data: {num1: num1, num2: num2}, //携带参数
success: function (data) { //服务端成功返回会回调,执行匿名函数
console.log(data)
$('#d3').val(data)
}
})
})
</script>


注意:

使用Ajax的时候,在视图函数中使用request对象方法判断什么类型的请求,如果是Ajax,不管本质是post还是get等,写request.is_ajax()即可

基于Ajax进行登录验证

需求:

1.前端登录页面

2.后端数据库验证前端提交的信息

'''urls.py'''
path('login/', views.login),
'''views.py'''
from django.shortcuts import render,redirect,HttpResponse
from app01 import models
from django.http import JsonResponse
import json def login(request):
if request.method == 'GET':
return render(request,'login.html')
# elif request.method=="POST":
elif request.is_ajax():
response = {'status':200,'msg':None}
username = request.POST.get('username')
password = request.POST.get('password')
# 数据库校验
res = models.User.objects.filter(username=username,password=password).first()
if res:
# 登录成功
# return redirect('http://www.baidu.com') # ajax使用重定向出错
response['msg']='登录成功'
else:
response['msg']='登录失败,用户名或密码错误'
response['status']=404
# return HttpResponse(json.dumps(response))
return JsonResponse(response,safe=False,json_dumps_params={'ensure_ascii':False})
'''models.py'''
from django.db import models class User(models.Model):
name=models.CharField(max_length=32)
password=models.CharField(max_length=32)
<body>
{#<form action="" method="post">#}
<div class="container">
<h1 class="text-center">Ajax登录认证</h1>
<div class="row">
<div class="col-md-8 col-lg-offset-2">
<p>Username: <input type="text" class="form-control" name="username" id="user_id"></p>
<p>Password: <input type="password" class="form-control" name="password" id="pwd_id"></p>
<p><button type="submit" class="btn btn-block btn-primary">提交</button> <span class="error" style="color: tomato"></span></p>
</div>
</div>
</div>
{#</form>#}
</body>
<script>
$('.btn').click(function (){
$.ajax(
{
url:'/login/',
method:'post',
data:{username:$('#user_id').val(),password:$('#pwd_id').val()}, //返回给后端的数据
success:function (data){
console.log(data)
//data是对象类型
if(data.status == 200){
//登录成功,前端重定向
location.href='http://www.baidu.com' }else{
//登录失败
$('.error').html(data.msg)
}
},
error:function (data){
console.log(data)
alert('请求错误')
}
}
)
})
</script>

注意

  • 如果使用Ajax,form表单提交完数据会自己刷新,所有在使用button元素提交的时候会刷两次,可以讲form元素去掉

  • 如果使用Ajax,form元素也可以不去掉,那么就不能使用button元素,可以使用input元素,type=‘button’

  • 在Ajax中,如果使用json模块序列化数据,前端返回的是字符串不是对象,响应头中是text/html格式,需要自己在html页面通过JSON.parse(data)反序列化,ajax接收到数据后需要自己转成对象

  • 在Ajax中,如果使用JsonResponse模块序列化数据,返回的就是一个对象,响应头中是application/json格式,不需要自己手动反序列化,ajax接收到数据后会自动转成对象

  • 如果使用Ajax,能不能解析返回的数据,取决于响应的类型,如果是json类型,那么就自动解析,不是需要自己手动解析

  • 如果使用了ajax,后端就不要返回rediret,render,HttpResponse,直接返回JsonResponse,因为返回json前端才能处理

  • 总结:后端返回数据,统一都用JsonResponse

HTTP请求编码格式和报文

我们知道请求和响应都有数据格式,请求格式常用得比如:urlencoded、form-data、json····响应格式常用得有:text/html、json····

  • application/x-www-form-urlencoded:窗体数据被编码为名称/值对。(默认)。空格转换为 “+” 加号,但不对特殊字符编码。
  • multipart/form-data:窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。
  • text/plain:窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
  • JSON:以纯文本形式进行编码,其格式为JSON

现有HTML代码如下:用属性enctype的值来区分Content-Type

<form action="http://localhost:8080" method="post" enctype="application/x-www-form-urlencoded">

    <input type="text" name="userName" value="zhan gsan"/>
<input type="text" name="password" value="password"/>
<input type="file" name="resultFile" />
<input type="submit" value="submit"/> </form>

当Content-Type为不同值时,报文结果分别为下:

Content-Type=application/x-www-form-urlencoded

浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。

 POST / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 62
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9 userName=zhan+gsan&password=password&resultFile=dddddddddd.vlx

Content-Type=multipart/form-data

浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),name(控件name)等信息,并加上分割符(boundary)。

此报文分割符为:boundary=—-WebKitFormBoundarys70zFPQBqcgHeMy9

POST / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 659
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarys70zFPQBqcgHeMy9
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9 ------WebKitFormBoundarys70zFPQBqcgHeMy9
Content-Disposition: form-data; name="userName" zhan gsan
------WebKitFormBoundarys70zFPQBqcgHeMy9
Content-Disposition: form-data; name="password" password
------WebKitFormBoundarys70zFPQBqcgHeMy9
Content-Disposition: form-data; name="resultFile"; filename="dddddddddd.vlx"
Content-Type: application/octet-stream {"nodes":[{"name":"11111","image":"theme/gast/ren.png","entityId":"1000001"},{"name":"5555","image":"theme/gast/ren.png","entityId":"1000001"}],"edges":[{"source":"11111","target":"5555","relation":"ssss","count":"1","currentExtDepth":"1"}]}
------WebKitFormBoundarys70zFPQBqcgHeMy9--

Content-Type=text/plain

POST / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 66
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: text/plain
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9 userName=zhan gsan
password=password
resultFile=dddddddddd.vlx

参考:请求头编码格式

总结

1 http --post--请求,有编码格式,主流有三种
-urlencoded :默认的----》从request.POST取提交的数据
-form-data :上传文件的----》从request.POST取提交的数据,request.FILES中取文件
-json :ajax发送json格式数据-----》request.POST取不出数据了,需要request.body 2 使用ajax和form表单,默认都是urlencoded格式
3 如果上传文件:form表单指定格式,ajax要使用Formdata对象 4 如果编码方式是urlencoded格式,放到body体中数据格式如下
username=Hammer&password=123 # post请求,Ajax预处理后得数据格式,urlencoded数据格式 5 如果是formdata编码格式,body体中是:两部分,数据和文件 6 如果是json格式,body体中的格式是:就是json格式字符串
-注意:注意:注意:如果这种格式,request.POST取不到值了

上传文件

前面我们介绍到上传文件可以通过form表单来上传文件,通过input元素修改type=file就上传单个文件,如果加multiple参数就可以上传多个文件等····

form表单上传文件

<h1>form表单上传文件</h1>
<form action="" method="post" enctype="multipart/form-data">
<p>用户名:<input type="text" name="name"></p>
<p>文件:<input type="file" name="myfile"></p>
<input type="submit" value="提交">
</form> def file_upload(request):
if request.method=='GET':
return render(request,'file_upload.html')
else:
myfile=request.FILES.get('myfile')
with open(myfile.name,'wb') as f:
for line in myfile:
f.write(line)
return HttpResponse('ok')

现在我们可以使用ajax上传文件,那么格式和编码有什么要求?实例如下:

<h1>ajax上传文件</h1>
<p>用户名:<input type="text" id="id_name"></p>
<p>文件:<input type="file" id="id_myfile"></p>
<button id="id_btn">提交</button> <script>
$('#id_btn').click(function () {
//如果要上传文件,需要借助于一个js的FormData对象
var formdata = new FormData() //实例化得到一个FormData对象
formdata.append('name', $('#id_name').val()) //追加了一个name对应填入的值
//追加文件
var file = $('#id_myfile')[0].files[0]
formdata.append('myfile', file)
$.ajax({
url: 'file_upload',
method: 'post',
//上传文件,一定要注意如下两行
processData: false, //不预处理数据,
contentType: false, //不指定编码格式,使用formdata对象的默认编码就是formdata格式
data: formdata,
success: function (data) {
console.log(data)
}
})
})
</script>
def file_upload(request):
if request.method=='GET':
return render(request,'file_upload.html')
else:
name=request.POST.get('name')
myfile=request.FILES.get('myfile')
print(type(myfile)) # 查看类型
from django.core.files.uploadedfile import InMemoryUploadedFile
with open(myfile.name,'wb') as f:
for line in myfile:
f.write(line) return HttpResponse('上传成功')

先拿到input元素:$(‘#id_myfile’)[0]

再拿到所有文件:$(‘#id_myfile’)[0].files

再通过索引取出要取得文件:$(‘#id_myfile’)[0].files[0]

总结

  • 如果要上传文件,需要借助于一个js的FormData对象
  • Ajax上传局部刷新
  • Ajax上传文件如果不想使用urlencoded默认处理,可以通过 processData: false不预处理,contentType: false不指定编码格式

Ajax上传json格式

注意:json模块在3.5版本之前不可以直接loads二进制格式(bytes),在3.6版本以后可以

Ajax传json格式只需指定编码格式和序列化数据就能上传

后端需要注意得是post请求得从body体里取数据,然后反序列化即可

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body> <h1>ajax提交json格式</h1> <p>用户名: <input type="text" id="id_name"></p>
<p>密码: <input type="password" id="id_password"></p>
<button id="id_button">提交</button>
</body> <script> $('#id_button').click(function () { $.ajax({
url: '/ajax_json/',
method: 'post',
contentType: 'application/json', //指定编码格式
data: JSON.stringify({name:$('#id_name').val(),password:$('#id_password').val()}), //json格式字符串,序列化数据
success: function (data) {
console.log(data)
}
})
})
</script>
</html>

后端

def ajax_json(request):
if request.method=='GET':
return render(request,'ajax_json.html') else:
# json格式,从POST中取不出来
name=request.POST.get('name')
print(type(request.POST)) # 返回QueryDict对象,不允许修改
# from django.http.request import QueryDict
print(name) # None # 在body体中,bytes格式
# django默认只处理两种格式数据urlencode和form-data,json格式需要自己处理
import json
request.data=json.loads(request.body) # 反序列化,从前端获取数据 name=request.data.get('name')
password=request.data.get('password')
print(name)
print(password)
return HttpResponse('ok')

django内置序列化

django提供了一个模块可以将对象直接序列化,然后返回给前端,但是可扩展性低,字段不能控制,返回得是一个整体

from django.core import serializers
def user_list(request):
user_list = models.User.objects.all() # queryset对象
res = serializers.serialize('json', user_list)
return HttpResponse(res)

现在想要字段可控,可以采用for循环列表套字典得格式,然后序列化

def user_list(request):
user_list = models.User.objects.all() # queryset对象
l = []
for user in user_list:
l.append({'name':user.name,'password':user.password})
return JsonResponse(l,safe=False) # 返回给前端
# 如果使用json模块不需要加safe参数

ps:可以通过json.cn将序列化的数据转成对象


【待续】

Ajax 实战(一)的更多相关文章

  1. JQuery+Ajax实战三级下拉列表联动(八)

    本片文章为练习,项目中不会这样写: 一:涉及到的知识点: jQuery Dom操作 jQuery Ajax操作 ASP.net中的json操作 二:用了自动代码生成器 1.Dal层的代码: publi ...

  2. Ajax实战(原生)

    /** 之前一直在学习ajax,也拿jQuery写了很多,感觉还是写原生的对基础的理论理解的深刻.特此书写. * 得到ajax对象 */ function getajaxHttp() { var xm ...

  3. AJAX 实战【三级联动】分析

    使用 AJAX 对全国地名进行选取 <%@ Page Language="C#" AutoEventWireup="true" CodeFile=&quo ...

  4. ajax实战用法详解

    谦虚使人进步,总结使人提高! 以下5个方法执行一般Ajax请求的简短形式,在处理复杂的Ajax请求时应该使用jQuery.ajax() 1.load(url,[data],[callback])载入远 ...

  5. ajax 实战使用

    注意ajax 必须放在script脚本中使用 ajax用于前端朝后端提交数据,并且后端函数处理好结果返回给success函数作为回调函数给前端,前端拿到后端传来的值,比如code==0 来做相应的前端 ...

  6. node+ajax实战案例(6)

    8.删除客户 8.1.发送id到后台 删除用户信息比较简单,只需要把对应行的id发送到后台就可以了 oTable.onclick = function (ev) { var ev = ev || ev ...

  7. node+ajax实战案例(5)

    6.添加客户 6.1.点击添加按钮,弹出表单框 // 添加用户 显示对话框 var addBtn = document.getElementById('add-btn'); var addUser = ...

  8. node+ajax实战案例(4)

    4.用户登录实现 4.1.用户登录实现思路 1 用户输入登录信息,点击登录的时候把用户登录的这些信息收集起来,然后组装数据通过ajax方式发送到后台 2 后台接到用户输入的登录信息,把这些信息拿去和数 ...

  9. node+ajax实战案例(3)

    3.用户注册实现 3.1.注册用户功能的实现逻辑 1 用户在表单上输入注册信息 2 点击注册后,收集用户在表单上输入的注册信息并且发送给后台 3 后台接收用户发送过来的注册信息 4 后台需要处理数据并 ...

随机推荐

  1. 删除修改docker网络环境

    安装工具包 yum install bridge-utils -y 设置docker0 ip网段 ip link set docker0 down brctl delbr docker0 brctl ...

  2. 使用Xamarin开发移动应用示例——数独游戏(五)保存游戏进度

    项目代码可以从Github下载:https://github.com/zhenl/ZL.Shudu .代码随项目进度更新. 保存进度是移动应用的基本功能,在应用的使用过程中会有各种各样的可能导致使用中 ...

  3. 回顾 2021 中国 .NET 开发者峰会

    .NET Conf China 2021 是面向开发人员的社区峰会,基于 .NET Conf 2021,庆祝 .NET 6 的发布和回顾过去一年来 .NET 在中国的发展.峰会由来自北京.上海.苏州. ...

  4. ApacheCN Angular 译文集 20211114 更新

    Angular 专家级编程 零.前言 一.架构概述和在 Angular 中构建简单应用 二.将 AngularJS 应用迁移到 Angular 应用 三.使用 Angular CLI 生成具有最佳实践 ...

  5. ApacheCN 深度学习译文集 20201229 更新

    新增了七个教程: TensorFlow 和 Keras 应用开发入门 零.前言 一.神经网络和深度学习简介 二.模型架构 三.模型评估和优化 四.产品化 TensorFlow 图像深度学习实用指南 零 ...

  6. SpringBoot Log4j 安全漏洞分析及解决方案

    一.序言 SpringBoot作为Java基础框架大行其道,前不久爆发出Log4j安全漏洞,大众更多关心Log4j的危害是多么严重,然而鲜有关心SpringBoot这一底层框架的安全性问题,换而言之, ...

  7. 通过json动态创建控制器

    通过字符串来创建控制器 如果通过字符串来创建控制器 不可以直接通过类型来获取对应的类 因为Swift有命名空间,类前需要加上命名空间的名称 获取命名空间的名称 let executable = NSB ...

  8. Core Animation的使用步骤

  9. HOOK API(二) —— HOOK自己程序的 MessageBox

    转载来源:https://www.cnblogs.com/hookjc/ 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己 ...

  10. mac brew安装

    mac 安装homebrew出错 Failed to connect to raw.githubusercontent.com port 443: Connection refused error:原 ...