如何使用SQLAlchemy在Flask应用程序中初始化Postgresql数据库



Flask教程(以及许多其他教程(建议enginedb_sessionBase(declarative_metadata的实例(都是在导入时创建的。

这会产生一些问题,其中之一是DB的URI在代码中被硬编码,并且只计算一次。一种解决方案是将这些调用封装在接受app作为参数的函数中,这就是我所做的。请注意,每次调用都会将结果缓存在app.config:中

def get_engine(app):                                                                           
"""Return the engine connected to the database URI in the config file.
Store it in the config for later use.
"""
engine = app.config.setdefault(
'DB_ENGINE', create_engine(app.config['DATABASE_URI'](), echo=True))
return engine                                                                              
                         
def get_session(app):                                                                          
"""Return the DB session for the database in use
Store it in the config for later use.
"""                          
engine = get_engine(app)
db_session = app.config.setdefault(
'DB_SESSION', scoped_session(sessionmaker(
autocommit=False, autoflush=False, bind=engine)))
return db_session
                         
def get_base(app):                     
"""Return the declarative base to use in DB models.
Store it in the config for later use.
"""                                                                                        
Base = app.config.setdefault('DB_BASE', declarative_base())
Base.query = get_session(app).query_property()
return Base                                

init_db中,我调用了所有这些函数,但仍然有代码气味:

def init_db(app):
"""Initialise the database"""
create_db(app)
engine = get_engine(app)
db_session = get_session(app)
base = get_base(app)
if not app.config['TESTING']:
import flaskr.models
else:
if 'flaskr.models' not in sys.modules:
import flaskr.models
else:
import flaskr.models
importlib.reload(flaskr.models)
base.metadata.create_all(bind=engine)

气味当然是我进口和创建所有模型所必须经历的困难。上面代码的原因是,在单元测试时,每次测试都会调用init_db一次(在setup()中,如同一教程中所建议的(,但导入将仅在第一次执行,因此create_all仅在该次起作用。

不仅如此,现在有了在应用程序期间共享的会话,我在参数化负单元测试(即预期某种失败的参数化单元测试(中遇到了问题:测试的第一个实例将触发失败(例如登录失败,请参阅教程中的test_login_validate_input(并正确退出,而所有后续的将提前退出,因为CCD_。很明显,DB初始化有问题。

初始化数据库的正确方法(TM(是什么?

我最终决定重构应用程序,使其使用Flask SQLAlchemy。

简而言之,该应用程序现在做的事情是这样的:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
db.init_app(app)
# ...

事后看来,这绝对是一种更清洁的方法。一开始让我反感的是教程中的这个条目(粗体是我的(:

因为SQLAlchemy是一个常见的数据库抽象层和对象关系映射器,需要一点配置工作,所以有一个Flask扩展可以为您处理这一问题如果您想快速入门,建议您这样做

我不知怎么读成了";使用Flask SQLAlchemy扩展将允许您节省一些成本,您可能会在以后为此付出代价;。

这还处于早期阶段,但到目前为止,在使用上述扩展的灵活性方面还没有付出代价。

最新更新