在SqlAlchemy中__init__的一致性应用

3 投票
2 回答
1766 浏览
提问于 2025-04-16 22:35

假设我有这样的代码:

class Tab(Base):
  a = 'a'
  b = 'b'
  c = 'c'

  def __init__(self):
    self.c_a = DBSession.query(Table2).filter(Table2.a == self.a).all()

看起来 self.c_a 只对我插入的项目有效。我想确保在 __init__ 中指定的操作(这只是一个例子,可能通过 relationship() 做会更好,但请发挥你的想象力)能应用到所有对象上,包括那些从我的数据库中查询出来的对象。有没有人知道该怎么做?

我觉得我可能有些误解,如果是这样请纠正我。

2 个回答

1

你说得对,当使用SA会话加载对象时,__init__这个初始化方法不会被调用。
如果你想在其他情况下也执行代码,可以使用实例事件。我觉得在你的情况下,load特别有用,但refresh也可能会引起你的兴趣。

5

在模型内部直接引用数据库,这是一种抽象泄漏;模型不应该了解它们可能存储在哪种持久化方式的细节。其实,它们可能根本就不是持久的(毕竟,它们是模型,可能用于任何计算)。

当你想要和其他实体建立关联时,应该始终使用 relationship(),这个方法无论底层是否有持久化存储都能正常工作。而且,当你使用 SQLAlchemy 进行动态生成查询时,关系非常有用;在模型方法中执行查询并不允许这种灵活性。

如果你确定需要在模型层操作会话(而不是通常应该在控制器层操作),那么你绝对 不应该 使用全局的 Session 实例;应该始终从对象本身计算会话:

class MyModel(Base):
    def frobnicate(self):
        session = sqlalchemy.orm.Session.object_session(self)
        if session is None:
            raise ValueError("not connected to a session")
        session.query(...)

撰写回答