tweb

作者: yuchanns | 来源:发表于2019-01-08 15:36 被阅读3次

基于Tornado的MTV脚手架

将常用到的功能和模块封装成一个MTV脚手架。主要加入了jinja2模板引擎(异步),aioredispeeweepeewee_asyncvuejselementuiaxios
目前异步数据库和异步缓存仅加入mysqlredis配置。

使用方法:

克隆到本地

git clone git@github.com:yuchanns/tweb.git

安装环境

项目根目录执行

pip install -r requirements.txt 

创建App

以下所有相对路径皆以项目根目录为起始。

blog为例:

进入项目根目录,运行python manage.py --cmd=startapp --app=blog
在项目根目录下就会生成一个blog文件夹。
./core/settings.py中,将blog/templates加入TEMPLATE_PATH

# ./core/settings.py
# ...
TEMPLATE_PATH = (
    os.path.join(BASE_DIR, 'blog/templates')
)

./core/urls.py中,导入blog.urls.routes

# ./core/urls.py
from blog.urls import routes as blog

routes = blog # + another_routes + ...

然后运行python manage.py --cmd=runserver --port=8080,访问localhost:8080/blog即可。

XSRF

manage.py提供一个生成cookie_secrete方法,运行python manage.py --cmd=generate即可获得一串密钥,写入./core/settings.pyCOOKIE_SECRET并开启XSRF_COOKIES = True即可使用Tornado自带的XSRF功能。

  • 当你使用form进行表单提交时
    在模板文件的<form>表单中加入{{ xsrf_form_html }}即可。
  • 当你使用ajax进行表单提交时
    在模板文件中引入./static/js/helpers.js
    <script>标签中使用getCookie("_xsrf")获得XSRFToken,并在headers中添加X-XSRFToken字段:

注意:由于tornado自身的get_argument方法无法识别dataType=json的数据,所以XSRFToken一定要加在headers中。

<!DOCTYPE html>
<html>
<head>
  <title>blog</title>
  <script src="{{ static_url('js/helpers.js') }}"></script>
  <script src="{{ static_url('js/axios.min.js') }}"></script>
</head>
<body>
<script>
function fetch() {
    axios.post(url, data, {
        headers: {
            'X-XSRFToken': getCookie('_xsrf')
        }
    }).then(function(response) {
        // do something
    }).catch(function(err)) {
        console.log(err)
    }
}
</script>
</body>
</html>

当然你也可以通过{{ xsrf_token }}直接获得XSRFToken

关于对ajax请求数据的接收

由于tornado自身的get_argument方法无法识别dataType=json的数据,所以我在CoreHandler中简单封装了一个post_argument方法,用于接收ajax请求数据:

from core.handlers import CoreHandler


class Handler(CoreHandler):
    def post(self):
        value = self.post_argument('key', None)

关于jinja2vuejsMustache语法冲突

三种解决方法:

  • 更改jinja2的变量引用符号
# .core/jinja2_env.py
# ...
async def render_template(self, template_name, **kwargs):
    env = Environment(loader=FileSystemLoader(self.settings['template_path']), enable_async=True)
    env.variable_start_string = '{['  # 更改变量引用符的开头
    env.variable_end_string = ']}'  # 更改变量引用符的结尾
    
    # ...
  • 更改vuejs的变量引用符号
new Vue({
    delimiters: ['{[', ']}'],
    // ...
})
  • 使用模板引擎的{% raw %}转义功能(个人推荐)

<div id='app'>标签中的Mustache语法会被模板引擎忽视,而<script>中的将会被模板引擎处理。

<!DOCTYPE html>
<html>
<head>
  <title>blog</title>
  <script src="{{ static_url('js/vue.js') }}"></script>
</head>
<body>
{% raw %}
<div id='app'>
{{ greeting }}
</div>
{% endraw %}
<script>
new Vue({
    el: '#app',
    data: function() {
        return {
            greeting: '{{ greeting }}'
        }
    }
})
</script>
</body>
</html>

生成models

使用peeweepwiz方法生成models.py之后,需要对该文件进行修改以支持异步:

# .core/models.py
from peewee import *
from peewee_async import Manager  # 导入Manager
from core.core import database  # 将database替换成从core.core导入


class UnknownField(object):
    def __init__(self, *_, **__): pass


class BaseModel(Model):
    object = Manager(database)  # 新增object成员变量
    atomic = database.atomic_async  # 新增异步事务支持

    class Meta:
        database = database

# ...

关于redis缓存

如果在.core/settings.py中开启了redis,并且debug = False,将会自动开启页面缓存,过期时间5分钟。可在.core/handlers.pyprepare()中进行修改。
在继承了CoreHandler的Handler中使用缓存的方式:

from core.handlers import CoreHandler


class Handler(CoreHandler):
    async def get(self):
        await self.cache.set('key', 'value')
        value = await self.cache.get('key')

关于路由

urls.py默认使用tornado.web.URLSpec,具有别名(alias)功能。在模板页面可使用{{ reverse_url('alias') }}对别名进行反向解析获得路由地址。

其他

关于各模块的更多使用,请参考开头列出的各自官方使用手册

相关文章

  • tweb

    基于Tornado的MTV脚手架 将常用到的功能和模块封装成一个MTV脚手架。主要加入了jinja2模板引擎(异步...

  • how to estimate story points

    http://info.thoughtworks.com/rs/thoughtworks2/images/tweb...

网友评论

      本文标题:tweb

      本文链接:https://www.haomeiwen.com/subject/psfbrqtx.html