- 3 Extending Templates
- 1 blocks and substitutions
- 2 autoescaping
- 3 UI modules
- basic module usage
- modules in depth
- embedding javascript and css
3 Extending Templates
1 blocks and substitutions
模板可以继承于基类模板,这样可以重复使用很多模块减少代码量
如在index.html中继承main.html,在index.html的开头加上:{% extends "main.html" %}
block
:划定一些扩展模板的时候可能需要修改的代码块,在子类中直接通过block name就可以重写这一块
如在main.html中:
<header> {% block header %}{% end %} </header>
在子模板index.html中:
{% extend main.html %} {% block header %} <h1>hello world</h1> {% end %}
2 autoescaping
escape的意思就是转义,将一些原本是script中的符号换一些编码表示,如<
变为<
, 在浏览器显示的时候才显示出原来的字符,这样是为了安全起见,比如别人在文章评论中可能上传一些<script>alert(‘dangerous...‘)</script>的文本来进行攻击,会导致我们打开网页弹出警告框.
默认情况下tornado会自动escape模板中的内容,但有些时候自动转义会导致一些变量无法正常使用,如在模板中有
{% set mailLink = "<a href=\"mailto:[email protected]\">Contact Us</a>" %} {{ mailLink }}
本来是设置一个邮件地址作为变量,但是由于转义变成类似<a href="mailto:[email protected]
为了处理这种情况,我们可以自己设置关闭自动转义,加上{% autoescape None %}
关闭自动转义虽然可以处理但是又少了保护机制,所以还有一种解决方法是加上raw block: {% raw mailLink %}
3 UI modules
Modules是继承于tornado的UIModule类的一个python类,当遇到{% module Foo(...) %}
这种标签,会调用模块的render
函数,返回一个string替换module标签。
UI模块可以嵌入js,css文件
basic module usage
要在模板中使用module,首先需要在应用中声明,ui_modules
参数接受一个dict将模块名字映射到渲染它们的类
hello.py
import os.path import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web from tornado.options import define, options define("port", default=8000, help="run on the given port", type=int) class HelloHandler(tornado.web.RequestHandler): def get(self): self.render(‘hello.html‘) class HelloModule(tornado.web.UIModule): def render(self): return ‘<h1>hello world!</h1>‘ if __name__ == ‘__main__‘: tornado.options.parse_command_line() app = tornado.web.Application( handlers=[(r‘/‘, HelloHandler)], template_path = os.path.join(os.path.dirname(__file__), ‘templates‘), ui_modules={‘Hello‘: HelloModule} ) server = tornado.httpserver.HTTPServer(app) server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
hello.html
<html> <head><title>UI module example</title></head> <body> {% module Hello() %} </body </html>
例子中ui_modules={‘Hello‘: HelloModule}定义Hello模块是用HelloModule类来进行处理,所以html中间中的模块标签会被替换为HelloModule类中返回的内容
modules in depth
在看Burt‘s books的例子,现在建立一个页面用来推荐一些书,每一本书都是用同样的模板进行渲染,创建modules/book.html文件:
<div class="book"> <h3 class="book_title">{{ book["title"] }}</h3> {% if book["subtitle"] != "" %} <h4 class="book_subtitle">{{ book["subtitle"] }}</h4> {% end %} <img src="{{ book["image"] }}" class="book_image"/> <div class="book_details"> <div class="book_date_released">released: {{ book["date_released"] }}</div> <div class="book_date_added">added: {{ locale.format_date(book["date_added"], relative=False) }}</div> <h5>description:</h5> <div class="book_body">{% raw book["description"] %}</div> </div> </div>
这个模板接受名为book的字典,然后定义展示一本书的形式,函数locale.format_date()
是tornado中提供时间功能的函数,参数为时间,relative=False说明是绝对时间
在recommended.html中,对每一本书调用Book模块来进行渲染:
{% extends "main.html" %} {% block body %} <h2>recommended reading</h2> {% for book in books %} {% module Book(book) %} {% end %} {% end %}
在py文件中,建立RecommendedHandler类和BookModule类
class RecommendedHandler(tornado.web.RequestHandler): def get(self): self.render( "recommended.html", page_title="burt‘s books | recommended reading", header_text="recommended reading", books=[ { "title": "Programming Collective Intelligence", "subtitle": "Building Smart Web 2.0 Applications", "image": "/static/images/collective_intelligence.gif", "author": "Toby Segaran", "date_added": 1310248056, "date_released": "August 2007", "isbn": "978-0-596-52932-1", "description": "<p>This fascinating book demonstrates how you " + "can build web applications to mine the enormous " + "amount of data created by people... </p>" }, ] ) class BookModule(tornado.web.UIModule): def render(self, book): return self.render_string(‘modules/book.html‘, book=book) if __name__ == "__main__": ... ui_modules = { "Book": BookModule, } ...
render_string是将模板渲染后以string的形式返回,这里的逻辑是请求首先通过RecommendedHandler类来处理,这个类使用模板recommended.html来渲染,然后在这个模板中对于每一本书的渲染将调用BookModule类来处理
embedding javascript and css
一些用来在模板中嵌入jss,cs,html等的函数:
- embedded_css()
- embedded_javascript()
- html_body()
- css_files()
- javascript_files()
1.embedded_javascript
class BookModule(tornado.web.UIModule): def render(self, book): return ... def embedded_javascript(self): return "document.write(\"hi!\")"
2.函数中插入的内容在html中将会内置在<script>标签中,放在</body>标签的前面
<script type="text/javascript"> document.write("hi") </script>
3.embedded_css用法类似,插入的内容内置在<style>标签中,eg
def embedded_css(self): return ".book {background-color:#F5F5F5}"
4.html_body()函数可以在</body>前加入html语句
def html_body(self): reutrn "<script>document.write(...)</script>"
5.css_files(), javascript_files()可以引用css,js文件
def css_files(self): return "static/css/style.css" def javascript(self): return "https://ajax.googleapis.com/ajax/.../jquery-ui.min.js"