flask 全家桶学习笔记

看到标题有的同学可能就问了,flask 是一个微框架,哪儿来的全家桶啊?其实作为一个框架来说,除非你提供的只有静态页面,那么肯定要和数据库打交道的,也要有后台登录管理以及提供 API 等等一大堆常规工作要做的。当提供这些功能的时候,就需要各种全家桶组件了,那么这篇文章里介绍的就是 flask + plugins + uwsgi 等等一系列的工具。

hello world

from flask import Flask, request

app = Flask(__name__)

@app.route("/")
def hello():
    return "hello, world"

app.url_map.strict_slashes = False  # 关闭 url 结尾的 `/` 检查
app.run()

Flask 中直接使用 request 对象访问请求的数据,比如:

  • request.form, Post 的数据字典
  • request.args, GET 参数
  • request.values, 以上两个都包括
  • request.json 属性,或者 request.get_json() 函数,不过 flask 会要求请求 header 必须是 Content-Type: application/json 类型的,这个是一个坑。

基于类的视图

Flask 默认采用的是基于函数和装饰器的视图。而有时候对于一些 CRUD 的资源,还是使用类更清晰一些,Flask 也是支持的。

from flask.views import MethodView

class PostView(MethodView):
    def get(self, id):
        if id is None:
            ...  # return a list of objects
        else:
            ...  # return a single object

    def post(self):
        ...

    def put(self, id):
        ...

    def delete(self, id):
        ...

def add_resource_view(app, view, url):
    view_func = view.as_view(view.__class__.__name__)
    url = url.rstrip("/")
    app.add_url_rule(url, defaults={"id": None}, view_func=view_func, methods=["GET"])
    app.add_url_rule(url, view_func=view_func, methods=["POST"])
    app.add_url_rule(url + "/<id>", view_func=view_func, methods=["GET", "PUT", "DELETE"])

add_resource_view(app, PostView, "/post")

使用 blueprints

在 Flask 中如果需要切分应用的话,那么需要使用 Blueprints. 比如说,我们有下面这样的目录:

app.py
views/
  posts.py

两个文件的内容分别是:

# posts.py
from flask import Blueprint, render_template

posts_bp = Blueprint('posts', __name__)

@posts_bp.route("/")
def index():
    return [{"title": "hello world"}, ...]
# app.py
from views.posts import posts_bp

app = Flask(__name__)
app.register_blueprint(posts_bp, "/posts")

一般在刚开始搭建的时候,也没必要一定要分 blueprints, 等函数太多了再分也不迟。

App Factory Pattern

在前面的例子中,我们都直接在模块中 app = Flask(__name__) 了,这样做实际上是有问题的。官方推荐使用 app factory pattern。

app factory pattern 其实也很简单,就是把 app 的创建包装在了 app.py 的 create_app 函数中,然后在这个函数中创建一个 Flask 实例,并调用各个插件的 init_app 函数。

这样做的好处主要有两点:

方便多环境部署

直接导入 app 的话,已经初始化了,无法再更改 app 的配置

from example import app

如果把 app 的创建包装在一个函数中,可以在创建 app 的时候传递不同的参数,可以区分开发测试等不同环境。

def create_app(**kwargs):
    app = Flask(**kwargs)
    return app

from example import create_app
app = create_app(DB_CONN="production")

方便依赖管理

默认情况下,代码可能是这样的,所有的代码都得依赖 app.py

# app.py
app = Flask(__name__)
db = SQLAlchemy(app)

# models.py
from example import db

class User(db.Model):
    pass

使用了 app factory pattern 之后,每个模块都可以不依赖 app.py,而是使用自己的 blueprint

def create_app():
    app = Flask(__name__)
    from example.models import db
    db.init_app(app)
    return app

# models.py
db = SQLAlchemy()

class User(db.Model):
    pass

Context

一般来说,Application Context 和 Request Context 有相同的生命时间。

参考文献

  1. https://blog.csdn.net/u010466329/article/details/78522992
  2. https://blog.csdn.net/qq_21794823/article/details/78194164
  3. http://www.manongjc.com/article/48448.html
  4. https://juejin.im/post/5964ce816fb9a06bb21abb23
  5. https://www.cnblogs.com/whitewolf/p/4686154.html
  6. 为什么要使用 APP Factory Pattern
  7. https://flask-login.readthedocs.io/en/latest/
  8. https://flasksession.readthedocs.io/en/latest/

及时获取更新,请关注公众号“爬虫技术学习(spider-learn)”

公众号“爬虫技术学习(spider-learn)”

About 逸飞

后端工程师

发表评论

邮箱地址不会被公开。 必填项已用*标注