由于tornado自带自己的模板,要把jinja2引入tornado需要做一些特殊处理
在这里,新建jinja.py 参考https://github.com/mxyzm/snail/blob/master/joiners/jinja.py
#coding=utf-8 """Make Jinja2 work with Tornado.""" from tornado import escape from jinja2 import Environment, FileSystemLoader class JinjaApplicationMixin(object): def __init__(self, *args, **settings): super(JinjaApplicationMixin, self).__init__(*args, **settings) if "template_path" not in settings: return if "template_loader" in settings: loader = settings['template_loader'] else: loader = FileSystemLoader(settings['template_path']) if "debug" in settings: auto_reload = settings["debug"] else: auto_reload = False autoescape = bool(settings.get('autoescape', False)) self.jinja_env = Environment( loader=loader, auto_reload=auto_reload, autoescape=autoescape, ) class JinjaHandlerMixin(object): def render_string(self, template_name, **context): self.require_setting("template_path", "render") default_context = { 'handler': self, 'request': self.request, 'current_user': self.current_user, 'static_url': self.static_url, 'xsrf_form_html': self.xsrf_form_html, 'reverse_url': self.reverse_url, 'me': self.oUser, } escape_context = { '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, } context.update(default_context) context.update(escape_context) context.update(self.ui) # Enabled tornado UI modules and methods. template = self.application.jinja_env.get_template( template_name) return template.render(**context)
这里我加了个当前用户对象me 给前台使用
然后主Application使用Mixin 继承 JinjaApplicationMixin
class MainApplication(JinjaApplicationMixin, tornado.web.Application): passserver.py 里面就可以这样跑
application = MainApplication(make_handlers(URL_PREFIX, (r'/', include('handlers.index')), (r'/', include('handlers.user')), (r'/', include('handlers.userGroup')),BaseHandler 同Mixin JinjaHandlerMixin
class BaseHandler(JinjaHandlerMixin, tornado.web.RequestHandler): def get_current_user(self): user = self.get_secure_cookie("user") if user is not None: self.oUser = self.session.query(User).filter_by(name=user).first() return user def initialize(self): self.session = db_session self.oUser = None def on_finish(self): self.session.close()这里已经为Sqlalchemy的session处理和 tornado的用户登录验证打好基础,等以后再做说明。
然后在handler里面使用:
@route('', name='index') class IndexHandler(BaseHandler): @tornado.web.authenticated @tornado.web.asynchronous def get(self): self.render("index.html")注意:
下面是登录窗口的示例
{% extends "base.html" %} {% block title %}登陆{% endblock %} {% block css %} <style type="text/css"> body { padding-top: 40px; padding-bottom: 40px; background-color: #eee; } .form-signin { max-width: 330px; padding: 15px; margin: 0 auto; } .form-signin .form-signin-heading, .form-signin .checkbox { margin-bottom: 10px; } .form-signin .checkbox { font-weight: normal; } .form-signin .form-control { position: relative; font-size: 16px; height: auto; padding: 10px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .form-signin .form-control:focus { z-index: 2; } .form-signin input[type="text"] { margin-bottom: -1px; border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .form-signin input[type="password"] { margin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0; } </style> {% endblock %} {% block body %} <div class="container"> <form class="form-signin" method="post"> {{ xsrf_form_html() }} <h2 class="form-signin-heading">登录</h2> <input name="name" type="text" class="form-control" placeholder="用户名" autofocus> <input name="pwd" type="password" class="form-control" placeholder="密码"> {% if form|d(none) is not none %} <div class="alert alert-danger"> {{ form.mainerr}} </div> {% endif%} <label class="checkbox"> <input name="remember" type="checkbox" value="remember">记住我 </label> <button class="btn btn-lg btn-primary btn-block" type="submit">登录</button> </form> </div> <!-- /container --> {% endblock %}静态文件通常如下使用:
<link href="{{ static_url("css/bootstrap.min.css") }}" rel="stylesheet" media="screen">需要在 server.py里面配置下 static_path