一. 在 tornado模板中使用自定义方法
在tornado中可以使用两种方式,达到在模板中调用自定义方法的效果,第一种是使用UIMethod 和UIModule。
1.UIMethod使用方法示例如下:
(1)在项目中建立一个新py文件命名为uimethod:
需要注意的是,这里的函数都需要加一个参数self,否则会报错
1 def show(self): 2 return "1111" 3 4 def lower_case(self, arg): 5 return arg.lower()
原因是这里的函数,其实本质上是渲染模板的handler类的方法,如下图中debug时候跟踪的结果所示,self其实就是MainHandler的实例
(2)在程序入口文件中引入并注册settings(key为ui_methods):
1 import uimethods as mt 2 3 # 其他的部分略... 4 5 settings = { 6 'template_path': 'template', 7 'static_path': 'static', 8 'static_url_prefix': '/static/', 9 'ui_methods': mt, 10 }
(3)在模板中使用方法:
注意这里调用lower_case处的入参test,是必须在render模板的时候,传入方法的,否则就是未定义,和其他直接在模板里使用的变量相同:
1 class MainHandler(tornado.web.RequestHandler): 2 @asynchronous 3 @gen.coroutine 4 def get(self): 5 is_authed = (self.get_cookie('auth', None) == USER) 6 self.render('index.html', is_authed=is_authed, user_id=self.get_cookie('auth', None), contents=CONTENTS, test='AA')
2. UIModule使用方法示例如下:
(1)创建文件
UIModule就是自定义类继承UIModule,其方法render返回的内容在模板上调用类的时候会被显示
1 from tornado.web import UIModule 2 from tornado import escape 3 4 class showMod(UIModule): 5 6 def render(self, *args, **kwargs): 7 return escape.xhtml_escape('333')
(2)在程序入口文件中引入并注册settings(key为ui_mothods):
1 import uimethods as mt 2 3 settings = { 4 'template_path': 'template', 5 'static_path': 'static', 6 'static_url_prefix': '/static/', 7 'ui_methods': mt, 8 'ui_modules': md, 9 }
(3)在模板中使用:
3. 然后小记一点tornado模板实现的原理:
实际上就是把模板的html,先根据{{与{%等特殊字符分割,将这些特殊部分外的字符串与特殊字符内的内容进行拼接;特殊字符内的字符串会经过一些特殊处理,比如获取变量判断类型,做python的逻辑判断或者是循环或者是函数调用等等,然后这些运算结果与其他部分进行拼接。拼接的方式是生成如左图这样一个函数的字符串,该函数作用是将内容根据我之前说的步骤,append到_buffer的列表里。然后把这个字符串用compile和exec即可编译执行。
对于函数中的参数如"title","data",是将render方法里面传入的参数,作为namespace全局变量加入exec里面,这样来实现的,简单的模拟如下:
4. tornado当中还提供了一写内置模板方法(其实也是用UIMothod,UIModule)实现的,小计如下:
- escape: tornado.escape.xhtml_escape 的別名
- xhtml_escape: tornado.escape.xhtml_escape 的別名
- url_escape: tornado.escape.url_escape 的別名
- json_encode: tornado.escape.json_encode 的別名
- squeeze: tornado.escape.squeeze 的別名
- linkify: tornado.escape.linkify 的別名
- datetime: Python 的 datetime 模组
- handler: 当前的 RequestHandler 对象
- request: handler.request 的別名
- current_user: handler.current_user 的別名
- locale: handler.locale 的別名
- _: handler.locale.translate 的別名
- static_url: for handler.static_url 的別名
- xsrf_form_html: handler.xsrf_form_html 的別名
二. static_path 和 static_url_prefix配置
在tornado的settings当中,有两个非必选参数 static_path和static_url_prefix,用来简化关于静态文件获取的方法。使用实例如下:
1. static_path 默认值为 static,也就是配置的所有静态文件的根目录,然后在模板或css中寻找文件路径的时候,就不用都自己去做一写绝对路径的配置写法了,方便统一管理修改,tornado就回到这里去找静态文件。只需要在模板中使用方法static_url,就会自动生成访问静态文件的相对路径,使用示例如下:
结果转换出来的是:
可以看到自动在css前面加了static,后面的v=XXXXXXXX则是static_url的另外个功能即让浏览器生成缓存记录
2.static_url_prefix 默认值为 /static/, 配置的是模板方法 static_url 里生成的结果里面 ,比如上面那个例子里面,就是/static/css前面的这个static,是可以改掉的,url就会不同。不过改这个不影响去找静态文件的存储路径也就是static_path
三. tornado中对cookie的一些操作
1. tornado中设置cookie示例:
1 self.set_cookie('auth', user_id, expires_days=30)
前两个分别是cookie键和值,后面的expires_days是可选参数,设置过期时间。如果我们想操作用户登出以后的cookie失效,可以改成expires_days=0。此外set_cookie还有个重要的可选参数是path,可以指定路径,这个cookie就会只能在指定的路径(路由页面)生效。
2. 获取cookie示例:
1 self.get_cookie('auth', None)
3. 给cookie加盐示例:
tornado中的set_cookie和get_cookie是明文不加密传输的,set_secure_cookie和get_secure_cookie是明文加密传输的,使用后两者的方法与前两者相同,只是需要在settings里面多加一点,在tornado.web.Application中设置cookie_secret参数:
也就是为其加盐!此外如果我们看一下set_secure_cookie的源码,会发现其expires_days默认值为30,而set_cookie的默认值为None...也就是注意用了set_secure_cookie以后默认就会持续30天的,而且还发现set_secure_cookie当中并没有path这个可选参数哦。
4. 此外RequestHandler 的cookies(示例用self.cookies)属性是获得所有cookie。
四. 对ajax发送的数据中含有中文的处理
在尝试使用ajax向tornado后端发post请求时候,我发现发送的data里面带有非拉丁字符的话,tornado在获取是会产生错误,无法正确地用get_argument取到参数
这个时候可以使用js的“encodeURI”方法来进行编码,示例如下:
1 var params = "article=" + encodeURI(text) + "&group=" + encodeURI(group);
这样在py3的tornado中使用get_argument时候就能正确获取了,而且也不用特意再decode。