这种关系需要多个关联表吗?

时间:2012-01-09 02:20:51

标签: python sqlalchemy associations relationship

我正试图找到构建将许多常量映射到多个项目的关系的最佳方法。

我的初始关系,一个项目有一个常量,看起来像这样。

class Constant(Base):
    __tablename__ = "Constant"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constantId = Column(Integer, ForeignKey("Constant.id"))
    constant = relationship("Constant")

但是,我真的需要我的项目有多个常量,就像这样......

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constant1Id = Column(Integer, ForeignKey("Constant.id"))
    constant1 = relationship("Constant")
    constant2Id = Column(Integer, ForeignKey("Constant.id"))
    constant2 = relationship("Constant")

我的第一次尝试是使用关联表...

item_to_constant_assoc = Table("itemToConstantAssoc", Base.metadata, Column("constantId", Integer, ForeignKey("Constant.id"), Column("itemId", Integer, ForeignKey("Item.id")))

同时更新Item类:

Class Item(Base):
__tablename__ = "Item"
id = Column(Integer, primary_key=True, autoincrement=True)
constant1 = relationship("Constant", secondary=item_to_constant_assoc, uselist=False)
constant2 = relationship("Constant", secondary=item_to_constant_assoc, uselist=False)

这失败了(当查看创建的MySQL表时可以理解)因为Item.constant1和Item.constant2引用了关联表中的相同条目。

我的下一步是为第二个常量添加另一个关联表,但我不得不想知道我是否正在咆哮错误的树,因为我似乎正在为相对简单的映射创建大量表。我已经阅读了文档。这是详细而实质的(感谢Michael Bayer!),我可能只是忽略了一个部分。任何人都可以向我提供这个问题的一些指示,或者我应该在文档中寻找什么?

谢谢! 菲尔

2 个答案:

答案 0 :(得分:2)

无法看到树木。这可以通过在关系上使用primaryjoin参数轻松完成。

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    constant1Id = Column(Integer, ForeignKey("Constant.id"))
    constant1 = relationship("Constant", primaryjoin="Constant.id==Item.constant1Id")
    constant2Id = Column(Integer, ForeignKey("Constant.id"))
    constant2 = relationship("Constant", primaryjoin="Constant.id==Item.constant2Id")

答案 1 :(得分:1)

多对多关联已经允许每个Item具有无限数量的常量。除了这两个基本表之外,你不需要任何其他东西。

class Constant(Base):
    __tablename__ = "Constant"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)

class Item(Base):
    __tablename__ = "Item"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(64), nullable=False)    

item_to_constant_assoc = Table("itemToConstantAssoc", Base.metadata, Column("constantId", Integer, ForeignKey("Constant.id"), Column("itemId", Integer, ForeignKey("Item.id")))

此时,每个Item都有无限数量的常量。如果需要特定常量,则必须通过Constant表中的name属性查询常量。您的关联表只是密钥对的列表:(itemID,constantId)。

Item的所有Constants的集合是一个三表连接,用于为给定Item连接匹配Constant行的所有关联行。

Constant的所有Items的集合是一个三表连接,用于所有关联行连接以及给定Constant的匹配Item行。

需要通过连接检索项的特定常量。您可以将其视为给定Item的所有常量集,其中包含Item和Constant名称。即使只检索了一行,SQL也会涉及连接。

我认为将常量与所有相关项或具有所有相关常量的项相关联的通用查询将看起来像这样。

  query(Item). join(item_to_constant_assoc.itemId==Item.itemId). join(item_to_constant_assoc.contantId==Constant.constantId