SQLAlchemy back_populates 具有多个关联的多对多(标记 table)

SQLAlchemy back_populates many-to-many with multiple associations (tag table)

我的问题:由于 Tag 通过关联 tables 连接到多个 tables,我会在 Tag 上为 back_populates 放置什么。 back_populates 对关联 table 是否也有必要?我不确定如何在这种情况下为 back_populates 建模。详情见下文。

我有以下 table 结构:

基本上,我可以将标签应用于源或源键。这是我的模型:

class Tag(Base):
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)

source_tag_assoc = Table('source_tag_assoc', Base.metadata,
    Column('source_id', Integer, ForeignKey('source.id')),
    Column('tag_id', Integer, ForeignKey('tag.id'))
)
class Source(Base):
    id = Column(Integer, primary_key=True, index=True)
    tags = relationship("Tag", secondary=source_tag_assoc, back_populates="source")

source_key_tag_assoc = Table('source_tag_assoc', Base.metadata,
    Column('source_id', Integer, ForeignKey('source_key.id')),
    Column('tag_id', Integer, ForeignKey('tag.id'))
)
class SourceKey(Base):
    id = Column(Integer, primary_key=True, index=True)
    tags = relationship("Tag", secondary=source_key_tag_assoc, back_populates="source_key")

back_populates 必须指向实际关系。如果您不想在两个模型上定义关系,则应改用 backref

以下是您调整模型以使用 back_populates 的方法:

class Tag(Base):
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    source = relationship('Source', secondary=source_tag_assoc, back_populates='tags')

class Source(Base):
    id = Column(Integer, primary_key=True, index=True)
    tags = relationship("Tag", secondary=source_tag_assoc, back_populates="source")
    source_key = relationship("SourceKey", secondary=source_key_tag_assoc, back_populates="tags")

class SourceKey(Base):
    id = Column(Integer, primary_key=True, index=True)
    tags = relationship("Tag", secondary=source_key_tag_assoc, back_populates="source_key")

这里切换到 backref,结果应该与上面完全相同:

class Tag(Base):
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)

class Source(Base):
    id = Column(Integer, primary_key=True, index=True)
    tags = relationship("Tag", secondary=source_tag_assoc, backref="source")

class SourceKey(Base):
    id = Column(Integer, primary_key=True, index=True)
    tags = relationship("Tag", secondary=source_key_tag_assoc, backref="source_key")

我个人更喜欢 back_populates,因为当您有十几个模型时,如果明确定义了所有可用关系,就更容易看到它们。