Tornado Web 开发 框架搭建 (2)

模板设置

由于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):
    pass
server.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")
注意:
  1. JinjaHandlerMixin里面的context是可以自己修改和添加的
  2. 在做BaseHandler的多继承的时候,一定要把mixin的放在前面,RequestHandler放后面
在server.py里面做下template_path 的配置
然后,在主页面里面就可以按jinja2的方式写模板了。理论上说,tornado的UI模块也能一起使用,但是个人觉得jinja2 的macro 也同样能实现相应功能,这里就没做测试。

下面是登录窗口的示例

{% 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



你可能感兴趣的:(python,tornado)