gpt4 book ai didi

python - 使用sqlalchemy加载动态关系类

转载 作者:太空宇宙 更新时间:2023-11-04 06:11:19 24 4
gpt4 key购买 nike

我有一个动态加载类的库。它被暴露为

mylib.registry.<className>

registry 是一个类的实例,它包含类名(字符串)到模块名的字典,以及一个在需要时动态加载类的 getattr 调用。因此,用户可以引用任何类,而不必处理模块位置(类名有一个全局命名空间,但模块名没有)。

例如,条目:

{'X', 'mylib.sublib.x',
'Y', 'mylib.sublib.y'}

然后可以这样使用:

import mylib

x = mylib.registry.X()
y = mylib.registry.Y()

这就是背景。最重要的是,这些对象是彼此有关系的 sqlalchemy ORM 类。假设 X 与 Y 之间存在一对多关系。

因此假设这个定义。

class X(Base):
y_id = Column(Integer, ForeignKey('y.id'))
y = relationship('Y')

class Y(Base):
xs = relationship('X')

这些在单独的文件中,每个文件都导入顶级注册表。

那么问题来了——我如何在不预先加载每个类的情况下真正解决这个问题?

上面的示例不起作用,因为如果我通过注册表仅导入 X,则 Y 不在 sqlalchemy 类注册表中,因此关系中断。

如果我导入注册表本身,然后直接引用类,那么由于相互依赖性,模块不会加载。

我尝试使用 lambda 来延迟加载,但这也失败了,并出现有关缺少“策略”的错误。

其他人在这里使用了哪些方法?如果我遗漏了一些明显的东西,请告诉我。这是漫长的一天。

谢谢。

最佳答案

您永远不应该在彼此不了解的两侧使用关系。通常,这可以通过使用 backref 来避免,但在您的情况下,这会产生问题,因为您希望每一方都知道自己的关系。这里的技巧是 back_populates 关键字,由 relationship 提供。 :

y = relationship("Y", back_populates="xs")

xs = relationship("X", back_populates="y")

应用这些将使他们了解彼此。但是,它不会解决您的导入问题。通常,您现在可以在Yfrom x import X。但反之则行不通,因为它会创建循环导入。

技巧很简单:将导入放在您要导入的类之后。因为 relationship 中的字符串是延迟计算的,所以您可以在定义关系后 导入类。所以对于 X 这样做:

class X(Base):
__tablename__ = 'x'
id = Column(Integer, primary_key=True)
y_id = Column(ForeignKey('y.id'))
y = relationship("Y", back_populates="xs")

from y import Y

对于 Y 也是如此(这不是必需的,但会产生更多的对称性)。我还会在那里发表评论来解释这一点,以避免有人将其置于顶部,从而破坏程序。

关于python - 使用sqlalchemy加载动态关系类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18622255/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com