从 Flask 蓝图访问数据库
Access database from Flask blueprint
我正在使用 Flask 和 SQLAlchemy 构建一个 RESTful API 应用程序,并尝试应用蓝图模式来注册我的路由。蓝图@route 函数包含对数据库会话对象的引用。我希望以“代理方式”访问它 - 以一种您可以使用 app.current_app 访问 Flask.app 的方式,但我的实现不起作用。
wsgi.py:(运行 来自这里)
# imports
from wallet.walletapp import main
app = create_app(url='sqlite:///./test.db')
dbase = Database(url='sqlite:///./test.db')
db = dbase.create_session()
models.Base.metadata.create_all(bind=dbase.engine)
abort = Abort(app, db)
app.config['database'] = db
app.config['abortion'] = abort
with app.app_context:
app.register_blueprint(main)
app.run(debug=True)
walletapp.py
main = Blueprint('main', __name__)
app = current_app
db = current_app.config['database']
abort = current_app.config['abortion']
# Get wallet list
@main.route('/v1/wallets', methods=['GET'])
def get_wallets():
'''
Get all the wallets and their balances
'''
wallets = db.query(models.Wallet).all()
result = wallets_schema.dump(wallets)
resp = cook_response(app, {'wallets': result})
return resp, 200
这样我得到一个 RuntimeError: Working out of application context early - 在 wsgi.py:
的导入阶段
File "/wsgi.py", line 5, in <module>
from wallet.walletapp import main
File "/walletapp.py", line 26, in <module>
db = current_app.config['database']
File "/env/lib/python3.9/site-packages/werkzeug/local.py", line 422, in __get__
obj = instance._get_current_object()
File "/env/lib/python3.9/site-packages/werkzeug/local.py", line 544, in _get_current_object
return self.__local() # type: ignore
File "env/lib/python3.9/site-packages/flask/globals.py", line 47, in _find_app
raise RuntimeError(_app_ctx_err_msg)
这背后的想法是使 walletapp.py 作为真正的蓝图更加灵活:例如,在单元测试中轻松地将工作数据库交换为虚拟数据库。
总结:
Defining or importing database (db) inside walletapp.py makes
module unpluggable: I can work only with database imported or stated
in it. How can I rewrite my code to make it working as expected?
This question has a direct connection with mine, but answers give not mush: use Flask-SQLAlchemy or "declare the database object before the context and then import it", which I tried to implement here. I do not wish to use Flask-SQLAlchemy pattern (because of some points described in this article).
我是 Flask 的新手,所以如果问题过时、过多或错误,请多多包涵)我觉得应该有一些合理而清晰的解决方案,但无法触及它的方法。
我找到了解决办法。会 post 在这里以防有人遇到同样的问题。
首先,我这里有一个错误:
app.app_context:
我应该把上下文称为
app.app_context():
感谢 。
其次, 我应该从 wsgi.py 中导入我的路由 app.app_context():
# defining app and db
abort = Abort(app, db)
app.config['database'] = db
app.config['abortion'] = abort
with app.app_context():
from wallet import walletapp
app.register_blueprint(walletapp.main)
app.run(debug=True)
而对于 last,我重写了 walletapp.py 如下:
app = current_app
with app.app_context():
db = current_app.config['database']
abort = current_app.config['abortion']
main = Blueprint('main', __name__)
# then goes @main.routes
在此模式中,代码运行良好。
我正在使用 Flask 和 SQLAlchemy 构建一个 RESTful API 应用程序,并尝试应用蓝图模式来注册我的路由。蓝图@route 函数包含对数据库会话对象的引用。我希望以“代理方式”访问它 - 以一种您可以使用 app.current_app 访问 Flask.app 的方式,但我的实现不起作用。
wsgi.py:(运行 来自这里)
# imports
from wallet.walletapp import main
app = create_app(url='sqlite:///./test.db')
dbase = Database(url='sqlite:///./test.db')
db = dbase.create_session()
models.Base.metadata.create_all(bind=dbase.engine)
abort = Abort(app, db)
app.config['database'] = db
app.config['abortion'] = abort
with app.app_context:
app.register_blueprint(main)
app.run(debug=True)
walletapp.py
main = Blueprint('main', __name__)
app = current_app
db = current_app.config['database']
abort = current_app.config['abortion']
# Get wallet list
@main.route('/v1/wallets', methods=['GET'])
def get_wallets():
'''
Get all the wallets and their balances
'''
wallets = db.query(models.Wallet).all()
result = wallets_schema.dump(wallets)
resp = cook_response(app, {'wallets': result})
return resp, 200
这样我得到一个 RuntimeError: Working out of application context early - 在 wsgi.py:
的导入阶段 File "/wsgi.py", line 5, in <module>
from wallet.walletapp import main
File "/walletapp.py", line 26, in <module>
db = current_app.config['database']
File "/env/lib/python3.9/site-packages/werkzeug/local.py", line 422, in __get__
obj = instance._get_current_object()
File "/env/lib/python3.9/site-packages/werkzeug/local.py", line 544, in _get_current_object
return self.__local() # type: ignore
File "env/lib/python3.9/site-packages/flask/globals.py", line 47, in _find_app
raise RuntimeError(_app_ctx_err_msg)
这背后的想法是使 walletapp.py 作为真正的蓝图更加灵活:例如,在单元测试中轻松地将工作数据库交换为虚拟数据库。
总结:
Defining or importing database (db) inside walletapp.py makes module unpluggable: I can work only with database imported or stated in it. How can I rewrite my code to make it working as expected?
This question has a direct connection with mine, but answers give not mush: use Flask-SQLAlchemy or "declare the database object before the context and then import it", which I tried to implement here. I do not wish to use Flask-SQLAlchemy pattern (because of some points described in this article).
我是 Flask 的新手,所以如果问题过时、过多或错误,请多多包涵)我觉得应该有一些合理而清晰的解决方案,但无法触及它的方法。
我找到了解决办法。会 post 在这里以防有人遇到同样的问题。
首先,我这里有一个错误:
app.app_context:
我应该把上下文称为
app.app_context():
感谢
其次, 我应该从 wsgi.py 中导入我的路由 app.app_context():
# defining app and db
abort = Abort(app, db)
app.config['database'] = db
app.config['abortion'] = abort
with app.app_context():
from wallet import walletapp
app.register_blueprint(walletapp.main)
app.run(debug=True)
而对于 last,我重写了 walletapp.py 如下:
app = current_app
with app.app_context():
db = current_app.config['database']
abort = current_app.config['abortion']
main = Blueprint('main', __name__)
# then goes @main.routes
在此模式中,代码运行良好。