关于flask:如何编写一个-Python-Web-应用-一Flask

33次阅读

共计 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

正文完
 0