【web系列四】AJAX

导读:本篇文章讲解 【web系列四】AJAX,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

AJAX介绍

AJAX简介

应用场景

XML和JSON

AJAX的优缺点

优点

缺点

HTTP协议

请求报文

响应报文

原生AJAX

demo框架介绍

GET请求

请求时传参和设置请求头

POST请求并传送参数

网页端解析由服务端返回的js数据

IE浏览器缓存问题

 请求超时或网络异常的处理

取消请求

使用jQuery发送AJAX请求

jQuery简介

下载jQuery库

get请求

post请求

浅谈csrf及django的csrf_token机制

解决post的403forbidden问题

通用请求

使用Axios发送AJAX请求

Axios简介

Features

下载和引用

GET请求

POST请求

通用请求

使用fetch发送AJAX请求

参考资料


        在学习vue之前,默认大家已经掌握了html的初级知识,如果对这些还不是很清楚的话,建议先学习一下下面这些内容:

web系列之HTML5_Nicholson07的博客-CSDN博客

AJAX介绍

AJAX简介

  • AJAX全称Asynchronous JavaScript And XML,也就是异步的JS和XML。
  • 通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势就是无刷新获取数据
  • AJAX不是编程语言,而是一种将现有的标准组合在一起使用的新方式。

应用场景

  • 搜索框在输入的同时,会在下方显示一些相关内容的列表;
  • 注册页面在输入用户名后,网站提示用户名是否合规;
  • 淘宝的一些二级菜单,需要把鼠标放上去才会加载出来;
  • 微信朋友圈向下到底会加载新的数据;

XML和JSON

  • XML全称Extensible Markup Language,可扩展标记语言;
  • XML被设计用来存储和传输数据;
  • XML和HTML类似,不同之处在于HTML预定义标签,而XML中没有预定义标签;
  • JSON全称JavaScript Object Notation,对象简谱;
  • JSON是一种轻量级数据交换格式,实现的功能和XML类似,但是更加简洁方便;
  • XML曾时Ajax数据传输的承载体,现在已经被JSON替代;

AJAX的优缺点

优点

  • 可以无需刷新页面而与服务器端进行通信;
  • 允许你根据用户事件来更新部分页面内容;

缺点

  • 没有浏览历史,不能后退;
  • 存在跨域问题,即无法通过www.a.com向www.b.com发送请求;
  • 对搜索引擎优化SEO不友好,搜索爬虫找不到通过AJAX获得的内容。因为网页中通过AJAX获得的内容是动态获取的,所以在网页源代码中是找不到的;

HTTP协议

        HTTP全称Hyper Text Transfer Protocol,超文本传输协议,是一个基于TCP的请求-响应协议,规定了是网页和服务器通信的规则。

        可以使用google chrome浏览器查看HTTP协议,按f12-network查看

请求报文

【web系列四】AJAX

  1. 请求方法-GET/POST
  2. URL-/s?ie=utf-8……
  3. HTTP版本-HTTP/1.1
  1. HOST: www.baidu.com
  2. Cookie: PSTM=1647220155;
  3. Context-type: application/x-bmp
  4. User-Agent: Chrome/100.0.4896.30
  5. ……
  • 空行
  1. 由<html></html>包含起来的部分

响应报文

  1. HTTP版本-HTTP/1.1
  2. 状态码-200
  1. Context-type: text/html;charset=utf-8
  2. Content-length: 2048
  3. ……
  • 空行
  1. 由<html></html>包含起来的部分

原生AJAX

demo框架介绍

       这里使用的框架是使用django搭建的,具体可见下文,我会对他做一下修改,具体内容如下。(1条消息) Django搭建本地python工程的云端可视化界面_Nicholson的博客-CSDN博客

        项目结构如下:

---hello               //项目容器
  |---hello            //主目录,整个项目的配置和调度中心。
  |  |---__init__.py   //告诉python,该目录是一个包   。  
  |  |---asgi.py       //一个 ASGI 兼容的 Web 服务器的入口,以便运行你的项目。
  |  |---settings.py   //该 Django 项目的设置/配置。
  |  |---urls.py       //该 Django 项目的 URL 声明; 一份由 Django 驱动的网站"目录"
  |  |---wsgi.py       //一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目
  |---first_app            //新建的应用
  |  |---migrations    //用于数据库迁移,便于数据库管理
  |  |  |---__init__.py
  |  |---templates     //用于存放html文件,即网页结构
  |  |  |---first_app  //同名文件夹
  |  |     |---js_lib  //用于存放js库
  |  |        |---get_data.js  //js库
  |  |     |---console.html //console.html页面,主页面!
  |  |     |---hello.html //hello.html页面,打印hello world!
  |  |---__init__.py
  |  |---admin.py      //自带的后台管理
  |  |---apps.py       //创建对应app类的文件
  |  |---models.py     //mtv中的m,用于和数据库交互
  |  |---tests.py      //用于开发测试用例
  |  |---urls.py       //first_app的urls目录
  |  |---views.py      //mtv中的v,用于处理网页的后端业务逻辑
  |---db.sqlite3       //轻量级数据库,用于和models交互
  |---manage.py        //一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。

        first_app/views.py:

from django.shortcuts import render

# Create your views here.


def home(request):
    '''home'''
    return render(request, 'first_app/console.html')


def hello(request):
    '''hello'''
    return render(request, 'first_app/hello.html')

        first_app/urls.py:

from django.conf.urls import url
from . import views

app_name = 'first_app'

urlpatterns = [
    url(r'^console/$', views.home),
    url(r'^hello/$', views.hello),
]

        first_app/hello.htm:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HELLO</title>
</head>
<body>
    <hi>hello world!</h>
</body>
</html>

        first_app/hello.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    
</body>
</html>

GET请求

        需求:在console.html中点击按钮,将hello.html的内容显示在下方文本框内,不刷新页面(不改变当前网址)。

        框架中已经将其他功能实现,只需要修改console.html就行

 XHR.readyState == 状态(0,1,2,3,4),而且状态也是不可逆的:

  • 0:请求未初始化,还没有调用 open()。
  • 1:请求已经建立,但是还没有发送,还没有调用 send()。
  • 2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。
  • 3:请求在处理中;通常响应中已有部分数据可用了,没有全部完成。
  • 4:响应已完成;您可以获取并使用服务器的响应了。

HTTP状态码

HTTP 状态码 | 菜鸟教程 (runoob.com)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <button id="get_data">点击按钮获取数据</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementById('get_data');         <!--根据id获取button元素-->
        const result = document.getElementById('result');        <!--根据id获取result元素-->
		btn.onclick = function(){                                <!--绑定点击事件的回调函数-->
			const xhr = new XMLHttpRequest();                    <!--创建一个AJAX类-->
			xhr.open('GET', '/hello/');                          <!--初始化,设置请求方法和URL-->
			xhr.send();                                          <!--发送请求-->
			xhr.onreadystatechange = function(){                 <!--当xhr中readystate(0,1,2,3,4)状态改变时调用函数-->             
				if(xhr.readyState === 4){                        <!--判断当前状态,4表示响应完成-->
					if(xhr.status >= 200 && xhr.status < 300){   <!--根据状态码判断响应是否成功,[200,300)都是成功的-->
						console.log(xhr.status);                 <!--状态码-->
						console.log(xhr.statusText);             <!--状态字符串-->
						console.log(xhr.getAllRequestHeaders()); <!--响应头-->
						console.log(xhr.response);               <!--响应体-->
						result.innerHTML = xhr.response;         <!--设置result的文本-->
					}
				}
			}
		}
    </script>
</body>
</html>

        效果如下:

        点击按钮前:

【web系列四】AJAX

        点击按钮后:

【web系列四】AJAX

请求时传参和设置请求头

        在url后按以下格式添加

?参数名1=参数值1&参数名2=参数值2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <button id="get_data">点击按钮获取数据</button>
    <div id=""result></div>
    <script>
        const btn = document.getElementById('get_data');         <!--根据id获取button元素-->
        const result = document.getElementById('result');        <!--根据id获取result元素-->
		btn.onclick = function(){                                <!--绑定点击事件的回调函数-->
			const xhr = new XMLHttpRequest();                    <!--创建一个AJAX类-->
			xhr.open('GET', '/hello/?a=100&b=200&c=300');        <!--初始化,设置请求方法和URL-->
			xhr.setRequestHeader('Context-Type', 'application/x-www-form-url');        
															     <!--设置请求头-->
			xhr.send();                                          <!--发送请求-->
			xhr.onreadystatechange = function(){                 <!--当xhr中readystate(0,1,2,3,4)状态改变时调用函数-->             
				if(xhr.readyState === 4){                        <!--判断当前状态,4表示响应完成-->
					if(xhr.status >= 200 && xhr.status < 300){   <!--根据状态码判断响应是否成功,[200,300)都是成功的-->
						console.log(xhr.status);                 <!--状态码-->
						console.log(xhr.statusText);             <!--状态字符串-->
						console.log(xhr.getAllRequestHeaders()); <!--响应头-->
						console.log(xhr.response);               <!--响应体-->
						result.innerHTML = xhr.response;         <!--设置result的文本-->
					}
				}
			}
		}
    </script>
</body>
</html>

        效果如下,在request headers中可以看到context-type,在quert string parameters中可以看到参数。

【web系列四】AJAX

POST请求并传送参数

        需求:在console.html中将鼠标放在文本框中,发送请求,并在文本框中显示hello.html的内容,不刷新页面(不改变当前网址)。

        框架中已经将其他功能实现,只需要修改console.html就行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <div id="result"></div>
    <script>
        const result = document.getElementById('result');        <!--根据id获取result元素-->
		result.addEventListener("mouseover", function(){         <!--绑定点击事件的回调函数-->
			const xhr = new XMLHttpRequest();                    <!--创建一个AJAX类-->
			xhr.open('POST', '/hello/');                         <!--初始化,设置请求方法和URL,并传参-->
			xhr.send('xxxxxx');                                  <!--发送请求以及请求体,请求体格式与服务端解析方式一致就行-->
			xhr.onreadystatechange = function(){                 <!--当xhr中readystate(0,1,2,3,4)状态改变时调用函数-->             
				result.innerHTML = xhr.response;                 <!--设置result的文本-->
			}
		}
    </script>
</body>
</html>

         由于django框架在使用post请求时需要发送csrftoken,比较麻烦,具体操作会在后文(jQuery)中解释。

网页端解析由服务端返回的js数据

        我们对get_data.js做一些修改

function get_data() {
    var data = {'name', 'david'};
    return data;
}

        hello.html保持不变

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HOME</title>
</head>
<body>
    <h1>hello world!</h>
    <h2 id="res"></h2>
    <script src="/static/first_app/js_lib/get_data.js"></script>   <!--引入js库-->
	<script>
		myFun();
		function myFun() {                                         <!--调用js库函数并输出至h2-->
			const res = document.getElementById('res');
			res.innerHTML = get_data();
		}
	</script>
</body>
</html>

         显示的结果如下,可以发现没有正确显示出我们想要的结果。

【web系列四】AJAX

         我们把hello调用get_data后返回的内容打出来可以发现确实返回了我们想要的值,这是由于无法直接显示字典。

【web系列四】AJAX

         我们需要对get_data()做一些修改,将字典转化为JSON格式字符串。

function get_data() {
    var data = {'name', 'david'};
    let str = JSON.stringify(data);
    return str;
}

         这样就能显示了,那如果我只想显示key[‘name’]对应的value怎么办。【web系列四】AJAX

         也很简单,我们修改以下hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HOME</title>
</head>
<body>
    <h1>hello world!</h>
    <h2 id="res"></h2>
    <script src="/static/first_app/js_lib/get_data.js"></script>   <!--引入js库-->
	<script>
		myFun();
		function myFun() {                                         <!--调用js库函数并输出至h2-->
			const res = document.getElementById('res');
			let data = JSON.parse(get_data()); 
			res.innerHTML = data.name; 
		}
	</script>
</body>
</html>

         这样就可以了,通过JSON.stringify和JSON.parse可以很方便的处理大型的json文件。

【web系列四】AJAX

IE浏览器缓存问题

        当向服务器发送请求时,ie浏览器会把本次请求的内容和结果记录下来,当下次继续发送相同请求时,会直接从缓存读取结果,这就导致一些实时结果的显示会有问题。

        为解决这个问题,我们需要在发送请求的地方做一些修改,加上时间戳,以区别两次请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <button id="get_data">点击按钮获取数据</button>
    <div id="result"></div>
    <script>
        const btn = document.getElementById('get_data');        
        const result = document.getElementById('result');       
		btn.onclick = function(){                               
			const xhr = new XMLHttpRequest();                    
			xhr.open('GET', '/hello?t=' + Date.now());          <!--请求时追加时间戳-->
			xhr.send();                                          
			xhr.onreadystatechange = function(){                 
				if(xhr.readyState === 4){                        
					if(xhr.status >= 200 && xhr.status < 300){   
						result.innerHTML = xhr.response;         
					}
				}
			}
		}
    </script>
</body>
</html>

 请求超时或网络异常的处理

        我们首先在views.py的hello函数中增加一个延时

from django.shortcuts import render
import time

# Create your views here.


def home(request):
    '''home'''
    return render(request, 'first_app/console.html')


def hello(request):
    '''hello'''
    time.sleep(3)
    return render(request, 'first_app/hello.html')

        然后修改console.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <div id="result"></div>
    <script>
        const result = document.getElementById('result');        
		result.addEventListener("mouseover", function(){         
			const xhr = new XMLHttpRequest();                    
			xhr.open('POST', '/hello/');    
			xhr.timeout = 2000;
			xhr.ontimeout = function(){
				alert("请求超时,请稍后重试!")
			}
			xhr.onerror = function(){
				alert("网络异常,请检查你的网络连接!")
			}
			xhr.send('xxxxxx');                                  
			xhr.onreadystatechange = function(){                
				result.innerHTML = xhr.response;                 
			}
		}
    </script>
</body>
</html>

         首先测试超时,直接启动运行,结果如下:

【web系列四】AJAX

        然后我们来测试一下网络问题,我们先正常启动服务并用chrome浏览器打开页面,打开f12进入network,将online切换为offline,然后触发函数,结果如下:

【web系列四】AJAX

取消请求

        修改一下console.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AJAX</title>
</head>
<body>
    <button id="send">点击发送</button>
    <button id="cancel">取消发送</button>
    <script>
        const btn = document.querySelectorAll('button');      
		let xhr = null;
		
		btn[0].onclick = function(){         
			xhr = new XMLHttpRequest();                    
			xhr.open('POST', '/hello/');    
			xhr.send();   
		}
		
		btn[1].onclick = function(){ 
			xhr.abort();
		}
    </script>
</body>
</html>

         点击发送【web系列四】AJAX

         取消发送

【web系列四】AJAX

使用jQuery发送AJAX请求

jQuery简介

        jQuery 是一个 JavaScript 函数库,包含以下特性:

  • HTML 元素选取
  • HTML 元素操作
  • CSS 操作
  • HTML 事件函数
  • JavaScript 特效和动画
  • HTML DOM 遍历和修改
  • AJAX
  • Utilities

        其中ajax部分将极大地简化使用ajax的操作过程。这一章就讲如何使用jQuery实现ajax请求。

下载jQuery库

1、进入以下网站:

BootCDN – Bootstrap 中文网开源项目免费 CDN 加速服务

2、找到jquery

【web系列四】AJAX

3、点击3.6.0的jquery.min.js复制链接可以找到源码,复制下来保存

4、将库放到first_app/js_lib文件夹下

get请求

$.get(url, [data], [callback], [type])

        url: 请求的URL地址

        data: 请求携带的参数

        callback: 请求成功时的回调函数

        type: 设置返回内容的格式,json\xml\html\script\text

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>AJAX</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>
	
	<script src="/static/first_app/js_lib/jquery.min.js"></script>
	<script>
		const btn = document.getElementById("btn");
		const result = document.getElementById("result"); 
		
		btn.onclick = function() {
			$.get("/hello/", function(data) {
				console.log(data);
				result.innerHTML = data;
			});
		}
	</script>
</body>
</html>

【web系列四】AJAX

post请求

$.post(url, [data], [callback], [type])

        url: 请求的URL地址

        data: 请求携带的参数

        callback: 请求成功时的回调函数

        type: 设置返回内容的格式,json\xml\html\script\text

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>AJAX</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>
	
	<script src="/static/first_app/js_lib/jquery.min.js"></script>
	<script>
		const btn = document.getElementById("btn");
		const result = document.getElementById("result"); 
		
		btn.onclick = function() {
			$.post("/hello/", function(data) {
				console.log(data);
				result.innerHTML = data;
			});
		}
	</script>
</body>
</html>

        如果在django中这么使用post请求的话会报错

【web系列四】AJAX

浅谈csrf及django的csrf_token机制

        这是由于跨域访问导致的,由于跨域访问会产生一个漏洞,也就是CSRF。

        CSRF(Cross-Site Request Forgery,跨站点伪造请求)是一种网络攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在未授权的情况下执行在权限保护之下的操作,具有很大的危害性。具体来讲,可以这样理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,添加系统管理员,甚至于购买商品、虚拟货币转账等。

        这里面涉及到了cookie和token的一些知识,大家感兴趣的可以通过以下网址了解

(1条消息) Cookie_Micca_Xx的博客-CSDN博客_cookie

 (1条消息) CSRF的详细介绍与token的分析_ru_li的博客-CSDN博客_csrf token

(1条消息) Python-django中ajax使用POST时使用csrf_token_ppdouble的博客-CSDN博客

        而django为了解决这个问题,增加了一个csrf_token的库,我们在settings.py中也可以看到以下内容

MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
]

       因此在使用Post请求时,django要求我们加上csrf_token字段,用于防止CSRF漏洞。但这也导致使用POST方法时会比较麻烦,所以上文中的代码会报403的error。

        这边我简单解释一下,csrf_token的生成、保存和携带机制。

1、服务器必须是启用了’django.middleware.csrf.CsrfViewMiddleware’中间件才会有csrf_token,注意要添加<form>{% csrf_token %}</form>;

2、客户端(浏览器)访问某个网址,即访问服务器的某个url;

3、服务器收到访问请求后,就会生成csrf_token,并发送给客户端;

4、如果客户端设置了 允许记录cookie以及非无痕模式,就会将这个cookie保存下来,我们可以通过 chrome右上角设置->安全和隐私设置->Cookie及其他网站数据->查看所有Cookie和网站数据 中看到;

【web系列四】AJAX

5、这样的话,下一次使用该客户端访问该网址时,客户端就会把这个  csrf_token 包含在request 中发送给服务器。

        我们可以检验一下,在view.py中加入以下代码

from django.shortcuts import render


# Create your views here.


def home(request):
    '''首页'''
    print('home')
    print(request.COOKIES)               # 用于打印request中包含的COOKIES
    print('home')
    return render(request, 'first_app/console.html')


def hello(request):
    '''hello'''
    return render(request, 'first_app/hello.html')

       我们先将客户端中以保存的该网站的cookie清空,然后用客户端访问该url两次,可以看到服务器端打印了如下结果

System check identified no issues (0 silenced).
March 18, 2022 – 11:59:24
Django version 3.2.12, using settings ‘demo.settings’
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
home
{}
home
[18/Mar/2022 11:59:26] “GET /console/ HTTP/1.1” 200 1101
[18/Mar/2022 11:59:26] “GET /static/first_app/js_lib/set_token.js HTTP/1.1” 304 0
[18/Mar/2022 11:59:26] “GET /static/first_app/js_lib/axios.min.map HTTP/1.1” 404 1849
home
{‘csrftoken’: ‘IqpQ0KKq0DX2YVEzy8gZVh7N8GzwuOGUQYHQaAri82VItVwfJh1v7Kwah6f6gZFe’}
home
[18/Mar/2022 12:03:03] “GET /console/ HTTP/1.1” 200 1101
[18/Mar/2022 12:03:03] “GET /static/first_app/js_lib/axios.min.map HTTP/1.1” 404 1849
E:\Project\web\demo\first_app\views.py changed, reloading.
Watching for file changes with StatReloader
Performing system checks…

        可以发现第一次访问时的request中没有包含csrf_token,因为服务器还没有把生成的csrf_token发送给客户端,而第二次就包含了,说明客户端接收到了csrf_token并在请求中包含了这个信息。

6、服务器会对request中的请求做校验,通过的话才能正常运行,否则就会返回403forbidden;

7、服务器在response时也需要把csrf_token作为请求的参数一起发送给客户端;

8、客户端会校验csrf_token是否一致,确定是不是同一个用户在访问,如果不一致,也会拒绝访问。

解决post的403forbidden问题

         为了解决这问题,我们可以加上这段代码,为了便于使用,可以把他写成一个js库放在js_lib下:

function set_token() {
	function csrfSafeMethod(method) {
		// these HTTP methods do not require CSRF protection
		return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
	}

	function sameOrigin(url) {
		// test that a given url is a same-origin URL
		// url could be relative or scheme relative or absolute
		var host = document.location.host; // host + port
		var protocol = document.location.protocol;
		var sr_origin = '//' + host;
		var origin = protocol + sr_origin;
		// Allow absolute or scheme relative URLs to same origin
		return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
			(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
			// or any other URL that isn't scheme relative or absolute i.e relative.
			!(/^(\/\/|http:|https:).*/.test(url));
	}

	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;
	}

	csrftoken = getCookie('csrftoken');
	$.ajaxSetup({
		beforeSend: function(xhr, settings) {
			if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
				// Send the token to same-origin, relative URLs only.
				// Send the token only if the method warrants CSRF protection
				// Using the CSRFToken value acquired earlier
				xhr.setRequestHeader("X-CSRFToken", csrftoken);
			}
		}
	});
}

        然后在发送post请求前调用这个函数即可,如果还是不行的话可能是django没有向浏览器发送key为csrf_token的cookie,只要加入<form>{% csrf_token %}</form>就可以了。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>AJAX</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>
    <form>{% csrf_token %}</form>
	
	<script src="/static/first_app/js_lib/jquery.min.js"></script>
	<script src="/static/first_app/js_lib/set_token.js"></script>
	<script>
		const btn = document.getElementById("btn");
		const result = document.getElementById("btn"); 
		
        set_token();
		btn.onclick = function() {
			$.post("/hello/", function(data) {
				console.log(data);
				result.innerHTML = data;
			});
		}
	</script>
</body>
</html>

【web系列四】AJAX

通用请求

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>AJAX</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>
	
	<script src="/static/first_app/js_lib/jquery.min.js"></script>
	<script src="/static/first_app/js_lib/set_token.js"></script>
	<script>
		const btn = document.getElementById("btn");
		const result = document.getElementById("btn"); 
		
        set_token();
		btn.onclick = function() {
			$.ajax({
				url: "/hello/",               // 请求的url
				data: {					      // 请求携带的参数
					a: 100,
					b: 200
				},
				type: "POST",                 // 请求的类型 get\post\all
				dataType: "json",             // 设置返回内容的格式 json\xml\html\script\text
				timeout: 2000,                // 最长等待时间
				headers: {                    // 请求头
					c: 300,
					d: 400
				},
				success: function(data) {     // 请求成功时的回调函数
					console.log(data);
					result.innerHTML = data;
				},
				error: function() {           // 请求失败时的回调函数
					console.log('请求超时!');
				}
			});
		}
	</script>
</body>
</html>

【web系列四】AJAX

使用Axios发送AJAX请求

Axios简介

        Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

        详细介绍和使用方法可以看这个

使用说明 · Axios 中文说明 · 看云 (kancloud.cn)

Features

  • 从浏览器中创建XMLHttpRequests
  • 从 node.js 创建http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御XSRF

下载和引用

        Axios的下载和引用于jQuery类似,这里就不赘述了。

GET请求

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>HOME</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="get">get</button>
	<div id="result"></div>

	<script src="/static/first_app/js_lib/axios.min.js"></script>
	<script>
		const btn = document.querySelectorAll("button");
		const result = document.getElementById("result");

		btn[0].onclick = function() {
			axios.get("/hello/", {
				// 请求行,url参数
				params: {
					a: 100,
					b: 200
				},
				// 请求头
				headers: {
					c: 300,
					d: 400
				}
			}).then(value => {
				console.log(value);   // 返回promise格式
				result.innerHTML = value.data;
			}).catch(function (error) {
				console.log(error);
			});
		}
	</script>
</body>
</html>

【web系列四】AJAX

POST请求

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>HOME</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>

	<script src="/static/first_app/js_lib/set_token.js"></script>
	<script src="/static/first_app/js_lib/axios.min.js"></script>
	<script>
		const btn = document.querySelectorAll("button");
		const result = document.getElementById("result");

		btn[0].onclick = function() {
			axios.post("/hello/", {             // 请求体
					username: '111',
					password: '222'
				}, {
					// 请求行,url参数
					params: {
						a: 100,
						b: 200
					},
					// 请求头
					headers: {
						c: 300,
						d: 400,
  						'X-CSRFToken': '{{csrf_token}}'
					}
			}).then(value => {
				console.log(value);   // 返回promise格式
				result.innerHTML = value.data;
			}).catch(function (error) {
				console.log(error);
			});
		}
	</script>
</body>
</html>

通用请求

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>HOME</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>

	<script src="/static/first_app/js_lib/set_token.js"></script>
	<script src="/static/first_app/js_lib/axios.min.js"></script>
	<script>
		const btn = document.querySelectorAll("button");
		const result = document.getElementById("result");

		btn[0].onclick = function() {
			axios({
				// method
				method: "POST",
				// url
				url: "/hello/",
				// 请求行,url参数
				params: {
					a: 100,
					b: 200
				},
				// 请求头
				headers: {
					c: 300,
					d: 400,
  					'X-CSRFToken': '{{csrf_token}}'
				},
				 // 请求体
				data: {
					username: '111',
					password: '222'
				}
			}).then(response => {
				console.log(response);              // 返回promise格式
				console.log(response.status);       // 响应状态码
				console.log(response.statusText);   // 响应状态字符串
				console.log(response.headers);      // 响应头
				console.log(response.data);         // 响应体
				result.innerHTML = response.data;
			}).catch(function (error) {
				console.log(error);
			});
		}
	</script>
</body>
</html>

【web系列四】AJAX

使用fetch发送AJAX请求

WorkerOrGlobalScope.fetch() – Web API 接口参考 | MDN (mozilla.org)

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>HOME</title>
	<Style type="text/css">
		#result {
			width: 200px;
			height: 100px;
			border: solid 1px #90b;
		}
	</Style>
</head>
<body>
	<button id="btn">点击</button>
	<div id="result"></div>

	<script>
		const btn = document.querySelectorAll("button");
		const result = document.getElementById("result");

		btn[0].onclick = function() {
			fetch('/hello/?a=100&b=200', {
				// method
				method: "POST",
				// 请求头
				headers: {
					c: 300,
					d: 400,
  					'X-CSRFToken': '{{csrf_token}}'
				},
				body: 'username=111&password=222'
			}).then(response => {
				console.log(response);              // 返回promise格式
				console.log(response.status);       // 响应状态码
				console.log(response.statusText);   // 响应状态字符串
				console.log(response.headers);      // 响应头
          response.text().then(data=>{
          	console.log(data) 				//响应体
					result.innerHTML = data;
          }).catch(function (error) {
					console.log(error);
				});
	    	});
		}
	</script>
</body>
</html>

【web系列四】AJAX

参考资料

(1条消息) Cookie_Micca_Xx的博客-CSDN博客_cookie

(1条消息) CSRF的详细介绍与token的分析_ru_li的博客-CSDN博客_csrf token

(1条消息) Python-django中ajax使用POST时使用csrf_token_ppdouble的博客-CSDN博客

Django的CSRF_TOKEN携带方式 – 知乎 (zhihu.com)

使用说明 · Axios 中文说明 · 看云 (kancloud.cn)

WorkerOrGlobalScope.fetch() – Web API 接口参考 | MDN (mozilla.org)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100787.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!