如何让相关的 SQLAlchemy 映射类分布在不同的模块中的问题在这里出现了很多次。不过,没有一个提议的解决方案对我很有效,我很想知道这是如何正确处理的(即我不想让我的代码可运行,我想把它做对)。
我真的很喜欢这个解决方案:
基础.py
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
一个.py
from sqlalchemy import *
from base import Base
from sqlalchemy.orm import relationship
class A(Base):
__tablename__ = "A"
id = Column(Integer, primary_key=True)
Bs = relationship("B", backref="A.id")
Cs = relationship("C", backref="A.id")
b.py
from sqlalchemy import *
from base import Base
class B(Base):
__tablename__ = "B"
id = Column(Integer, primary_key=True)
A_id = Column(Integer, ForeignKey("A.id"))
py
from sqlalchemy import *
from base import Base
class C(Base):
__tablename__ = "C"
id = Column(Integer, primary_key=True)
A_id = Column(Integer, ForeignKey("A.id"))
主文件
from sqlalchemy import create_engine
from sqlalchemy.orm import relationship, backref, sessionmaker
import base
import a
import b
import c
engine = create_engine("sqlite:///:memory:")
base.Base.metadata.create_all(engine, checkfirst=True)
Session = sessionmaker(bind=engine)
session = Session()
# snip
但是,如果我希望能够对a.py 中的 A 类做一些事情,而不是定义它呢?例如
一个.py
from sqlalchemy import *
from base import Base
from sqlalchemy.orm import relationship
import main
class A(Base):
__tablename__ = "A"
id = Column(Integer, primary_key=True)
Bs = relationship("B", backref="A.id")
Cs = relationship("C", backref="A.id")
def populate_A(session):
for i in range(10):
new_A = A(id=i)
session.add(new_A)
session.commit()
if __name__ == '__main__':
session = main.Session()
populate_A(session)
这就是我想要构建我的代码的方式 - 从语义上讲, A 和 populate_A 似乎它们应该存在于同一个模块中。但显然这在上面的示例中不起作用,因为循环 a -> main -> a 导入。
所以我通常会在某处定义 A (a.py),然后在导入 main (a_functions.py ?) 的单独模块中做一些事情。或者,由于创建会话不需要导入映射类但创建表需要,我是否将这两个功能放在不同的模块中?还是我在 main.py 中做一些恶心的事情,比如
def create_tables():
import a, b, c
engine = create_engine("sqlite:///:memory:")
base.metadata.create_all(engine)
这样 a、b 和 c 仅在我需要创建表时有条件地导入,避免循环导入?
简而言之,使用 SQLAlchemy 的包的惯用高级组织是什么样的?