位置: 编程技术 - 正文

深入解析Python的Tornado框架中内置的模板引擎(python 解析算法)

编辑:rootadmin

推荐整理分享深入解析Python的Tornado框架中内置的模板引擎(python 解析算法),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:python求解析解,python解析函数,python解析函数,深入理解python,python求解析解,深入理解python,python解析函数,深入理解python,内容如对您有帮助,希望把文章链接给更多的朋友!

template中的_parse方法是模板文法的解析器,而这个文件中一坨一坨的各种node以及block,就是解析结果的承载者,也就是说在经过parse处理过后,我们输入的tornado的html模板就变成了各种block的集合。这些block和node的祖宗就是这个“抽象”类, _Node,它定义了三个方法定义,其中generate方法是必须由子类提供实现的(所以我叫它“抽象”类)。 理论上来说,当一个类成为祖宗类时,必定意味着这个类包含了一些在子类中通用的行为,那么,从_Node暴露出来的方法来看,即所有的子类理论上都会有如下特征:1. 可作为容器 (each_child, find_named_blocks)2. generate当然了,理想总是丰满的,现实也总有那么点儿不对劲,对于某些子孙,它们的特征看上去不是那么靠谱,比如_Text。 _Text这个类只用到了generate这个方法,用于将文字(Html, JS)经过trim后添加到输入流中,如果调用它的each_child or find_named_blocks,当然你能这么做,但是没有什么意义。 前面反复说到_Parse方法,它返回的结果是一个_ChunkList的实例,而_ChunkList继承与_Node。这是一个体现了_Node容器特点的类,重写了generate方法和each_child方法,而基本上就是依次调用容器内所有元素的相关方法而已。 _Nodes众多子子孙孙中比较奇葩的是_ExtendsBlock这个类,丫什么事情都没做(That is true),看上去像是另外一个“抽象类”,但是居然会被_Parse初始化,用于处理Extends这个token(tornado术语)。我就纳闷了,一旦这货被generate,难道不会抛一个异常出来木? 真正有意思的是另外几个方法,它们有共通的模式,用_ApplyBlock来举例 在_ApplyBlock中,有趣的是generate方法

简单来说,这个函数做了两件事情:定义了一个python文件全局函数叫做applyXXX():,其中的XXX是一个整形的,自增的值,返回值是一个utf8字符串。执行这个applyXXX函数,将此函数的输出再作为self.method这个函数的输入。所以,如果一个类似于这样的模板

会得到一个类似于如下的输出:

tornado的template机制,本质上讲,就是允许开发者已HTML + template marker的方式来编写视图模板,但是在背后,tornado会把这些视图模板通过template的处理,变成可编译的python代码。 拿autumn-sea上面的代码作为例子,比较容易理解: View Template

处理后

实例剖析tornado的模板基本都在template.py这个文件中,短短多行代码就实现了基本可用的模板,让我们慢慢揭开她的面纱。首先我们看看tornado是如何编译模板的,下面是个简单的模板

tornado最后编译代码如下:

是的,你没看错,tornado编译就是将之翻译成一个个代码块,最后通exec传递我们给的参数命名空间执行_tt_execute函数。在我们上面的模板中包含了4种预定义的NODE节点,_ControlBlock,_Expression,_TEXT,每种Node节点都有自己的生成方式。比如说_Expression表达式节点,也就是我们模板中的{{name}},当_parse解析时发现'{'后面还是'{'就认为是表达式节点,

最后生成时会调用节点的generate方法,self.expression就是上面的name,所以当exec的时候就会把name的值append到内部的列表中。像if,for等都是控制节点,他们的定义如下:

控制节点的generate方法有点意义,因为if,for等是下一行是需要缩进的,所以调用了with writer.indent继续缩进控制,可以看下_CodeWriter的indent方法。节点中比较有意思的是_ExtendsBlock,这是实现目标基础的节点,

我们发现并没有定义generate方法,那当生成继承节点时不是会报错吗?让我们看一段事例

当前目录下base.html如下:

我们可以看看解析后的节点,

深入解析Python的Tornado框架中内置的模板引擎(python 解析算法)

由于我们继承了base.html,所以我们的应该以base.html的模板生成,并使用新定义的block代替base.html中的block,这是很正常的思路,tornado也的确是这么干的,只不过处理的并不是在_ExtendsBlock。而实在Template的_generate_python中

_generate_python中调用_get_ancestors获取当前模板的父模板,我们看到如果当前模板的_FILE节点中有_ExtendsBlock就代表有父模板并通过loader.load加载父模板,此时父模板已经是解析过的_FILE节点了。所以,在上面的模板中,ancestors是[当前模板_FILE节点,父模板_FILE节点],ancestors.reverse()后其实ancestors[0]就是父模板,我们看到最后是通过ancestors[0].generate(writer)来生成代码的。那当前模板是如何替换父模板的block内容呢?看上图,block login_name通过解析为_NamedBlock,在_generate_python中通过调用ancestor.find_named_blocks来替换父模板的_NamedBlock的。

其它节点find_named_blocks都没有做什么事,_NamedBlock通过named_blocks[self.name] = self替换为当前模板的_NamedBlock,因为ancestors父模板在前,当前模板在后,所以最后使用的是当前模板的_NamedBlock。生成代码后generate将在给定的命名空间中exec代码

所以在模板中可以使用datetime等,都是通过在这里注入到模板中的,当然还有其它的是通过web.py 中get_template_namespace注入的

我们再来看看tornado的模板是如何对UI模块的支持的。

在使用module时将会生成_Module节点

我们看到其实_Module节点是继承自_Expression节点,所以最后执行的是_tt_modules.Entry(entry)_tt_modules定义在web.py的RequestHandler中

并通过上文的get_template_namespace中注入到模板中。

所以当执行_tt_modules.Entry(entry)时先访问_UIModuleNamespace的__getattr__,后访问__getitem__,最后调用handler._ui_module(key, self.ui_modules[key]),

_tt_modules.Entry(entry)中entry将会传给_ui_module内部的render,也就是args=entryself._active_modules[name] = module(self)此时就是实例化后的UIModule,调用render获取渲染后的内容

当然如果你觉得这么做费事,也可以使用tornado自带的TemplateModule,它继承自UIModule,你可以这么用

在module_entry.html中可以通过set_resources引用需要的静态文件

这里需要注意的是:只能在Template引用的html文件中使用set_resources函数,因为set_resources是TemplateModule.render的内部函数

浅析Python的web.py框架中url的设定方法 网页中的数据在传递的时候有GET和POST两种方式,GET是以网址的形式传参数,在web.py中有着很好的匹配,如果我们配置以下的urlsurls=('/','index','/weixin/(.*)',

Swift 3.0在集合类数据结构上的一些新变化总结 一、Array数组的更改array数组中修改的API示例如下://创建大量相同元素的数组//创建有个String类型元素的数组,并且每个元素都为字符串"Hello"//swift2.2//

Python中内置的日志模块logging用法详解 logging模块简介Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记

标签: python 解析算法

本文链接地址:https://www.jiuchutong.com/biancheng/386971.html 转载请保留说明!

上一篇:使用Python的Tornado框架实现一个Web端图书展示页面(python tonny)

下一篇:浅析Python的web.py框架中url的设定方法(python,web)

  • 不能抵扣的进项抵扣了
  • 实收资本增加印花税怎么算
  • 出口免税收入的计税依据
  • 资源税的税目有几个
  • 增值税抵扣不够怎么解决
  • 董事长费用可以在公司报销吗
  • .申报表税源编码怎么填
  • 资产评估收益法的前提条件
  • 赠品折扣计算法
  • 购进免税农产品怎么计算进项税额
  • 资本公积转增股本什么意思
  • 成本核算会计科目包括
  • 分支机构第要交企业所得税吗?
  • 发票进项和销项对不上后果
  • 2021年新疆果业灰枣销售情况
  • 生物性资产是什么
  • 资金流量表国外部门如何记录
  • 公司房租押金收不回来账务处理
  • 同城提入业务包括
  • 本年固定资产投资额与不良贷款的关系
  • 应收票据盘点表是出纳填吗
  • 投资理财产品的优势和劣势
  • win10工作站版和企业版的区别
  • .exe文件怎么打不开
  • 多缴的企业所得税如何处理
  • 联想昭阳k41笔记本
  • 财务软件税率
  • 成本法转为权益法属于会计政策变更吗
  • nuxt怎么用
  • 公司赞助是什么意思
  • 提高支票处理效率的有效方法是
  • 增值税实际税负计算公式
  • php中常见的错误类型有
  • 深度学习第一步——Pytorch-Gpu环境配置:Win11/Win10+Cuda10.2+cuDNN8.5.0+Pytorch1.8.0(步步巨细,少走十年弯路)
  • web前端入门教程
  • vue通过url访问单个页面
  • vue内置指令实验总结
  • php取字符串
  • 帝国cms怎么安装不了
  • vue组件怎么使用
  • python用内置函数来打开文件
  • 中央空调的维护和保养
  • 收到快递赔款分录怎么做
  • 劳务费发票 个税
  • 医疗报销发票是什么样的
  • php如何判断是移动还是pc
  • python local
  • 工程施工科目借方尾差怎么调整
  • 现金流量表上期金额
  • 营业利润是税前利润吗
  • 公司注销持股1%的股东需要他签字吗
  • 深入理解计算机系统
  • 什么叫做有限循环小数
  • 同级财政和本级财政
  • 增值税纳税申报表怎么填
  • 管理费用包括哪些税
  • 税局代开的法律顾问费能否抵扣?
  • 营改增后建筑行业增值税税率
  • 社保个人部分如何继承
  • 未取得合法支付凭据和与本单位无关的收入
  • myeclipse中连接数据库的地方在哪
  • 网关dns配置异常是什么意思
  • windows允许多用户登录
  • win8屏幕键盘快捷键
  • win10桌面右边没有了怎么弄出来了?
  • win10的命令行在哪里
  • 如何dj
  • linux getuid
  • win7怎么修改开机启动
  • kb3150220安装失败
  • option标签的作用
  • jquery 点击按钮
  • jquery 插件写法
  • shell脚本编程实例
  • bash 删除文件夹
  • 关于全局变量和局部变量说法不正确的是
  • javascript 基础篇3 类,回调函数,内置对象,事件处理
  • 贵州铜仁苗族自治区
  • 深圳税务局怎么添加办税员
  • 超期未申报还能申报吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设