Используйте CLI Flask Click с шаблоном фабрики приложений

Я определяю свое приложение Flask, используя шаблон фабрики приложений. При использовании Flask-Script я могу передать фабричную функцию в файл Manager. Вместо этого я хотел бы использовать встроенный в Flask интерфейс командной строки Click. Как использовать фабрику с 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()

person user3313834    schedule 12.03.2017    source источник


Ответы (2)


Команда flask представляет собой интерфейс Click, созданный с помощью flask.cli.FlaskGroup. Создайте свою группу и передайте ей заводскую функцию. Используйте app.shell_context_processor для добавления объектов в оболочку.

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

В идеале создайте точку входа и установите свой пакет в env. Затем вы можете вызвать скрипт как команду. Создайте файл 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

Использование собственного интерфейса командной строки менее надежно, чем встроенная команда flask. Поскольку ваш объект cli определен с помощью другого вашего кода, ошибка на уровне модуля приведет к сбою загрузчика, поскольку он больше не может импортировать объект. Команда flask отделена от вашего проекта, поэтому на нее не влияют ошибки в вашем модуле.

person davidism    schedule 13.03.2017

Чтобы передать аргументы вашей фабрике приложений, вам нужно использовать 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 к setup.py, как упоминалось в @davidism, либо после запуска pip install manage.py).

person reubano    schedule 09.04.2020