2

如何让相关的 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 的包的惯用高级组织是什么样的?

4

1 回答 1

0

我认为这实际上是 Python 成语的问题,而不是 SQLAlchemy 成语的问题。根据 Guido Van Rossum 的说法,在包中运行脚本是一种反模式(zzeek 在评论中暗示了这一点)。所以 a.py、b.py 和 c.py 不应该有if __name__ == '__main__'块。

于 2013-01-21T23:04:03.330 回答