【发布时间】:2018-07-21 21:02:35
【问题描述】:
前提:我有很多 表必须单独创建(它们不能动态创建),因此,我发现自己经常需要制作允许相关表的标准化:
class A_Table(Base):
id = Column(Integer, primary_key=True)
class A_Relator(My_Mixin_Base):
@declared_attr
def a_table_id(cls):
return Column(ForeignKey(A_Table.id))
@declared_attr
def a_table(cls):
return relationship(A_Table)
class B_Table(A_Relator, Base):
id = Column(Integer, primary_key=True)
class C_Table(A_Relator, Base):
id = Column(Integer, primary_key=True)
class D_Table(A_Relator, Base):
id = Column(Integer, primary_key=True)
# ad nauseam
很简单,但是当B_Table、C_Table 等都有自己的 Relator 类时,它会变得非常重复,因此应该很容易在代码中解决。
我的解决方案:我创建了一个类工厂 (?),它创建了一个一次性使用的 mixin 类。
def related(clss, defined=False, altName=None):
class X((Definer if defined else Relator),):
linkedClass = clss
@classmethod
def linkedClassFieldName(cls):
return "{}Id".format(clss.getBackrefName())
def linkId(cls):
return Column(ForeignKey(clss.id))
def linkRe(cls):
return relationship(clss,
foreign_keys=getattr(cls, "{}Id".format(clss.getBackrefName() if not altName else altName)),
backref=cls.getBackrefName())
setattr(X, "{}Id".format(clss.getBackrefName() if not altName else altName), declared_attr(X.linkId))
setattr(X, "{}".format(clss.getBackrefName() if not altName else altName), declared_attr(X.linkRe))
del X.linkId
del X.linkRe
return X
这允许您执行以下操作并完成它:
class B_Table(related(A_Table), Base):
id = Column(Integer, primary_key=True)
...但这很混乱且令人困惑,我想有一种更好的方法可以做到这一点,从而减少不确定性。
问题:我正在寻找一种方法,以一种更直接的 SQLAlchemy 对齐方式来执行此操作,同时减少迂回的“hack”。或者总结一下:我如何制作一个生成关系的通用 SQLAlchemy mixin?
【问题讨论】:
-
嗨。在您的第一个示例代码块中,
A_Relator类中的ForeignKey和relationship被定义回您的A_Table模型,对吗?在您的示例代码中,它们与未定义的模型A相关。 -
@SuperShoot 是的,对不起,你是对的。
标签: python-3.x orm sqlalchemy factory