Tornado模板系统是将模板编译成Python代码。

        最基本的使用方式:

t = template.Template("<html>{{ myvalue }}</html>")
print t.generate(myvalue="XXX")

       Loader这个类加载根目录的模板,然后缓存编译好的模板。

       tornado模板系统不像其他模板系统,我们不会在表达式上设置任何限制。If 和for语句块都会被精确地转成Python代码,所以你可以像下面一个使用复杂的表达式。

{% for student in [p for p in people if p.student and p.age > 23] %}
<li>{{ escape(student.name) }}</li>
{% end %}

       

### Python code
def add(x, y):
return x + y
template.execute(add=add) ### The template
{{ add(1, 2) }}

        默认情况下,我们提供escape,url_escape,json_encode以及squeeze函数给所有的模板。

       一般情况下,应用不会创建Template或者Loader实例,而是使用tornado.web.RquestHandler的 render以及render_string 方法,这两个方法根据Application setting的template_path选项的值自动加载模板。

       以 _tt_ 开始的变量名称是被模板系统保留的,应用程序不能使用。

 

9.1 语法

          模板表达式使用双方括号{{…}}包围。里面内容可以是任何python的表达式,里面的内容根据当前的autoescape设置而决定是否进行转义。其他模板指令使用{%...%}.如果你需要将{{ 或者{%原样输出,你可以使用{{!和 {%!进行转义。

         注释部分使用{#...#},从而注释部分会被忽略,而不会输出。

         {% apply *function* %} ….{% end %}

         在apply 和end之间对模板的所有输出应用函数。比如:

         {% apply linkify %}{{name}} said: {{message}}{% end %}

         {% block *name* %}...{% end %} 表示一个命名的、可以被替换的块看,这个语法是针对模板继承的使用 {% extends %}。在父模板中的块会被子模板同名的块中内容替换。比如:

<!-- base.html -->

<title>{% block title %}Default title{% end %}</title>

<!-- mypage.html -->

{% extends "base.html" %}

{% block title %}My page title{% end %}

         {% comment ... %} 表示注释,是不会被输出的。注意这里没有{% end %}标签。

        {% extends *filename* %} 继承模板。

        {% for *var* in *expr* %}...{% end %} 跟Python for循环语句相同。{% break %}和{% continue %} 可以在循环内使用。

       {% from *x* import *y* %}  跟Python import语句一样

        {% if *condition* %}...{% elif *condition* %}...{% else %}...{% end %} 条件语句

         {% import *module* %} 跟Python import语句一样

         {% include *filename* %}引用其他模板文件。这个引用的文件可以看到所有的本地变量,因为他们都被直接复制。相反地,{% module Template(filename, **kwargs) %} 被用来包含其他在隔离命名空间的模板。

         {% set *x* = *y* %}设置值

        {% try %}...{% except %}...{% else %}...{% finally %}...{% end %}跟Python的异常处理一样。

         {% while *condition* %}... {% end %}跟Python的while语句一样。

 

9.2 关联的类

tornado.template.Template

    源代码位于site-packages > tornado > template.py,这个类表示已编译好的模板。

  • 构造函数:
def __init__(self, template_string, name="<string>", loader=None,
compress_whitespace=None, autoescape=_UNSET):

   参数:

       template_string :模板字符串

       name :模板名称

       loader: 模板加载器

       compress_whitespace :是否压缩空白字符

       autoescape :是否自动转义

   实现代码:

self.name = name
if compress_whitespace is None:
compress_whitespace = name.endswith(".html") or \
name.endswith(".js")
if autoescape is not _UNSET:
self.autoescape = autoescape
elif loader:
self.autoescape = loader.autoescape
else:
self.autoescape = _DEFAULT_AUTOESCAPE
self.namespace = loader.namespace if loader else {}
reader = _TemplateReader(name, escape.native_str(template_string))
self.file = _File(self, _parse(reader, self))
self.code = self._generate_python(loader, compress_whitespace)
self.loader = loader
try:
# Under python2.5, the fake filename used here must match
# the module name used in __name__ below.
# The dont_inherit flag prevents template.py's future imports
# from being applied to the generated code.
self.compiled = compile(
escape.to_unicode(self.code),
"%s.generated.py" % self.name.replace('.', '_'),
"exec", dont_inherit=True)
except Exception:
formatted_code = _format_code(self.code).rstrip()
app_log.error("%s code:\n%s", self.name, formatted_code)
raise

   处理过程:

      (1) compress_whitespace的值进行设置。如果是None,如果模板是html或者js文件,则compress_whitespace 为True.

      (2) 对 autoescape 的设置。autoescape是一个函数,默认为“xhtml_escape”函数

      (3) 对namespace 命名空间的设置。如果设置了loader,则为loader的namespace.

   (4) 设置内部类_TemplateReader类型的reader.

   (5) 设置file、code属性。

   (6) 最后调用compile方法,进行模板编译。

  • generate方法

def generate(self, **kwargs):
"""Generate this template with the given arguments."""
namespace = {
"escape": escape.xhtml_escape,
"xhtml_escape": escape.xhtml_escape,
"url_escape": escape.url_escape,
"json_encode": escape.json_encode,
"squeeze": escape.squeeze,
"linkify": escape.linkify,
"datetime": datetime,
"_tt_utf8": escape.utf8, # for internal use
"_tt_string_types": (unicode_type, bytes),
# __name__ and __loader__ allow the traceback mechanism to find
# the generated source code.
"__name__": self.name.replace('.', '_'),
"__loader__": ObjectDict(get_source=lambda name: self.code),
}
namespace.update(self.namespace)
namespace.update(kwargs)
exec_in(self.compiled, namespace)
execute = namespace["_tt_execute"]
# Clear the traceback module's cache of source data now that
# we've generated a new template (mainly for this module's
# unittests, where different tests reuse the same name).
linecache.clearcache()
return execute()

       作用:根据给定的参数,生成模板,最后是生成模板的结果,是一个字符串。

       参数:

             kwargs:是一个namespace的字典,都是一个方法的映射。

tornado.template.BaseLoader

         模板加载器的基类。

         当你使用像 “{% extends %}”、{% include% }这些模板语法时,你必须使用模板加载器。当模板第一次加载完毕后,加载器会缓存这些模板。

  • 构造函数:
def __init__(self, autoescape=_DEFAULT_AUTOESCAPE, namespace=None):
"""``autoescape`` must be either None or a string naming a function
in the template namespace, such as "xhtml_escape".
"""
self.autoescape = autoescape
self.namespace = namespace or {}
self.templates = {}
# self.lock protects self.templates. It's a reentrant lock
# because templates may load other templates via `include` or
# `extends`. Note that thanks to the GIL this code would be safe
# even without the lock, but could lead to wasted work as multiple
# threads tried to compile the same template simultaneously.
self.lock = threading.RLock()

       参数:

             autoescape: 是否自动转义。要么是None值,要么是在模板namespace中的函数名,比如是”xhtml_escape”

             namespace:模板中使用的方法的映射字典。

      处理过程:

           主要是对相关属性的初始化。注意,最后一句self.lock= threading.RLock() 是为了考虑多线程并发的存在,加上线程锁。

 

  • reset 方法

              重设加载器的模板,清除缓存

  • resolve_path方法

              将模板的相对路径转换成绝对路径,由子类继承

  • load方法

            加载模板。调用了resolve_path以及_create_template方法,这两个方法都有子类实现。

def load(self, name, parent_path=None):
"""Loads a template."""
name = self.resolve_path(name, parent_path=parent_path)
with self.lock:
if name not in self.templates:
self.templates[name] = self._create_template(name)
return self.templates[name]

 

tornado.template.Loader

        模板加载器,继承BaseLoader,从单一根路径加载。

  • 构造函数:

 

def __init__(self, root_directory, **kwargs):
super(Loader, self).__init__(**kwargs)
self.root = os.path.abspath(root_directory)

       参数:

              root_directory:根路径

              kwargs:参数字典

       处理过程:

              调用父类初始化过程,同时设置root属性,为绝对路径

  • resolve_path方法

              实现BaseLoader父类中的方法。

def resolve_path(self, name, parent_path=None):
if parent_path and not parent_path.startswith("<") and \
not parent_path.startswith("/") and \
not name.startswith("/"):
current_path = os.path.join(self.root, parent_path)
file_dir = os.path.dirname(os.path.abspath(current_path))
relative_path = os.path.abspath(os.path.join(file_dir, name))
if relative_path.startswith(self.root):
name = relative_path[len(self.root) + 1:]
return name

         就是讲各种路径合并,然后得到模板的绝对路径,最后去除根路径,返回剩余的路径。

  • _create_template方法
def _create_template(self, name):
path = os.path.join(self.root, name)
with open(path, "rb") as f:
template = Template(f.read(), name=name, loader=self)
return template

        根据模板的绝对路径,打开模板文件,然后实例化Template对象并返回。实例化的Template对象会缓存在加载器中。

tornado 学习笔记9 Tornado web 框架---模板(template)功能分析的更多相关文章

  1. tornado 学习笔记2 Python web主流框架

    2.1 Django 官方网址:https://www.djangoproject.com/ 简介:Django is a high-level Python Web framework that e ...

  2. Tornado学习笔记12 tornado.httpserver-.非阻塞的Http服务器

    是一个非阻塞的,单线程的Http 服务器. 一般地,应用程序很少与HttpServer类直接交互,除非在进程开始时启动服务时(甚至在使用tornado.web.Applicaiton.listen时也 ...

  3. python 学习笔记十五 web框架

    python Web程序 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. Python的WEB框架分为两类: 自己写socket,自 ...

  4. tornado学习笔记19 Tornado框架分析

    19.1 Http服务器请求处理流程图 (1) 调用HTTPServer的bind方法,绑定Socket的监听端口号: (2) 调用HTTPServer的listen方法,初始化一个listen so ...

  5. Tornado学习笔记(一) helloword/多进程/启动参数

    前言 当你觉得你过得很舒服的时候,你肯定没有在进步.所以我想学习新的东西,然后选择了Tornado.因为我觉得Tornado更匹配目前的我的综合素质. Tornado学习笔记系列主要参考<int ...

  6. tornado 学习笔记1 引言

    从事软件开发这行业也快5年啦,其实从事的工作也不完全是软件开发,软件开发只是我工作中的一部分.其中包括课题研究.信息化方案设计.软件开发.信息系统监理.项目管理等工作,比较杂乱.开发的软件比较多,但是 ...

  7. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  8. Spring实战第八章学习笔记————使用Spring Web Flow

    Spring实战第八章学习笔记----使用Spring Web Flow Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序. 其实我们可以使用任何WEB框架写流程化的应 ...

  9. Spring实战第五章学习笔记————构建Spring Web应用程序

    Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...

随机推荐

  1. Java环境变量的简记

    1,安装版的jre或jdk.安装后如果不做开发用,则只是做Java运行时环境,则不需要手动配置任何Java环境变量. 2,绿色解压版(拷贝版)jdk或jre.运行和开发都需要配置环境变量. 运行Jav ...

  2. ibatis order by 防止sql注入

    (1) 排序控制 select TABLE_NAME, TABLESPACE_NAME from user_tables order by TABLE_NAME $ordertype$ Where t ...

  3. Hdu4311 || 4312Meeting point-1/-2 n个点中任意选一个点使得其余点到该点曼哈顿距离之和最小

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  4. Asp.Net WebApi开发注意

    1.Api的版本控制 2.Api的异常处理 设置全局异常处理 3.Api的权限控制 4.Api的请求处理 get:查询 post:创建 put:修改 delete:删除 5.Api的文档说明

  5. HTML5之文件API

    问题很简单,做个上传文件的页面. <!-- multiple代表可上传多个文件 --> <input type="file" id="file" ...

  6. NoSql basic knowledge

    The big picture to keep in mind first is: There are lots of articles and resources out there: http:/ ...

  7. 深入理解Spark(一):Spark核心概念RDD

    RDD全称叫做弹性分布式数据集(Resilient Distributed Datasets),它是一种分布式的内存抽象,表示一个只读的记录分区的集合,它只能通过其他RDD转换而创建,为此,RDD支持 ...

  8. c#中abstract与virtua、overridel的用法

    1.abstract 抽象方法 ,virtual 虚方法 ,override 重载函数 父类A.m() 子类B.m()   abstract的方法父类可以不实现,让子类去重写(重写=overwrite ...

  9. Unity之CharacterController 碰撞问题总结

    CharacterController 不会受到scene的重力影响,自带物理碰撞检测,在脱离导航网格的应用场景下(比如飞行),是很有优势的Unity原生工具组件.如果在复杂的应用场景里,会有多种CC ...

  10. cocos2dx 实现flappybird

    前两天在博客园看到网友实现的一个网页版的flappy bird,挂在360游戏平台,玩了一会儿得分超低,就很想自己做一个.刚好这两天炫舞的活都清了,就弄一下玩玩. 效果图 布局类GameScene.h ...