Flask最佳实践

Posted Python之美

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask最佳实践相关的知识,希望对你有一定的参考价值。


这是「写个抓取网易云音乐精彩评论的爬虫」的续篇。本节将主要分享 https://github.com/dongweiming/commentbox 中我使用Flask的考虑以及延伸出来的问题。


1. 怎么用扩展


在Application Factories提到了如何用扩展,也就是在create_app内才用init_app初始化对应的扩展。但是我推荐如下方式来组织扩展。首先 创建一个ext.py(叫extensions.py或者其他我也不反对)文件,用来管理全部的扩展:


Flask最佳实践

同样在create_app里面初始化(https://github.com/dongweiming/commentbox/blob/master/app.py#L18):

Flask最佳实践

举个例子,注意其中的db,我没有用 「from yourapplication.model import db」,而是使用了第三方的ext中import进来的。

而在model里面怎么用呢(https://github.com/dongweiming/commentbox/blob/master/models.py#L24):

Flask最佳实践


这样就解耦了扩展的使用,也就是不会有相互依赖的问题了,这就是init_app存在的意义。


2. 自定义RESTAPI的处理


现存的框架比较知名的有django-rest-framework和flask-restapi,但是这些框架我都不太满意,而对于我这个项目用它们还太重了。好吧,手动写一个实现。首先是借用 DispatcherMiddleware 实现对/j这样的路径特殊处理(https://github.com/dongweiming/commentbox/blob/master/app.py#L23):

Flask最佳实践

我希望/j开头的返回的响应都是json格式的内容:

Flask最佳实践

其中返回了一个额外的字段r, 如果是0表示响应的结果是正确的,为1表示响应的内容有问题。

接着我们自定义错误处理的方式,比如404返回这样:

Flask最佳实践
怎么实现呢:

Flask最佳实践

而且响应也被封装了:

Flask最佳实践

使用的时候可以让返回的正确和错误结果的格式都保持统一。


3. Redis序列化


我使用了mongoengine处理model,但是为了给后端减少压力,所以使用Redis缓存结果。大家知道Redis支持了很多数据结构,对我来说,其实是可以满足的,但是为了演示如何存储复杂对象,单个文档对象缓存的是序列化之后的结果,也就是一个字符串(https://github.com/dongweiming/commentbox/blob/master/models.py#L42):

cache.set(key, rs.to_json())

取的时候这样用:

Flask最佳实践

其中from_json和to_json都是mongoengine自带的,希望对大家在业务中的使用有启发。


4. local_settings.py


local_settings.py在豆瓣被广泛的使用,一般的Flask应用都会有一个config.py文件,包含一些配置,它会被放进版本库。但是线上和测试环境其中的一些设置是不一样的,比如DEBUG在线上一定是False,但是在测试环境就是True。 那么可以在config.py这么用(https://github.com/dongweiming/commentbox/blob/master/config.py#L17):

Flask最佳实践

假如存在local_settings.py,那么配置就被会覆盖了,而local_settings.py就是在特定环境下才存在的。


5. 使用Mako


豆瓣在我印象里面好像都是没人使用Jinja2的。Mako是另一个知名模板语言,它有如下优点:

1. 性能和Jinja2相近,这一点Jinja2也承认。

2. 有大型网站在使用,有质量保证。Reddit在2011年的月PV就达到10亿,豆瓣几乎全部用户产品都使用Mako模板,所以不需要担心没有大公司使用的案例。

3. 有知名Web框架支持。Pylons和Pyramid这两个Web框架内置Mako,而且把它作为默认模板。

4. 支持在模板中写几乎原生的Python语法的代码,对Python工程师友好,我已经见过多个人来了豆瓣爱上Mako而抛弃Jinja2的例子了。

5. 自带完整的缓存系统。Mako提供非常好的扩展接口,很容易切换成其他的缓存系统。

Jinja2和Mako的设计哲学有一点不同:Jinja2认为应该尽可能把逻辑从模板中移除,界限清晰,不允许在模板内写Python代码,也不支持全部的Python内置函数(只提供了很有限、最常用的一部分);而Mako正好相反,它最后会编译成Python代码以达到性能最优,在模板里面可以自由写后端逻辑,不需要传递就可以使用Python自带的数据结构和内置类。Jinja2带来的好处是模板引擎易于维护,并且模板有更好的可读性;而Mako是一个对Python工程师非常友好的语言,限制很少,完成模板开发工作时更有效率,整个项目的代码可维护性更好。


6. 合理使用Flask提供的资源


这并不是这个项目中用到的实践。我在豆瓣东西的一个后台项目看到过这样用蓝图:

Flask最佳实践

其实好的做法是什么呢:


是否懂了呢?



以上是关于Flask最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

在片段和活动之间进行通信 - 最佳实践

Flask最佳实践

android片段-数据传递-最佳实践[重复]

最佳实践从 0 开始,用 flask+mongodb 打造分布式服务器监控平台

使用 FLASK 将 REST API 与 Web 界面相结合的最佳实践

在另一个活动托管的片段之间传递数据的最佳实践