Flask SQLAlchemy设置动态URI [英] Flask SQLAlchemy setup dynamic URI

查看:171
本文介绍了Flask SQLAlchemy设置动态URI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Flask应用程序,在WSGI下数据库URI随时间变化。每两个小时URI切换到另一个数据库。我正在使用这段时间来填充一个数据库,而另一个正在为应用程序提供数据。



我很难弄清楚如何最好地配置会话,以便在发生切换时,客户端将在下一个请求中获得正确的(不同的)数据库。从我的测试来看,如果我在顶层初始化数据库,当发生切换时,客户端仍然指向旧数据库。

我曾经想过在页面(索引等等)中设置会话本身,但是真是痛苦,然后我担心会打开和关闭太多的数据库连接,让他们躺在附近。我想我可以通过在启动时初始化两个会话,然后在每个页面内切换时选择使用哪一个来工作。这似乎是效率低下,我敢肯定有更好的办法。



帮助?!



~~~ ~~~~~~



这是我目前正在做什么的一般想法,但是没有办法改变请求之间的URI。如果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
$ b $ def init_db(uri,** kwargs):
engine = create_engine(uri,** kwargs)

Base.metadata.create_all(bind = engine)
$ b $ 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(例外=无):
db_session.remove()

@ app.route('/')
def index():
...等等...

工作示例 - 美丽。

  app = Flask(__ name__)
app.c onfig ['SQLALCHEMY_DATABASE_URI'] =mysql:// foo:poo @ localhost:3306 /%s
$ b $ class SessionManager(object):
def __init __(self,base_uri = None, ** kwargs):
self.session = None
self.base_uri = base_uri
self.kwargs = kwargs
$ b $ def get_session(self):
如果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

如果不是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_ma nager = SessionManager(base_uri = app.config ['SQLALCHEMY_DATABASE_URI'],pool_recycle = 3600)

db_session = LocalProxy(session_manager.get_session)


解决方案

您可以为会话创建一个自定义构建器,以便在您的规则指定它时重新创建引擎和范围会话。类似于

  class SessionManager(object):
$ b $ def __init __(self):
self.session = None
$ b $ 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)


I have a Flask app served up under WSGI where the database URI changes over time. Every two hours the URI toggles to another database. I'm using that time to fill up one database while the other is serving up data for the app.

I'm having a hard time figuring out how best to configure the session so that when the switchover happens, the clients will get the correct (different) database on their next request. From my testing, if I initialize the database at the top level, when the switchover happens, the clients are still left pointing to the old database.

I thought about setting up the session inside the pages (index, etc) themselves, but what a pain, and then I worry about opening and closing too many database connections and leaving them lying around. I think I could probably make it work by initializing both sessions at startup, and then just choosing which to use at the switchover inside each page. It seems inefficient and I'm sure there is a better way.

Help?!

~~~~~~~~~

This a general idea of what I'm currently doing, but there is no way to change the URI between requests. The top level code is run only once, or every so often.

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...

Working example - Beautiful.

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)

解决方案

You can make a custom builder for the session that will re-create the engine and scoped session when your rules dictate it. Something like

class SessionManager(object):

    def __init__(self):
        self.session = None

    def get_session(self):
        # return existing session or make a new engine and scoped_session

To make this class transparent, use Werkzeug's LocalProxy. The code that uses the sessions won't have to change at all.

session_manager = SessionManager()
db_session = LocalProxy(session_manager.get_session)

这篇关于Flask SQLAlchemy设置动态URI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆