Python 使用烧瓶&x27;s使用应用程序工厂模式单击CLI

Python 使用烧瓶&x27;s使用应用程序工厂模式单击CLI,python,flask,command-line-interface,python-click,flask-script,Python,Flask,Command Line Interface,Python Click,Flask Script,我使用AppFactory模式定义我的Flask应用程序。当使用Flask脚本时,我可以将工厂函数传递给管理器。我想改用Flask的内置Click CLI。如何使用带有Click的factory from flask import Flask from flask_script import Manager, Shell def create_app(): app = Flask(__name__) ... return app manager = Manager(c

我使用AppFactory模式定义我的Flask应用程序。当使用Flask脚本时,我可以将工厂函数传递给
管理器
。我想改用Flask的内置Click CLI。如何使用带有Click的factory

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()
我当前的代码使用Flask脚本。如何使用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()

flask
命令是使用
flask.cli.FlaskGroup
创建的单击界面。创建自己的组并将其传递给factory函数。使用
app.shell\u context\u 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
命令。您将使用您的工厂获得单击界面

FLASK_DEBUG=1 python app.py run

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

项目/
应用程序/
__初始值
setup.py
pip安装-e/path/to/project
FLASK_调试=1个应用程序运行


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

为了将参数传递给应用程序工厂,您需要使用
脚本信息
,例如

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()
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:'
config.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()
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生产运行
(如@davism所述,将
入口点
添加到
setup.py
,或者运行
pip install manage.py