位置: 编程技术 - 正文

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

  • 当月不发工资会影响社保吗
  • 税务师厉害吗
  • 教育培训行业是干什么的
  • 差额增税可以抵扣吗
  • 固定资产处置损益科目编码
  • 向投资者支付的股息红利等权益性投资收益款项
  • .申报表税源编码怎么填
  • 销项负数发票原发票还有用吗?
  • 股票投资会计科目
  • 公司电话费用
  • 本月开的发票次月预缴如何做会计分录呢?
  • 按年征收的基金有哪些
  • 认购私募股权基金
  • 所得税汇算清缴分录怎么做
  • 企业所得税减半征收计算公式
  • 小规模纳税人开具1%增值税专用发票可以抵扣吗
  • 实收资本与账簿不一致
  • 怎么看是不是专用发票
  • 税务机关核定征收契税
  • 公司负担劳务费的个税如何做分录
  • 非全日制劳动用工扣税
  • 需要缴纳消费税的委托加工存货,由受托方
  • 发票未到计提房租费用会计分录
  • 预缴增值税抵扣销项税额账务处理
  • 工资薪金支出的扣除标准
  • 固定资产出租需要交什么税
  • 以前年度少计费用,调整分录
  • win10专业版激活密钥永久2023
  • 个税是负数直接工资加上吗
  • win7缓存设置方法
  • 暂估营业成本怎做分录
  • uview2.0封装http请求实战以及常见请求传参实录
  • 应税货物销售额是什么意思
  • 金融商品转让属于什么服务
  • 废旧物资经营单位增值税税率
  • random_state=123
  • 生产成本和库存商品的区别
  • php连接mysql数据库的几种方式及区别
  • 小微企业所得税税收优惠政策2023年
  • 黏菌算法总结
  • 什么是大语言模型(LLM)?
  • php解析原理
  • php页面刷新
  • 存放中央银行款项借方表示什么意思
  • 报名附件怎么上传
  • 车船税每年都要付吗
  • 外经证预缴税款之后剩下的税款交到哪呢
  • 折扣店商场
  • 做账计提是什么意思
  • 车票怎么抵扣增值税税率
  • 残保金计提和缴纳分录
  • mysql随机密码怎么看
  • 工资总额主要包括
  • 单位买理财产品怎么买
  • 企业所得税季度申报表营业收入怎么填写
  • 房租能不能一次性付清
  • 入股投资的钱能取出来吗
  • 主营业务成本如何设置明细
  • 增值税和所得税不一致的说明
  • 利息与资金占用费
  • 贷款买车成功后,给客户什么手续
  • 记账簿的目的在于为企业
  • zmweb.exe是什么进程
  • linux创建makefile
  • hipo.dll是什么
  • macbookpro登陆
  • 让xp系统自动修复软件
  • opencv与pil
  • 安卓 aac
  • cmd新建
  • node.js怎么创建js文件
  • python的iloc
  • android开发菜鸟教程
  • js赋值input
  • 江西省国家税务局李德平
  • 新加坡税务局电邮
  • 入职培训结束寄语
  • 土地整治税率是多少
  • 核算成本需要哪些数据来源
  • 内蒙古国税网上办税厅
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设