我有各种类似(但不完全相同)的数据库,并希望使用SQLAlchemy作为“标准化”访问的方式。数据库可以略有不同,例如在列名称上具有唯一的前缀,或者它们可以更加显着地区别并且缺少列(或者对于旧数据库,缺少整个表)。
我正在寻求帮助的不是SQLAlchemy问题,而是Python /组织问题。如何才能轻松设置多个可在项目中重复使用的数据库?
我已经阅读过关于SQLAlchemy会话的内容,但看不到使用这些会话的方法,而没有在每个项目中实例化每个会话。
我的问题是:如何制作一个模块/包,其中包含许多数据库模型设置,可以在SQLAlchemy中使用,可以在另一个python项目中轻松导入/使用?
我还没有那么担心处理丢失的列/表。我可以稍后解决这个问题,但是我需要记住这个问题,因为我不能为每个数据库使用完全相同的模型。
有关此主题的任何资源,指示或阅读材料都将受到真正的赞赏。在此先感谢,如果在其他地方已经回答,我很抱歉,搜索没有显示与此有关的任何内容。
编辑:我原封不动,并根据保罗的建议添加了更多内容。
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')
。当我完成更多模型时,它们会被添加到tupples列表中。这允许我随时添加或删除内容。
我在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如何工作(目前还没有)。但我走上正轨。我想我会为那些偶然想知道如何做同样事情的人更新这个。
对不起,这已经太久了!
干杯!
答案 0 :(得分:7)
根据我最初提问的要求,我已经进行了第三次编辑并将其作为答案。由于我不确定正确的协议,我已经在上面留下了第三个编辑。如果您已经阅读过EDIT3,那么您已经阅读了我的答案。
我已经设法花了更多的时间在这上面。我按以下方式设置了项目:
Databases
__init__.py
databases.py
settings.py
DB1
__init__.py
models.py
...
DB3
__init__.py
models.py
目前,我在settings.py文件中有一个“已安装”的数据库。每个条目都像INSTALLED_DATABASES = ('DB1', ..., 'DB3')
。当我完成更多模型时,它们会被添加到tupples列表中。这允许我随时添加或删除内容。
我在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如何工作(目前还没有)。但我走上正轨。我想我会为那些偶然想知道如何做同样事情的人更新这个。
对不起,这已经太久了!
干杯!
答案 1 :(得分:3)
你的解决方案看起来很不错。这就是我所做的。
我有一个名为connectors的包,其中包含每个数据库的模块以及设置文件。
每个连接器模块都会创建其连接字符串及其引擎,以及表的声明性基础和类。
然后有一个方法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(...)