使用Flask的Click CLI和app工厂模式

时间:2017-03-12 23:15:38

标签: python flask click flask-script

我使用app工厂模式定义我的Flask应用程序。使用Flask-Script时,我可以将工厂函数传递给Manager。我想改用Flask的内置Click CLI。如何使用Click?

来使用工厂

我当前的代码使用Flask-Script。如何使用Click?

执行此操作
from flask import Flask
from flask_script import Manager, Shell

def create_app():
    app = Flask(__name__)
    ...
    return app

manager = Manager(create_app)

def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)

manager.add_command('shell', Shell(make_context=make_shell_context))

if __name__ == '__main__':
    manager.run()

2 个答案:

答案 0 :(得分:9)

flask命令是使用flask.cli.FlaskGroup创建的Click界面。创建自己的组并将其传递给工厂函数。使用app.shell_context_processor将对象添加到shell。

from flask import Flask
from flask.cli import FlaskGroup
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(script_info=None):
    app = Flask(__name__)
    db.init_app(app)
    ...

    @app.shell_context_processor
    def shell_context():
        return {'app': app, 'db': db}

    return app

cli = FlaskGroup(create_app=create_app)

@cli.command
def custom_command():
    pass

if __name__ == '__main__':
    cli()

运行您的文件而不是flask命令。您将使用工厂获得Click界面。

FLASK_DEBUG=1 python app.py run

理想情况下,创建一个入口点并在您的环境中安装您的包。然后,您可以将脚本作为命令调用。创建一个至少包含以下内容的setup.py文件。

project/
    app/
        __init__.py
    setup.py
from setuptools import setup, find_packages

setup(
    name='my_app',
    version='1.0.0',
    packages=find_packages(),
    entry_points={
        'console_scripts': [
            'app=app:cli',
        ],
    },
)
pip install -e /path/to/project
FLASK_DEBUG=1 app run

使用您自己的CLI不如内置flask命令强大。由于您的cli对象是使用其他代码定义的,因此模块级错误将导致重新加载器失败,因为它无法再导入该对象。 flask命令与您的项目是分开的,因此它不受模块中错误的影响。

答案 1 :(得分:1)

为了将参数传递给您的应用程序工厂,您需要像这样使用<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <button type="button" class="btn btn-primary" id="btn">Click to swap column order</button> <br /><br /> <div class="row"> <div class="col-6 d-flex align-items-center justify-content-center" id="logo-col"> <div class="logo-centered" id="logo_auth"> <a href="#default"> <img src="https://via.placeholder.com/200x100?text=Logo" alt="logo"> </a> </div> </div> <div class="col-6 d-flex align-items-center justify-content-center" id="slogan-col"> <div class="v1-slogan" id="v1_slogan"> <h3>Spécial covid-19</h3> </div> </div> </div> ...

script_info

manage.py

#!/usr/bin/env python import click import config from flask import Flask from flask.cli import FlaskGroup, pass_script_info def create_app(script_info): app = Flask(__name__) if script_info.config_mode: obj = getattr(config, script_info.config_mode) flask_config.from_object(obj) ... return app @click.group(cls=FlaskGroup, create_app=create_app) @click.option('-m', '--config-mode', default="Development") @pass_script_info def manager(script_info, config_mode): script_info.config_mode = config_mode if __name__ == "__main__": manager()

config.py

现在在命令行中,您可以执行class Config(object): TESTING = False class Production(Config): DATABASE_URI = 'mysql://user@localhost/foo' class Development(Config): DATABASE_URI = 'sqlite:///app.db' class Testing(Config): TESTING = True DATABASE_URI = 'sqlite:///:memory:' (在将manage -m Production run添加到entry_points并提到@davidism之后,或者运行setup.py。)