【问题标题】:SQLAlchemy and Multiple DatabasesSQLAlchemy 和多个数据库
【发布时间】:2013-03-07 15:58:55
【问题描述】:

我有各种相似(但不相同)的数据库,并希望使用 SQLAlchemy 作为“标准化”访问的一种方式。数据库可能略有不同,例如在列名上具有唯一前缀,或者它们可能差异更大并​​且缺少列(或者对于旧数据库,缺少整个表)。

我正在寻求帮助的不是 SQLAlchemy 问题,而是 Python/组织问题。我怎样才能有多个可以在项目中轻松重用的数据库设置?

我已经阅读了有关 SQLAlchemy 会话的信息,但是如果不在每个项目中实例化每个会话,就看不到使用这些会话的方法。

我的问题是:如何制作一个模块/包,其中包含许多要在 SQLAlchemy 中使用的数据库模型设置,这些设置可以很容易地在另一个 python 项目中导入/使用?

到目前为止,我还不太担心处理丢失的列/表。我可以稍后解决这个问题,但需要牢记这一点,因为我不能为每个数据库使用完全相同的模型。

任何有关此主题的资源、指针或阅读材料都将不胜感激。提前致谢,如果这已在其他地方得到解答,我很抱歉,搜索没有显示与此相关的任何内容。

编辑:我原封不动地保留了原版,并根据 Paul 的建议添加了更多内容。

RE: SA ORM - 是的,我打算使用 SQLAlchemy ORM。由于可能显而易见的原因,我无法提供真实的数据库。然而,假设这三个虚构的数据库,恰当地命名为 DB1、DB2 和 DB3(我们将假设每个数据库中只有一个表,只有几列,现实世界中两者的数量会多得多)。

每个数据库都有一个用户表,每个表中都有几列。以下是表/列的一些 SQL 表示法:

DB1.user  --> DB1.user.id,      DB1.user.username,  DB1.user.email
DB2.user  --> DB2.user.id,      DB2.user.user_name, DB2.user.email
DB3._user --> DB3._user.userid, DB3._user.username, DB3.user.email_address

目前,我正在尝试将这些数据库分离为“模块化”,并且可以随时添加其他数据库。

我考虑了几个不同的文件组织方面(假设 __init__.py 在需要的地方存在,但为简洁起见省略),包括:

Databases         |    Databases            |    Databases
    DB1.py        |        DB1              |        DB1
    DB2.py        |            models.py    |            models
    DB3.py        |        DB2              |                user.py
                  |            models.py    |                anothertable.py
                  |        DB2              |        ...
                  |            models.py    |        DB3
                  |                         |            models
                  |                         |                user.py
                  |                         |                anothertable.py

我希望能够使用 SA ORM 访问这些数据库,并且在需要在 python 文件中使用这些数据库时尽可能少地导入/声明。需要做类似的事情:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from Database import DB1, ..., DB[N]
db1_engine = create_engine('connect_string/db1')
db1_session = sessionmaker(bind=db1_engine)()
...
db3_engine = create_engine('connect_string/db3')
db3_session = sessionmaker(bind=db3_engine)()

会非常麻烦,因为我要处理的不仅仅是三个数据库。我宁愿已经为我处理好了(在 __init__.py 文件中,也许?)

能够访问和使用它类似于:

import Databases

Databases.DB1.session.query('blahblah')

会更好。

EDIT2:我还知道在设置模型时如何绕过数据库/列命名约定中的变体。这不是问题,但我确实提到了它,以便知道我不能只为多个数据库使用一个模型集。

我希望通过扩展这个我没有弄混水或让这个太混乱。感谢您花时间阅读!

EDIT3:我已经设法在这方面多花一点时间。我通过以下方式设置了项目:

Databases
    __init__.py
    databases.py
    settings.py
    DB1
        __init__.py
        models.py
    ...
    DB3
        __init__.py
        models.py

目前,我在 settings.py 文件中“安装”了一组数据库。每个条目都像INSTALLED_DATABASES = ('DB1', ..., 'DB3')。随着我完成更多模型,它们被添加到元组列表中。这让我可以随时添加或删除内容。

我在 models.py 文件中设置了引擎和 sessios,并将每个数据库设置的 init.py 文件设置为 from models import *

在 databases.py 文件中,我有以下内容

class Databases(object):
    def __init__(self):
        for database in INSTALLED_DATABASES:
            setattr(self, database, __import__(database))

我现在可以通过以下方式使用这些:

from databases import Databases

db = Databases()

for qr in db.DB1.query(db.DB1.User):
    print qr.userid, qr.username

SQLAlchemy 允许我在定义模型时手动指定列名,这对我想要的标准化来说是一个巨大的好处。

我还有很多工作要做。我想创建强制模型验证的对象(即,是否存在字段?不存在的字段是否具有默认值?等等)并更好地结合它与我的 IDE 的工作方式(目前还没有)。但我走上了正确的轨道。我想我会为任何可能想知道如何做与我相同的事情的人更新此内容。

抱歉,拖了这么久!

干杯!

【问题讨论】:

  • 我在 EDIT3 中添加了一些附加信息。我已经有点按照我想要的方式工作了,但需要继续改进它。我将不得不将这个问题延续到不同的问题中,因为原始的范围已经得到解答。所以,我不希望我会更新这个,除非我改变一些剧烈的东西,或者在它的工作方式上取得重大进展。如果有人对如何更好地做到这一点有任何建议,我会全力以赴。感谢阅读。
  • 我不确定这是否可以解决您的问题,但也许它可以为您添加一些东西。这是来自 zzeek 的帖子,在阅读您的问题时,我被部分提醒:techspot.zzzeek.org/2012/01/11/…
  • 我真诚地建议您进行最后一次编辑并将其作为答案 - 这是一个很好的答案,并且在这里回答您自己的问题会被微笑:-)
  • 我同意肖恩的观点,请这样做:)

标签: python sqlalchemy


【解决方案1】:

根据对我最初问题的要求,我已经进行了第三次编辑并将其作为我的答案。由于我不确定正确的协议,所以我将第三次编辑留在了上面。如果您已经阅读了 EDIT3,那么您已经阅读了我的答案。

我已经设法在这上面多花一点时间。我通过以下方式设置了项目:

Databases
    __init__.py
    databases.py
    settings.py
    DB1
        __init__.py
        models.py
    ...
    DB3
        __init__.py
        models.py

目前,我在 settings.py 文件中“安装”了一组数据库。每个 DB 条目都在 INSTALLED_DATABASES = ('DB1', ..., 'DB3') 中指定。随着我完成更多模型,它们被添加到元组列表中。这让我可以随时添加或删除内容。

我在models.py 文件中设置了引擎和会话,并将每个数据库的__init.py__ 文件设置为from models import *

在 databases.py 文件中,我有以下内容

class Databases(object):
    def __init__(self):
        for database in INSTALLED_DATABASES:
            setattr(self, database, __import__(database))

我现在可以通过以下方式使用这些:

from databases import Databases

db = Databases()

for qr in db.DB1.query(db.DB1.User):
    print qr.userid, qr.username

SQLAlchemy 允许我在定义模型时手动指定列名,这对我想要的标准化来说是一个巨大的好处。

我还有很多工作要做。我想创建强制模型验证的对象(即,是否存在字段?不存在的字段是否具有默认值?等等)并更好地结合它与我的 IDE 的工作方式(目前还没有)。但我走上了正确的轨道。我想我会为任何可能想知道如何做与我相同的事情的人更新此内容。

抱歉,拖了这么久!

干杯!

【讨论】:

    【解决方案2】:

    您的解决方案看起来不错。这就是我所做的。

    我有一个名为 connector 的包,其中包含一个用于每个 db 的模块以及一个设置文件。

    这些连接器模块中的每一个都创建其连接字符串和引擎,以及表的声明性基和类。

    然后有一个方法 loadSession 可以返回会话(这是我从教程或这里的另一篇文章中获得的,记不清了),还有一个我添加的方法返回引擎,以防我想用它做点什么。

    那么在程序的其他模块中,我会做这样的事情

    from connectors import x, y, z
    
    x_ses = x.loadSession()
    y_ses = y.loadSession()
    z_ses = z.loadSession()
    
    xq = x_ses.query(...)
    yq = y_ses.query(...)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-11
      • 2017-06-01
      • 2016-08-21
      相关资源
      最近更新 更多