Tornado Web 開發 框架搭建 (2)

模板設置

因爲tornado自帶本身的模板,要把jinja2引入tornado須要作一些特殊處理 css

在這裏,新建jinja.py 參考https://github.com/mxyzm/snail/blob/master/joiners/jinja.py html


#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 給前臺使用 python

而後主Application使用Mixin 繼承 JinjaApplicationMixin git

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裏面使用: github

@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 也一樣能實現相應功能,這裏就沒作測試。

下面是登陸窗口的示例 web

{% 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
相關文章
相關標籤/搜索