位置: 编程技术 - 正文

深入解析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)

  • 增值税专用发票几个点
  • 融资租赁的进项税可以抵扣吗
  • 海运报文是什么意思
  • 销售使用过的车辆
  • 对方公司已注销如何付款
  • 分支机构注销后往来账如何处理
  • 预计净残值的计算公式为
  • 高新企业申报指南
  • 工程结算扣罚款怎么开票
  • 收到项目投资款账务处理
  • 收到进项发票已认证,对方冲红重开,我方凭证什么做
  • 学生是纳税人吗为什么
  • 金蝶怎么填写凭证
  • 成本法长期股权投资账务处理
  • 工资扣款做什么科目
  • 广告公司收到的信息技术发票计入什么科目
  • 资产减值损失结转
  • 小规模增值税征收条件
  • 房地产形象海报
  • 没有发票的管理费用汇算清缴的时候怎么调出来
  • 外贸企业购进固定资产进项税能留存吗
  • 商业保险和交强险区别
  • 携税宝可以不买吗
  • 五险一金缴税基数
  • 本单位员工投稿怎么写
  • 生产型出口企业的概念
  • 无法查明原因现金盘盈计入什么科目
  • 折价购入对投资者而言,是为以后多得利息
  • 确认坏账需要纳税调整吗
  • 应收票据的核算账户有哪些
  • 在win7中,打开资源管理器的快捷键
  • 土地出让金可以代缴吗
  • 王者荣耀中廉颇是哪一个族的族长
  • win11电脑硬盘分区
  • macbookpro常见问题
  • PHP:Memcached::getDelayedByKey()的用法_Memcached类
  • PHP:stream_get_filters()的用法_Stream函数
  • 预付的房屋租赁费账务如何处理
  • 公司买发票的费用怎么做账
  • 最贵的游戏宣传片
  • 企业所得税减免20%按5%征收
  • 采用公允价值模式计量的投资性房地产处置
  • php-xml
  • 金税盘减免税款留抵
  • php输出表格css
  • python2 tkinter
  • 个体工商户注册资本是多少
  • 税局代开专票已扣款还需季度增值税申报吗
  • 分公司以总公司名义
  • c 语言 static
  • 收客户样品费怎么做分录
  • 一般纳税人差额纳税
  • 分公司税务登记流程与操作手册
  • 如何算基数
  • 应收应付会计分录大全
  • 公司车辆过户给个人需要多少费用
  • 未开票收入如何计提增值税
  • 残保金逾期申报了补报会有罚款和滞纳金吗?
  • 总资产利润率一般为多少
  • 过桥贷款有什么风险
  • 转账支票办理收款所要拿的单证
  • 企业年初借的
  • sql server错误和使用情况报告
  • sql server 自增列设置语句
  • centos7如何设置ssh免密登陆
  • macos 音量快捷键
  • w8系统怎么连接投影仪
  • win8怎么找开始程序
  • win10电脑补丁 kb5000802
  • perl 采集入库脚本分享
  • webuploader使用教程
  • css position: absolute、relative详解
  • 关于ie浏览器下面说法正确的是
  • jquery的循环
  • python的基础代码
  • python爬虫抓取数据的步骤
  • 电子税务局申领的发票怎么读入金税盘
  • 购置税缴费方式
  • 购置税周天上班吗
  • 福建省泉州市石狮市新服装城
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设