python - meaning - Al dispersar modelos de matraz, RuntimeError: ''aplicación no registrada en db'' se planteó
flask wikipedia (2)
Estoy refaccionando mi aplicación Flask diseminando los modelos, planos, pero estoy teniendo un error de tiempo de ejecución.
def create_app():
app = flask.Flask("app")
app.config[''SQLALCHEMY_DATABASE_URI''] = ''sqlite://''
app.register_blueprint(api)
db.init_app(app)
db.create_all()
return app
Tengo el siguiente problema (el proyecto de ejemplo está alojado aquí: https://github.com/chfw/sample ):
Traceback (most recent call last):
File "application.py", line 17, in <module>
app = create_app()
File "application.py", line 12, in create_app
db.create_all()
File "/AppData/Roaming/Python/Python27/site-packages/flask_sqlalchemy/__init__.py", line 856, in create_all
self._execute_for_all_tables(app, bind, ''create_all'')
File "/AppData/Roaming/Python/Python27/site-packages/flask_sqlalchemy/__init__.py", line 836, in _execute_for_all_tables
app = self.get_app(app)
File "/AppData/Roaming/Python/Python27/site-packages/flask_sqlalchemy/__init__.py", line 809, in get_app
raise RuntimeError(''application not registered on db
''RuntimeError: application not registered on db
instance and no application bound to current context
Hice una investigación sobre este tema. El re-factoring se sugiere aquí:
Flask-SQLAlchemy problema de importación / contexto
El mismo problema se planteó aquí:
Y el hilo anterior (2010) sugirió un truco como este:
app.register_blueprint(api)
db.app=app #<------------<<
db.init_app(app)
¿Alguien sabe cómo hacer esto correctamente? ¿Cómo lo resolvió?
Gracias
Esto tiene que ver con el contexto de la aplicación de Flask. Cuando se inicializa con db.init_app(app)
, Flask-SQLAlchemy no sabe qué aplicación es la "actual" (recuerde que Flask permite varias aplicaciones en el mismo intérprete). Podrías tener varias aplicaciones usando la misma instancia SQLAlchemy
en el mismo proceso, y Flask-SQLAlchemy necesitaría saber cuál es la "actual" (debido a la naturaleza local del contexto de Flask de todo).
Si necesita hacer esto durante el tiempo de ejecución, debe indicar explícitamente qué aplicación es la "actual" para todas las llamadas. Puedes hacer esto cambiando tu código para usar un with app.app_context()
:
def create_app():
app = flask.Flask("app")
app.config[''SQLALCHEMY_DATABASE_URI''] = ''sqlite://''
app.register_blueprint(api)
db.init_app(app)
with app.app_context():
# Extensions like Flask-SQLAlchemy now know what the "current" app
# is while within this block. Therefore, you can now run........
db.create_all()
return app
Si está escribiendo una secuencia de comandos independiente que necesita el contexto de la aplicación, puede presionar el contexto al principio en lugar de poner todo en un bloque with
.
create_app().app_context().push()
Si escribe un comando para cli de Flask, el comando tendrá automáticamente acceso al contexto.
La respuesta de Mark fue genial y me ayudó mucho. Sin embargo, otra forma de abordar esto es ejecutar el código que se basa en el contexto de la aplicación en una función decorada con @ app.before_first_request. Ver http://flask.pocoo.org/docs/0.10/appcontext/ para más información. De hecho, así fue cómo terminé haciéndolo, en gran parte porque también quería poder llamar el código de inicialización fuera del matraz, que manejé de esta manera.
En mi caso, quiero poder probar los modelos de SQLAlchemy como modelos simples de SQLAlchemy sin Flask-SQLAlchemy, aunque la base de datos del código siguiente es simplemente un (Frasco) SQLAlchemy db.
@app.before_first_request
def recreate_test_databases(engine = None, session = None):
if engine == None:
engine = db.engine
if session == None:
session = db.session
Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
# Additional setup code