基于 Flask 的快速 Web 开发入门
Posted 百姓网技术团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于 Flask 的快速 Web 开发入门相关的知识,希望对你有一定的参考价值。
一、前言
Flask 是基于 Werkzeug 的一个小型框架,小到都不应该把 Flask 叫框架(Framework),因为它没有像常见框架那样集成 ORM,只有薄薄的请求处理和模板渲染功能。
但我们不能因为 Flask 小,就轻视它,认为它是一个玩具框架,不能用于生产实践。相反,正是因为它结构松散,没有绑定多余的东西,因此它足够灵活,你可以根据自己的需要,去集成任何你想要的东西。
Python 庞大的生态,加上 Flask 丰富的扩展,在用 Flask 做 Web 开发的过程中,几乎可以轻易地找到大部分想要的 “轮子”,从而可以让开发人员专注于业务功能,实现产品的快速开发。
本文以一个简单的 CMS 系统为例,为大家分享如何在一个小时之内,利用 Flask 框架快速地搭建起一个带管理后台和 API 的简单 CMS 系统。
另外,本文是入门教程,主旨是分享 Flask 框架的使用以及其丰富的周边生态,让大家对 Flask 开发 Web 的方便和快捷有个基本的了解,因此会更注重于看得见摸得着的开发实践,而不会对框架的源码做详细深入的介绍。所以,暂时略去了关于 WSGI 和 Werkzeug 的介绍,有兴趣的可以看下官方文档。
二、快速开始
要想构建一个 CMS(内容管理系统),最重要的东西是什么呢?毫无疑问,就是文章和文章分类,那我们就以这两点为基础,进行我们的开发构建。
2.1 基础环境搭建
因为是 CMS 系统,所以数据库是免不了的,这里使用 SQLAlchemy 作为数据库的 ORM 层。具体安装非常简单,一句话就可以搞定:
pip install Flask Flask-SQLAlchemy
2.2 Quick Demo
from flask import Flask
app = Flask(__name__)
@app.route('/')
def main():
return 'hello world'
if __name__ == '__main__':
app.run(debug=True, port=5012)
以上是每一个框架所必备的 Hello World 示例。可以看到,使用 Flask 的入门成本是极低的,没有冗余繁琐的配置和需要事先了解的一大堆的范式,只有简单的路由定义和一目了然的响应方式,让我们可以用极快的速度上手开发。
2.3 表模型创建
下面我们直接进入正题,开始真正的 CMS 的开发。
from flask_sqlalchemy import SQLAlchemy
DB = SQLAlchemy(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'SQLite://test.db'
下面是我们要定义的表模型:
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(48), nullable=False, doc='分类名')
pid = db.Column(db.Integer, nullable=False, index=True, doc='父ID')
def __repr__(self):
return '{} <{}>'.format(self.name, self.id)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128), index=True, nullable=False, doc='标题')
category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False, doc='分类ID')
content = db.Column(db.Text)
category = db.relationship('Category', backref='post')
然后是利用 Flask 自带的 hook,在首次响应的时候,自动创建数据库表模型:
@app.before_first_request
def create_db():
db.create_all()
在我们访问了一次 http://127.0.0.1:5012
以后,会自动在当下目录生成 test.db 文件,这个就是我们的数据库了。
三、快速构建管理控制后台
有了数据库表模型以后,我们想的第一件事情应该就是往数据库里塞一点测试数据,然后供我们继续的开发测试用了。这个时候,有的同学就会找一个数据库客户端,然后打开我们刚才生成的 test.db 文件,然后找到我们刚刚创建的 category 和 post 这两张表,往里面插入数据了。
接下来我是不是要说这个呢?
看我们的小标题就知道了,肯定不是!
我们要做的是在创建完表模型以后,快速地构建出一个管理后台,让我们能够通过这个管理后台去做生成和修改测试数据的事情。但是,天天写增删改查这种逻辑任谁也受不了,所以我们需要一个比较无痛的方法省掉我们那些增删改查的代码,把我们从重复中解放出来。
OK,下面祭出我们的 Flask 界的后台生成神器:Flask-Admin。
这是一款前端基于 bootstrap 的后台管理工具,安装同上,依然是很简单的 pip install Flask-Admin
就可以搞定。
在代码中的引入和实例化也和 SQLAlchemy 类似:
from flask_admin import Admin
admin = Admin(app, name='Baixing Simple CMS', template_mode='bootstrap3')
细心的同学看到这个地方就会发现,Flask 的扩展的命名和引入方式大多都是一样的,先引入扩展,然后实例化的时候传入 app 实例,使之与 Flask 绑定。这里有个注意点,就是 Flask-Admin 使用的时候需要我们去配置 SECRET_KEY
这个参数,如果不定义的话,是没办法在后台进行表单提交的。配置方法很简单,在上面配置 SQLALchemy 的地方,再补充一句配置就可以了,示例如下:
app.config['SECRET_KEY'] = '!!!-----www.baixing.com-----!!!!'
既然是自动生成后台的工具了,那么必然有一个生成的依据,这个依据就是我们刚刚定义的 SQLAlchemy 模型,在 Flask-Admin 中,我们可以直接使用由 SQLAlchemy 定义的模型来生成增删改查的页面。
先引入适配 SQLAlchemy 的 ModelView:
from flask_admin.contrib.sqla import ModelView
最后一步,创建我们需要的管理页面:
admin.add_view(ModelView(Category, db.session))
admin.add_view(ModelView(Post, db.session))
接下来访问 http://127.0.0.1:5012/admin/
看下效果。
后台列表页截图:
后台编辑页截图:
Awesome!!
一个带着增删改查全功能的后台就这么出来了,而且从上图可以看到,在创建 Post 的时候,Flask-Admin 可以自动识别外键,直接将 category 和我们的 Category 模型进行关联,而显示的内容,正是我们定义 Category 这个模型的时候,定义在 __repr__
这个魔术方法中的返回值。
上面的例子里,我们代码基本都是通过配置的方式生成的,虽然很快速,但有的同学一定会有这样的疑惑,就是我们用的 Flask-Admin,会不会因为自动生成的缘故,导致难以实现定制,从而降低了应用的可扩展性。
可以肯定的说,自动生成必然会带来可扩展性的降低,但是 Flask-Admin 给我们预留的扩展的口子还是很多的。从模板层面来讲,因为是基于 Bootstrap 的,所以你几乎可以无痛地将模板更换成任何你想用的 Bootstrap 模板,笔者就曾经换了一套 AdminLTE2 模板 ( github.com/couldtt/flask-admin ) 用在公司一个项目的开发上。
另外,在使用 Flask-Admin 的时候,我们可以不局限于 ModelView 这种方式,把 Flask-Admin 当做一种页面布局的方式。通过 ModelView 和 CustomView 混合布局的方式,适合直接用模型生成的就直接生成,不合适的就略做调整,通过重定义各类 form 操作的方法来实现部分的自定义,如果还是不合适,那就直接重写界面,Flask-Admin 提供了一个 expose 方法,用途和 Flask 中的 route 方法类似,可以用来定义 Admin 的路由。
最后,顺便提一句,Airbnb 开源的数据流管理工具 Airflow ( github.com/apache/incubator-airflow ) 也是基于 Flask-Admin 开发的哦~
四、快速构建 Restful 风格的 API
通过上面的内容,我们已经构建出了一个 CMS 的雏形,但是还缺了最重要的一层——展示层。这里我们使用当下流行的前后端分离的方式去做,输出 Restful 风格的 API 供前端使用。
Restful 风格的 API 说白了其实就是针对一个 Resource 用 HTTP 协议里已经有定义的 Method 来进行增删改查。比如我们的 Post 接口,我们需要能够看到 Post 列表,能够看到 Category 列表,能够看到 Post 的详细内容。但是我们不能删除这些内容,因为我们的 API 是给客户端用的,而我们的观众是没有这个权限干这个事情的。
所以,到这里明确了我们要做的事情,我们需要以下几个 API:
Post Listing (
/post
)Post Detail (
/post/postID
)Category Listing (
/category
)Post Listing by category (
/category/categoryID/post
)
对于 Listing 类型的接口,我们通常需要额外增加一个翻页的功能,以供内容足够多的时候进行分块的显示。
既然说了是快速构建,那这里肯定也不是手写一堆查询的逻辑和分页的逻辑了,依然是用配置为主少量自定义为辅的方式进行。
这里再引入一个 Flask 里很好用的扩展:Flask-Restless。安装同上 pip install Flask-Restless
,使用上也和 Flask-Admin 相似:
from flask_restless import APIManager
api_manager = APIManager(app, flask_sqlalchemy_db=db)
api_manager.create_api(Post, methods=['GET'])
api_manager.create_api(Category, methods=['GET'])
至此,我们需要的四个查询接口,都已经被生成了。访问方式是 URL 后面加个 API,然后接上我们的 post 或者 category 即可。
关于 Post Listing、Post Detail、Category Listing 这三个接口的返回,因为很简单,这里不再赘述,着重说一下 Post Listing by category 这个接口。
看 URL 就可以猜出,这个接口的目的在于返回某个分类下的文章,而我们什么都没做,只是定义了 Post 和 Category 这两个 Resource 而已,直接访问 /api/category/categoryId/post
就可以获取下面的结果,而这其中的奥秘就在于我们上面定义 Post 这个模型的时候,定义的 Relationship category = db.relationship('Category', backref='post')
,backref 的全称是 “back reference”,反向引用的意思。Flask-Restless 可以直接读取这个引用关系,直接应用到我们创建的 API 上面去,可谓十分方便。
Post Listing by category 的返回结果:
{
num_results: 2,
objects: [
{
category: {
id: 1,
name: "未命名",
pid: 0
},
category_id: 1,
content: "212121",
id: 1,
title: "1212"
},
{
category: {
id: 1,
name: "未命名",
pid: 0
},
category_id: 1,
content: "",
id: 3,
title: "3241234"
}
],
page: 1,
total_pages: 1
}
从上面的返回结果中看,分页已经被处理了,我们在使用 GET 语义的接口获取 Listing 相关的内容时,是不需要去关心 total 以及 offset 等分页的逻辑的,拿来就用即可。
另外,Flask-Restless 的功能远远不止这些,Flask-Restless 在每一个 HTTP Verb 上,都定义了对应的 preprocessor 和 postprocessor,你可以很轻松得使用面向切面编程的方式去插入各种中间件,针对特定的业务需求引入自己的业务逻辑。
五、后记
作为一个 CMS,上面的例子还很原始,它还缺少很多基本的功能,比如作者管理,授权等等。但是从这个例子出发,稍微扩展一下,加一加模型,在熟悉 Flask 开发的套路以后,将其补充成一个功能完备的 CMS 系统并不困难。
Flask、Flask-SQLAlchemy、Flask-Admin 和 Flask-Restless 进行配合,可以很轻松的实现我们日常开发中一些常见的某某系统,对于性能等要求不高的内部系统尤为合适。对于初创产品的构建,使用这个组合也可以很好地满足需求,既能实现快速开发的目标,同时又保留了扩展的空间,可以方便我们后期对项目进行重构和迁移。
https://gist.github.com/couldtt/22583f6f4cb303a29c2b004484afe9ab
六、参考资料
Flask 官方文档:http://flask.pocoo.org/
Flask-SQLAlchemy 官方文档:http://flask-sqlalchemy.pocoo.org/2.1/
Flask-Admin 官方文档:https://flask-admin.readthedocs.io/en/latest/
Flask-Restless 官方文档:https://flask-restless.readthedocs.io/en/stable/
张腾百姓网业务系统技术团队 TL。 |
本文仅为作者个人观点,不代表百姓网立场。
(题图来源:Flask Logo)
每周推送一篇技术文章, 长按二维码立即关注! |
以上是关于基于 Flask 的快速 Web 开发入门的主要内容,如果未能解决你的问题,请参考以下文章