共计 3083 个字符,预计需要花费 8 分钟才能阅读完成。
对于 Flask 最外围的有三点:
- Application Context: 将整个利用连成一体.
- View Function & CLI Command: 利用暴漏给外界的操作接口
- Blueprints (蓝图): 实现模块化开发
当然还有其余细节,但有了这三点,就能够编写一个残缺的 Web 援用了
Application Context
参考: Flask 2.0.x
我更习惯应用 工厂模式 创立 Context: 在 __init__.py
中写 create_app()
:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
configure(app, test_config)
db.init_app(app)
from faq.blueprints import review
app.register_blueprint(review.bp)
return app
当在命令行输出命令 flask run
时, flask 将主动寻找 create_app
函数来执行, 以创立 Application Context.
PS: flask run
便是一个默认的 CLI Command
默认在 View Function 和 CLI Command 中主动就在 以后利用的 Context 下. 而此外其余的场景下, 须要手动的创立 / 引入 Application Context. flask-sqlalchemy 中的例子:
with app.app_context():
user = db.User(...)
db.session.add(user)
db.session.commit()
但实际上 有 View Function 和 CLI 就足够了
View Functions & CLI Command
View Function 次要做到了门路和函数的映射绑定, 同时借助 Flask 其余的模块 (request
, current_app
, make_response
等 ), 取得参数和返回响应
参考: Flask 2.0.x Doc
这是一个 View Function 的例子.
bp = Blueprint('review_show', __name__, url_prefix='/review/show', cli_group=None)
@bp.route('/requests/<user_id>', methods=['GET'])
def show_requests(user_id):
page = int(request.args.get('page'))
per_page = int(request.args.get('page_size'))
data: dict = request.get_json()
print(data)
current_app.logger.info("request user id: %s", user_id)
requests: Pagination = ERequest.query \
.order_by(ERequest.time.desc()) \
.paginate(page=int(page), per_page=int(per_page), error_out=False)
body = [RequestEntry(rq) for rq in requests.items]
return make_response(jsonify(body), 200)
取得 param 参数:
page = int(request.args.get('page'))
per_page = int(request.args.get('page_size'))
取得 json 格局的 request body:
data: dict = request.get_json()
print(data)
响应
return make_response(jsonify(body), 200)
接下来是 CLI Command:
参考:
- custom-commands,
- testing-cli-commands: 蕴含了两种参数 (option, argument) 的用法
bp = Blueprint('review_show', __name__, cli_group='cli')
@bp.cli.command('test')
@click.option('--who', default='tom')
@click.argument('what', default='good morning')
def hello(who, what):
print(f'hello: {who},{what}')
运行:
PS D:\my\flask\app> $env:FLASK_APP = "faq"
PS D:\my\flask\app> flask cli hello
hello: tom,good morning
PS D:\my\flask\app> flask cli hello goodby --who bob
hello: bob,goodby
PS D:\my\flask\app>
Blueprints 蓝图
从 Java 转来的我非常心愿实现像 Spring boot Controller 那样的多模块开发. 行将不同类型或不同需要模块的 API 放在不同的 Controller 中, 而后通过命名加以辨别.
Blueprints 就实现了这点. 蓝图能够注册到 app 中去, 同时又能够注册其余子蓝图, 从而能够实现一个树状的注册构造.
比方, 这是我的文件目录
│ models.py
│ __init__.py
│
└─blueprints
│ __init__.py
│
└─ review
│ handle.py
│ show.py
└─ __init__.py
/blueprints/show.py
中 我定义了具体的 View Functions 和 CLI
bp = Blueprint('review_show', __name__, url_prefix='/review/show', cli_group='cli')
@bp.cli.command('hello')
@click.option('--who', default='tom')
@click.argument('what', default='good morning')
def hello(who, what):
print(f'hello: {who},{what}')
@bp.route('/requests/<user_id>', methods=['GET'])
def show_requests(user_id):
pass
这个蓝图 review_show
注册到另一个蓝图 review
中:
/blueprints/review/__init__.py
:
from flask import Blueprint
from faq.blueprints.review import show, handle
bp = Blueprint('review', __name__)
bp.register_blueprint(show.bp)
bp.register_blueprint(handle.bp)
最终, 蓝图 review
注册到 app 中:
/__init__.py
:
def create_app(test_config=None):
......
from faq.blueprints import review
app.register_blueprint(review.bp)
return app