【问题标题】:Pattern for a Flask App using (only) SQLAlchemy Core使用(仅)SQLAlchemy Core 的 Flask 应用程序模式
【发布时间】:2014-03-03 20:37:53
【问题描述】:

我有一个我想使用 SQLAlchemy Core 的 Flask 应用程序(即我明确想要使用 ORM),类似于 Flask 文档中描述的“第四种方式” :

http://flask.pocoo.org/docs/patterns/sqlalchemy/#sql-abstraction-layer

我想知道推荐的模式是什么:

  1. 如何连接到我的数据库(我可以简单地将connection 实例存储在g.db 变量中,在before_request 中吗?)

  2. 如何执行反射以检索现有数据库的结构(如果可能,我希望避免显式创建任何“模型/表类”)

【问题讨论】:

    标签: python sqlalchemy flask


    【解决方案1】:
    1. 正确:您将为每个线程创建一次连接并使用线程局部变量访问它。像往常一样,SQLAlchemy 已经想到了这个用例并为您提供了一个模式:Using the Threadlocal Execution Strategy

      db = create_engine('mysql://localhost/test', strategy='threadlocal')
      db.execute('SELECT * FROM some_table')
      

      注意:如果我没记错的话,这个例子似乎混淆了dbengine 的名称(我认为应该也是db)。

      我认为您可以放心地忽略文档中发布的注释,因为这正是您想要的。只要每个事务范围都链接到一个线程(就像通常的烧瓶设置一样),您就可以安全地使用它。只是不要开始弄乱无螺纹的东西(但无论如何烧瓶都会窒息)。

    2. Reflecting Database Objects 中所述,反射非常简单。由于您不想手动创建所有表,SQLAlchemy 也提供了一个不错的方法:Reflecting All Tables at Once

      meta = MetaData()
      meta.reflect(bind=someengine)
      users_table = meta.tables['users']
      addresses_table = meta.tables['addresses']
      

      我建议您查看有关反思的完整章节。

    【讨论】:

    • 谢谢,这很有用。你知道把这段代码放在哪里吗? This answer 提供了一种可能的方式,它似乎可以满足我想要做的事情。
    • 其实我只是在应用程序启动的时候做。这样,一旦您的应用程序运行,您就知道一切都已启动,并且不会因为反射而需要更长时间的第一个请求。因此: 在导入级别定义它。然后像上面那样手动分配您的表格,或者仅在您链接的答案中的请求期间访问所需的表格。
    • 我对第 1 步有点困惑。在 OP 中,cjauvin 建议从引擎获取连接并将其存储在 g 对象上。即 @app.before_request def before_request(): g.db = engine.connect() 并在整个请求中使用它。这与使用“threadlocal”策略创建引擎相同吗?还是两者都需要?
    • 基本上是的,主要是因为烧瓶严重依赖于每个请求都有一个线程的假设。如果您要更改它并且每个线程有多个请求(以任何方式实现此目的),您会希望更喜欢不依赖线程局部变量(即事件、回调等)的东西。
    • 我认为您不需要使用线程本地模式创建引擎。 g 对象已经是线程本地的。在before_request 中,您可以创建一个新连接并将其添加到g。在您的路线内,您可以执行g.conn.execute(select([Foo]))。然后在after_request 你可以发出g.conn.close()。你同意吗?
    猜你喜欢
    • 1970-01-01
    • 2020-09-26
    • 2015-06-16
    • 2013-07-21
    • 1970-01-01
    • 2018-07-20
    • 2021-04-29
    • 2018-09-02
    • 1970-01-01
    相关资源
    最近更新 更多