Python SQLAlchemy设置动态URI
我在WSGI下提供了一个Flask应用程序,其中数据库URI随时间变化。URI每两小时切换到另一个数据库。我正在利用这段时间填充一个数据库,而另一个正在为应用程序提供数据 我很难弄清楚如何最好地配置会话,以便在发生切换时,客户端在下一个请求时获得正确的(不同的)数据库。根据我的测试,如果我在顶层初始化数据库,当切换发生时,客户端仍然指向旧数据库 我曾考虑在页面(索引等)内部设置会话,但这是一件多么痛苦的事情,然后我担心打开和关闭太多数据库连接,而让它们到处乱跑。我想我可以在启动时初始化两个会话,然后在每个页面内的切换中选择要使用的会话。这似乎效率低下,我相信还有更好的办法 救命啊 ~~~~~~~~~ 这是我目前正在做的事情的基本概念,但是没有办法在请求之间更改URI。顶层代码只运行一次,或者每隔一段时间运行一次Python SQLAlchemy设置动态URI,python,sqlalchemy,flask,uri,Python,Sqlalchemy,Flask,Uri,我在WSGI下提供了一个Flask应用程序,其中数据库URI随时间变化。URI每两小时切换到另一个数据库。我正在利用这段时间填充一个数据库,而另一个正在为应用程序提供数据 我很难弄清楚如何最好地配置会话,以便在发生切换时,客户端在下一个请求时获得正确的(不同的)数据库。根据我的测试,如果我在顶层初始化数据库,当切换发生时,客户端仍然指向旧数据库 我曾考虑在页面(索引等)内部设置会话,但这是一件多么痛苦的事情,然后我担心打开和关闭太多数据库连接,而让它们到处乱跑。我想我可以在启动时初始化两个会话,
if now.hour % 2:
db_name = 'db1'
else:
db_name = 'db2'
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://foo:poo@localhost:3306/%s" % db_name
def init_db(uri, **kwargs):
engine = create_engine(uri, **kwargs)
Base.metadata.create_all(bind=engine)
global db_session
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
Base.query = db_session.query_property()
init_db(app.config['SQLALCHEMY_DATABASE_URI'], pool_recycle=3600)
@app.teardown_request
def shutdown_session(exception=None):
db_session.remove()
@app.route('/')
def index():
...etc...
工作示例-美丽
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://foo:poo@localhost:3306/%s"
class SessionManager(object):
def __init__(self, base_uri=None, **kwargs):
self.session = None
self.base_uri = base_uri
self.kwargs = kwargs
def get_session(self):
if now.hour % 2:
db_name = 'db1'
else:
db_name = 'db2'
if self.session:
if self.session.name == db_name:
return self.session
else:
self.session.remove()
self.session = None
if not self.session:
engine = create_engine(self.base_uri % db_name, **self.kwargs)
db_session = scoped_session(sessionmaker(bind=engine))
db_session.name = db_name
self.session = db_session
return db_session
session_manager = SessionManager(base_uri=app.config['SQLALCHEMY_DATABASE_URI'], pool_recycle=3600)
db_session = LocalProxy(session_manager.get_session)
您可以为会话创建一个自定义生成器,当您的规则规定时,该生成器将重新创建引擎和作用域会话。差不多
class SessionManager(object):
def __init__(self):
self.session = None
def get_session(self):
# return existing session or make a new engine and scoped_session
要使此类透明,请使用。使用会话的代码根本不需要更改
session_manager = SessionManager()
db_session = LocalProxy(session_manager.get_session)
这真是太棒了。实际上,我在使用LocalProxy会话提交数据库时遇到了一些问题,但在我的情况下,这并不重要。我对会话生命周期的了解还没有达到应有的程度,因此我仍在努力解决一些问题,但似乎这是一条出路。我认为我的问题是,我只是在每次调用db_会话时盲目地返回一个新的db_会话。因此,当我执行db_session.add()和db_session.commit()时,它们是两个不同的会话,因此在不同的会话上调用commit。如果已设置,则需要返回相同的会话。有道理。谢谢你,jd。那是炸弹。