La creación de comandos personalizados en el matraz necesita acceso a la aplicación, que generalmente se crea en app.py de esta manera:
import click from flask import Flask app = Flask(__name__) @app.cli.command("create-user") @click.argument("name") def create_user(name): ... Sin embargo, para no inflar mi app.py, quiero poner mis comandos personalizados en un archivo separado, por ejemplo, commands.py , pero esto no funciona porque el punto de entrada a mi proyecto es app.py , así que tendré para importar la aplicación en commands.py e importar mis comandos en app.py , lo que da como resultado un error de importación circular.
¿Cómo puedo crear comandos personalizados en archivos separados?
Una forma de lograr esto sería usando planos
Lo probé usando Flask 1.1.1, así que asegúrese de revisar la documentación de la versión correcta que tiene.
Esta es la idea general:
==> aplicación.py <==
from flask import Flask from commands import usersbp app = Flask(__name__) # you MUST register the blueprint app.register_blueprint(usersbp)==> comandos.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)) Al ejecutar flask users , debería obtener una respuesta como la siguiente:
flask users Usage: flask users [OPTIONS] COMMAND [ARGS]... Options: --help Show this message and exit. Commands: create Creates a usersolo impórtalo en tu fábrica de aplicaciones
dir tree my_app L app.py L commands.pycomandos.py
@app.cli.command('resetdb') def resetdb_command(): """Here info that will be shown in flask --help""" passapp.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 resetdbpero tiene que haber una mejor manera;) de la cual no estoy al tanto en este momento
Tengo este diseño:
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()comandos.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() En la consola donde ejecuta los comandos, primero defina FLASK_APP para que sea commands.py , luego ejecute los comandos que defina.
set FLASK_APP=commands.py export FLASK_APP=commands.py flask create-super-user me Puede usar un terminal separado para los comandos integrados o borrar la variable FLASK_APP antes de emitirlos. En Linux es aún más fácil porque puedes hacer
FLASK_APP=commands.py flask create-super-user meLo que funcionó para mí en caso de que no esté utilizando el patrón de fábrica de aplicaciones, similar a @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 *comandos.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')Si está utilizando una fábrica de aplicaciones (tiene una función create_app() ), entonces ni siquiera hay una variable de app para importar.
La mejor manera de mantener su código organizado es definir la función en otro lugar y luego registrarla al crear la instancia de la aplicación.
P.ej
my_app/ | main.py | app/ | | __init__.py | | commands.pycomandos.py
def foo(): print("Running foo()")iniciar .py
def create_app(): app = Flask(__name__) ... from .commands import foo @app.cli.command('foo') def foo_command(): foo() ...