【问题标题】:Flask SQLAlchemy setup dynamic URIFlask SQLAlchemy 设置动态 URI
【发布时间】:2013-01-07 15:19:26
【问题描述】:

我在 WSGI 下提供了一个 Flask 应用程序,其中数据库 URI 会随着时间而变化。每两个小时,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)

【问题讨论】:

    标签: python sqlalchemy flask uri


    【解决方案1】:

    您可以为会话创建一个自定义构建器,该构建器将在您的规则规定时重新创建引擎和范围会话。类似的东西

    class SessionManager(object):
    
        def __init__(self):
            self.session = None
    
        def get_session(self):
            # return existing session or make a new engine and scoped_session
    

    要使此类透明,请使用Werkzeug's LocalProxy。使用会话的代码根本不需要更改。

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

    【讨论】:

    • 这太棒了。实际上,我在使用 LocalProxy 会话提交数据库时遇到了一些问题,但在我的情况下,这真的无关紧要。我对会话生命周期的了解并不完整,所以我仍在努力解决一些问题,但似乎这是要走的路。
    • 我认为我的问题是我只是在每次调用 db_session 时盲目地返回一个新的 db_session。因此,当我执行 db_session.add() 和 db_session.commit() 时,它们是两个不同的会话,因此在不同的会话上调用了提交。如果已经设置,则需要返回相同的会话。有道理。
    • 谢谢,jd。那就是炸弹。
    猜你喜欢
    • 2019-10-11
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 2019-07-15
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多