我应该在哪里实现flask自定义命令(CLI)

时间:2019-07-25 13:09:25

标签: python flask command-line-interface python-click flask-cli

在flask中创建自定义命令需要访问该应用,该应用通常在app.py中创建,如下所示:

import click
from flask import Flask

app = Flask(__name__)

@app.cli.command("create-user")
@click.argument("name")
def create_user(name):
    ...

但是,为了不肿我的app.py,我想将自定义命令放在一个单独的文件中,例如commands.py,但这不起作用,因为我项目的入口点是app.py,所以我必须在commands.py中导入应用程序,并在app.py中导入命令导致循环导入错误。

如何在单独的文件中创建自定义命令?

5 个答案:

答案 0 :(得分:5)

只需将其导入您的应用程序工厂

dir tree

my_app
     L app.py
     L commands.py

commands.py

@app.cli.command('resetdb')
def resetdb_command():
    """Here info that will be shown in flask --help"""
    pass

app.py

def create_app():
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    db.init_app(app)

    with app.app_context():
        from . import routes
        from . import commands  # <----- here

        return app
$ export FLASK_APP=my_app/app.py
$ flask resetdb

但是必须有更好的方法;)我现在还不知道

答案 1 :(得分:3)

一种实现此目标的方法是使用blueprints

我已经使用Flask 1.1.1对其进行了测试,因此请务必检查您拥有的正确版本的文档。

这是一般想法:

  1. 在另一个文件中创建一个或多个蓝图,我们称其为commands.py
  2. 然后导入新蓝图并将其注册到您的应用中

==> app.py <==

from flask import Flask
from commands import usersbp

app = Flask(__name__)
# you MUST register the blueprint
app.register_blueprint(usersbp)

==>命令。py<==

import click
from flask import Blueprint

usersbp = Blueprint('users', __name__)

@usersbp.cli.command('create')
@click.argument('name')
def create(name):
    """ Creates a user """
    print("Create user: {}".format(name))

执行flask users后,您应该得到如下响应:

flask users
Usage: flask users [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  create  Creates a user

答案 2 :(得分:1)

我有这样的布局:

baseapp.py

from flask import Flask

app = Flask("CmdAttempt")

app.py

from .baseapp import app

def main():
    app.run(
        port=5522,
        load_dotenv=True,
        debug=True
    )

if __name__ == '__main__':
    main()

commands.py

import click

from .baseapp import app


@app.cli.command("create-super-user")
@click.argument("name")
def create_super_user(name):
    print("Now creating user", name)


if __name__ == '__main__':
    from .app import main
    main()

在运行命令的控制台中,首先将FLASK_APP定义为commands.py,然后运行定义的命令。

set FLASK_APP=commands.py
export FLASK_APP=commands.py
flask create-super-user me

您可以对内置命令使用单独的终端,也可以在发出命令之前清除FLASK_APP变量。在Linux中甚至更容易,因为您可以做到

FLASK_APP=commands.py flask create-super-user me

答案 3 :(得分:1)

如果您没有使用类似于@quester 的应用工厂模式,什么对我有用:

app.py

import os

from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv("DATABASE_URL")
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
migrate = Migrate(app, db)

with app.app_context():
    # needed to make CLI commands work
    from commands import *

commands.py

from app import app

@app.cli.command()
def do_something():
    print('hello i am so nice I posted this even though I have 100 other things to do')

答案 4 :(得分:1)

如果您使用的是应用工厂(您有一个 create_app() 函数),那么甚至没有一个 app 变量可供您导入。

保持代码井井有条的最好方法是在其他地方定义函数,然后在构建应用程序实例时注册它。

例如

my_app/
 | main.py
 | app/
 |  | __init__.py
 |  | commands.py

commands.py

def foo():
   print("Running foo()")

init.py

def create_app():
 app = Flask(__name__)
 ...
 from .commands import foo
 @app.cli.command('foo')
 def foo_command():
   foo()
 ...