第二百六十一节,Tornado框架模板引擎本质
Tornado框架模板引擎本质
只需要了解一下即可
本篇就来详细的剖析模板处理的整个过程。
上图是返回给用户一个html文件的整个流程,较之前的Demo多了绿色流线的步骤,其实就是把【self.write('hello world')】变成了【self.render('main.html')】,对于所有的绿色流线只做了五件事:
- 使用内置的open函数读取Html文件中的内容
- 根据模板语言的标签分割Html文件的内容,例如:{{}} 或 {%%}
- 将分割后的部分数据块格式化成特殊的字符串(表达式)
- 通过python的内置函数执行字符串表达式,即:将html文件的内容和嵌套的数据整合
- 将数据返回给请求客户端
所以,如果要返回给客户端对于一个html文件来说,根据上述的5个阶段其内容的变化过程应该是这样:
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.render("main.html",**{'data':['11','22','33'],'title':'main'})
[main.html]
{{title}}
{% for item in data %}
{{item}}
{% end %}
{{title}}
{% for item in data %}
{{item}}
{% end %}
第1块:'' 第2块:'title' 第3块:'
\n\n' 第4块:'for item in data' 第4.1块:'\n' 第4.2块:'item' 第4.3块:'
\n' 第五块:''
'def _execute():
_buffer = []
_buffer.append(\\'\\n\\n\\n\\n \\n\\n\\n\\')
_tmp = title
if isinstance(_tmp, str): _buffer.append(_tmp)
elif isinstance(_tmp, unicode): _buffer.append(_tmp.encode(\\'utf-8\\'))
else: _buffer.append(str(_tmp))
_buffer.append(\\'
\\n\\')
for item in data:
_buffer.append(\\'\\n\\')
_tmp = item
if isinstance(_tmp, str): _buffer.append(_tmp)
elif isinstance(_tmp, unicode): _buffer.append(_tmp.encode(\\'utf-8\\'))
else: _buffer.append(str(_tmp))
_buffer.append(\\'
\\n\\')
_buffer.append(\\'\\n\\n\\')
return \\'\\'.join(_buffer)
'
RequestHandler的render方法
此段代码主要有三项任务:
- 获取Html文件内容并把数据(程序数据或框架自带数据)嵌套在内容中的指定标签中(本篇主题)
- 执行ui_modules,再次在html中插入内容,例:head,js文件、js内容、css文件、css内容和body
- 内部调用客户端socket,将处理请求后的数据返回给请求客户端
-
class RequestHandler(object): def render(self, template_name, **kwargs): #根据Html文件名称获取文件内容并把参数kwargs嵌入到内容的指定标签内 html = self.render_string(template_name, **kwargs) #执行ui_modules,再在html的内容中插入head,js文件、js内容、css文件、css内容和body信息。 js_embed = [] js_files = [] css_embed = [] css_files = [] html_heads = [] html_bodies = [] for module in getattr(self, "_active_modules", {}).itervalues(): embed_part = module.embedded_javascript() if embed_part: js_embed.append(_utf8(embed_part)) file_part = module.javascript_files() if file_part: if isinstance(file_part, basestring): js_files.append(file_part) else: js_files.extend(file_part) embed_part = module.embedded_css() if embed_part: css_embed.append(_utf8(embed_part)) file_part = module.css_files() if file_part: if isinstance(file_part, basestring): css_files.append(file_part) else: css_files.extend(file_part) head_part = module.html_head() if head_part: html_heads.append(_utf8(head_part)) body_part = module.html_body() if body_part: html_bodies.append(_utf8(body_part)) if js_files:#添加js文件 # Maintain order of JavaScript files given by modules paths = [] unique_paths = set() for path in js_files: if not path.startswith("/") and not path.startswith("http:"): path = self.static_url(path) if path not in unique_paths: paths.append(path) unique_paths.add(path) js = ''.join('<script src="' + escape.xhtml_escape(p) + '" type="text/javascript"></script>' for p in paths) sloc = html.rindex('