我有一个 Flask 应用程序需要在启动时运行代码。就我而言,它会检测可用的云资源并将其写入数据库中的表中。
问题是,当我运行
flask db upgrade
时,flask-migrate会执行应用程序启动代码,包括尝试写入数据库表的代码。由于迁移本身就是创建表的过程,因此该表还不存在,迁移失败。
这是代码,删除了不相关的部分:
def create_app():
app = Flask(__name__, static_url_path=None)
with app.app_context():
db = set_up_database_connection()
Migrate(app, db)
# This is what fails because the table doesn't exist yet
run_startup_tasks()
@app.get('/')
def health_check():
return 'OK'
app.logger.info("Application created.")
return app
我使用
@app.before_first_request
注释做了一个临时解决方法。通过解决方法,启动代码将在第一个请求通过之前运行。但这并不理想,因为这会导致对应用程序的第一个请求需要很长时间。
@app.before_first_request
def perform_startup_tasks():
run_startup_tasks()
如何在不破坏flask-migrate的情况下运行需要数据库的启动任务?
我最终通过创建一个单独的文件来解决这个问题,该文件运行启动任务:
app = Flask(__name__, static_url_path=None)
with app.app_context():
db = set_up_database_connection()
run_startup_tasks()
此文件在主应用程序运行之前和迁移运行之后运行:
flask db upgrade && python run_startup_tasks.py && flask run
这解决了问题,因为主应用程序(flask-migrate 使用的)不运行启动任务。它在单独的脚本中运行。
可能会稍晚一些,但如果有人需要另一个解决方案:如
sys.argv
是一个 list[str]
,其中包含用于执行应用程序的所有命令行参数,您只需测试命令名称即可确定它是否已运行、迁移、升级或其他任何操作:
include sys
# This will always execute
print("hello world")
if not 'run' in sys.argv:
# This will not execute when 'flask run ...' is used
print("not run")
if not 'upgrade' in sys.argv:
# This will not execute when 'flask db upgrade' is used
print("not upgrade")