使用AJAX和Django获取数据的方法实例


Posted in Python onOctober 25, 2020

前言

使用Django服务网页时,只要用户执行导致页面更改的操作,即使该更改仅影响页面的一小部分,它都会将完整的HTML模板传递给浏览器。 但是如果我们只想更新页面的一部分,则不必完全重新渲染页面-我们可以使用AJAX代替。

AJAX提供了一种将GET或POST请求发送到Django视图并接收任何返回的数据而无需刷新页面的方法。 现代JavaScript包含fetch API,该API为我们提供了一种纯JavaScript方式来发送AJAX请求。

让我们看一下如何通过获取发出GET和POST请求,以在视图和模板之间传递JSON数据。

GET请求

通过获取发出GET请求

通过向其提供视图的URL和适当的标头来进行带有获取的GET请求。 发出请求后,视图返回请求的数据,然后需要将响应转换为JSON,然后才能将其用于其他操作。

fetch(URL, {
  headers:{
   'Accept': 'application/json',
   'X-Requested-With': 'XMLHttpRequest', //Necessary to work with request.is_ajax()
  },
 })
 .then(response => {
  return response.json() //Convert response to JSON
 })
 .then(data => {
  //Perform actions with the response data from the view
 })

URL

提取将URL作为其第一个参数。根据Django项目的URLconf和视图的配置方式,URL可能包含关键字参数或查询字符串,我们希望在视图中使用该参数来选择请求的数据。

Headers

通过提取进行的AJAX请求将包含多个标头。我们希望数据以JSON形式从视图返回,因此我们将'Accept'标头设置为'application / json'。在视图中,我们可能要确保该请求是AJAX请求。通过将设置为“ XMLHttpRequest”的“ X-Requested-With”标头包括在内,该视图将能够检查请求是否为AJAX。

提取不会直接返回数据。相反,它将返回一个承诺,该承诺将被兑现并解决所请求的响应。为了从响应中获取数据,我们必须通过多次使用.then处理程序来使用链式承诺。第一个.then接收已解析的响应并将其转换为JSON。第二个.then允许我们访问第一个.then返回的数据,并允许我们使用它,但是我们想更新页面。

在视图中处理GET请求
我们需要一个视图来处理来自fetch调用的AJAX请求。这可以通过多种方式完成,但是最简单的方法之一就是使用基于函数的视图,该视图接受请求并返回带有请求数据的JsonResponse。

# views.py
from django.http import JsonResponse

def ajax_get_view(request): # May include more arguments depending on URL parameters
 # Get data from the database - Ex. Model.object.get(...)
 data = {
   'my_data':data_to_display
 }
 return JsonResponse(data)

如果通过包含附加参数的URL访问该视图,则这些附加参数也将与请求一起包含在功能参数列表中。 将根据那些URL参数或查询字符串(如果使用的话)从数据库中检索数据。 我们要发送回页面的数据必须在提供给JsonResponse的字典中。 调用之前,请确保从django.http导入JsonResponse。

该视图将返回JsonResponse,该序列将数据字典序列化并将其发送回我们的页面,在此页面中将通过链接的promise进行处理。 现在,我们可以使用JavaScript使用GET请求中的数据来更新页面的一部分。

POST请求

通过提取发出POST请求

带GET的POST请求比GET请求需要更多的参数。

fetch(URL, {
  method: 'POST',
  credentials: 'same-origin',
  headers:{
   'Accept': 'application/json',
   'X-Requested-With': 'XMLHttpRequest', //Necessary to work with request.is_ajax()
   'X-CSRFToken': csrftoken,
 },
  body: JSON.stringify({'post_data':'Data to post'}) //JavaScript object of data to POST
 })
 .then(response => {
  return response.json() //Convert response to JSON
 })
 .then(data => {
 //Perform actions with the response data from the view
 })

Method

提取默认为发出GET请求。我们必须通过添加方法“ POST”来明确地告诉它发出POST请求。

Credentials

我们需要指定如何在请求中发送凭据。凭证可能很棘手,特别是如果项目的前端和后端分别托管。如果AJAX请求是通过与后端其他位置相同的模板提供的,我们可以使用默认值“ same-origin”。这意味着,如果所请求的URL与提取调用来自同一站点,则将在请求中发送用户凭据。如果前端和后端不在某个位置,则需要使用不同的凭据设置,并且需要考虑跨域资源共享(CORS)。

Headers

“ Accept”和“ X-Requested-With”标头与GET请求的标头相同,但是现在必须包括一个附加的“ X-CSRFToken”标头。

向Django发出POST请求时,我们需要包含csrf令牌以防止跨站点请求伪造攻击。 Django文档提供了我们需要添加的确切JavaScript代码,以从csrftoken cookie中获取令牌。

function getCookie(name) {
  let cookieValue = null;
  if (document.cookie && document.cookie !== '') {
   const cookies = document.cookie.split(';');
   for (let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i].trim();
    // 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;
 }
 const csrftoken = getCookie('csrftoken');

现在我们有了csrftoken,我们将其添加到标头中作为“ X-CSRFToken”:csrftoken。

BODY

POST请求的目标是将数据发送到视图并更新数据库。 这意味着我们还需要在fetch调用中包含数据。 假设我们要发送JSON数据,我们添加主体:JSON.stringify(data)其中data是我们要发送的数据的JavaScript对象。 除了JSON数据(包括文件和来自表单的数据)外,其他数据也可以在正文中发送。 有关如何包含其他类型的数据的更多信息,请参见MDN文档。

我们从POST请求中获得的响应将像GET请求一样使用链式承诺进行处理。

在视图中处理POST请求

接受POST请求的视图将从请求中获取数据,对其执行一些操作,然后返回响应。

# views.py
from django.http import JsonResponse
import json

def ajax_post_view(request):
 data_from_post = json.load(request)['post_data'] #Get data from POST request
 #Do something with the data from the POST request
 #If sending data back to the view, create the data dictionary
 data = {
  'my_data':data_to_display,
 }
 return JsonResponse(data)

我们认为,我们需要从AJAX请求中提取数据才能使用它。数据以JSON格式发送,因此我们需要使用json.load(request)将其加载到视图中。这需要从Python标准库中导入json模块。结果是我们通过提取发送的数据的字典。现在,我们可以通过其键访问数据。

一旦获得了请求中的数据,我们就可以执行用户希望启动AJAX请求的操作。这可能是创建模型的新实例或更新现有实例。

与GET请求一样,可以使用JsonResponse和带有数据的字典将数据发送回页面。这可以是新的或更新的模型对象,也可以是成功消息。

确保请求是AJAX

在大多数情况下,都会发出AJAX请求,因为我们只希望更新页面的一部分,并且需要获取新数据来进行更新。在页面上下文之外,JsonResponse返回的数据本身很少使用。但是,如果我们没有正确设置视图,则可以在AJAX请求之外访问数据,并且不会像我们期望的那样将其呈现给用户。

为了防止这种情况的发生,我们可以使用request.is_ajax()方法在视图中添加检查以确保该请求是AJAX请求。

# views.py
from django.http import JsonResponse

def ajax_view(request):
 if request.is_ajax():
  data = {
    'my_data':data_to_display
  }
  return JsonResponse(data)

这使用“ X-Requested-With”标头来确定请求是否由AJAX发起。 如果尝试通过直接在浏览器中键入URL来访问此视图,则会收到错误消息。 可以向视图中添加其他逻辑(例如重定向),以防止用户尝试在没有AJAX请求的情况下访问视图时看到错误。

Django 3.1及更高版本

在即将发布的Django 3.1版本(2020年8月)中,request.is_ajax()将被弃用。 这意味着如果我们要检查AJAX请求,则必须自己重新创建功能。 幸运的是,Django开发人员确切地告诉我们我们需要做什么。 我们必须自己从request.is_ajax()方法重新创建逻辑,该逻辑只有1行代码:

request.headers.get('x-requested-with') == 'XMLHttpRequest'

现在,我们可以编辑视图以包括此检查:

def ajax_view(request):
 if request.headers.get('x-requested-with') == 'XMLHttpRequest':
 # Get requested data and create data dictionary
 return JsonResponse(data))

一些重要注意事项

尽管获取是发出AJAX请求的便捷方法,但并非所有浏览器(即所有版本的Internet Explorer)都支持提取。 如果需要支持IE,请查看jQuery或XMLHttpRequest来发出AJAX请求。

AJAX请求应仅限于Django项目的一小部分。 如果发现自己在多个模板中使用它们来获取大量数据,请考虑使用Django Rest Framework创建API。

概要

通过在Django项目中使用AJAX请求,我们可以更改页面的某些部分而无需重新加载整个页面。 提取API使添加此功能相当轻松,同时需要最少的JavaScript。 正确而谨慎地使用它,可以使我们的页面感觉更快,并为用户提供更多的交互体验。

原文:https://www.brennantymrak.com/articles/fetching-data-with-ajax-and-django.html

总结

到此这篇关于使用AJAX和Django获取数据的文章就介绍到这了,更多相关AJAX和Django获取数据内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python网络编程学习笔记(八):XML生成与解析(DOM、ElementTree)
Jun 09 Python
Django中处理出错页面的方法
Jul 15 Python
python使用mysql数据库示例代码
May 21 Python
NetworkX之Prim算法(实例讲解)
Dec 22 Python
浅谈Python黑帽子取代netcat
Feb 10 Python
pycharm运行和调试不显示结果的解决方法
Nov 30 Python
Python简易版停车管理系统
Aug 12 Python
python实现一个函数版的名片管理系统过程解析
Aug 27 Python
利用python控制Autocad:pyautocad方式
Jun 01 Python
Python优秀开源项目Rich源码解析的流程分析
Jul 06 Python
Python使用urlretrieve实现直接远程下载图片的示例代码
Aug 17 Python
python用海龟绘图写贪吃蛇游戏
Jun 18 Python
Python Tkinter实例——模拟掷骰子
Oct 24 #Python
Python+OpenCV图像处理——图像二值化的实现
Oct 24 #Python
python 下划线的不同用法
Oct 24 #Python
python 写一个性能测试工具(一)
Oct 24 #Python
Django admin组件的使用
Oct 24 #Python
Python数据可视化常用4大绘图库原理详解
Oct 23 #Python
Python+OpenCV图像处理——实现轮廓发现
Oct 23 #Python
You might like
php中目录,文件操作详谈
2007/03/19 PHP
细谈php中SQL注入攻击与XSS攻击
2012/06/10 PHP
php检测网页是否被百度收录的函数代码
2013/10/09 PHP
PHP与JavaScript针对Cookie的读写、交互操作方法详解
2017/08/07 PHP
因str_replace导致的注入问题总结
2019/08/08 PHP
JMenuTab简单使用说明
2008/03/13 Javascript
js字符编码函数区别分析
2011/12/28 Javascript
getJSON调用后台json数据时函数被调用两次的原因猜想
2013/09/29 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
js实现精美的银灰色竖排折叠菜单
2015/05/16 Javascript
微信小程序tabBar底部导航中文注解api详解
2017/08/16 Javascript
vue中实现在外部调用methods的方法(推荐)
2018/02/08 Javascript
js拖动滑块和点击水波纹效果实例代码
2018/10/16 Javascript
element-ui upload组件多文件上传的示例代码
2018/10/17 Javascript
vue 项目地址去掉 #的方法
2018/10/20 Javascript
jQuery实现ajax的嵌套请求案例分析
2019/02/16 jQuery
JS+CSS3实现的简易钟表效果示例
2019/04/13 Javascript
详解Vue.js 作用域、slot用法(单个slot、具名slot)
2019/10/15 Javascript
JS如何把字符串转换成json
2020/02/21 Javascript
使用Python实现下载网易云音乐的高清MV
2015/03/16 Python
ubuntu安装sublime3并配置python3环境的方法
2018/03/15 Python
Python寻找路径和查找文件路径的示例
2019/07/10 Python
django连接mysql数据库及建表操作实例详解
2019/12/10 Python
基于Keras中Conv1D和Conv2D的区别说明
2020/06/19 Python
html5使用canvas实现弹幕功能示例
2017/09/11 HTML / CSS
吃透移动端 1px的具体用法
2019/12/16 HTML / CSS
阿波罗盒子:Apollo Box
2017/08/14 全球购物
TripAdvisor瑞典:全球领先的旅游网站
2017/12/11 全球购物
Exoticca英国:以最优惠的价格提供豪华异国情调旅行
2018/10/18 全球购物
For Art’s Sake官网:手工制作的奢华眼镜
2018/12/15 全球购物
中国领先的汽车保养服务平台:途虎养车
2019/10/18 全球购物
高一生物教学反思
2014/01/17 职场文书
社会调查研究计划书
2014/05/01 职场文书
教师一帮一活动总结
2014/07/08 职场文书
教师业务学习材料
2014/12/16 职场文书