我正在尝试使用声明性 SQLAlchemy (v1.1.5) 在两个表之间创建关系,其中表具有复合主键和外键。
这本质上是两个表之间经典的一对多关系,其中Resource定义父级,每个资源有多个段,在Resourcesegment表中定义。不同之处在于,我已将 VersionID 列添加到两个表中,因此我可以将数据库与多个版本的数据一起使用。这是简化的代码:
from sqlalchemy import Column, String, Integer, ForeignKeyConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
class Resource(Base):
__tablename__ = 'resource'
VersionID = Column(String, primary_key=True)
ResourceID = Column(String, primary_key=True)
ResourceProperty = Column(String)
segments = relationship("Resourcesegment", back_populates="resource")
class Resourcesegment(Base):
__tablename__ = 'resourcesegment'
VersionID = Column(String, primary_key=True)
ResourceID = Column(String, primary_key=True)
Segment_Type = Column(String, primary_key=True)
Segment_Number = Column(Integer, primary_key=True)
Segment_Property = Column(String)
resource = relationship("Resource", foreign_keys=[VersionID, ResourceID], back_populates="segments")
__table_args__ = (ForeignKeyConstraint([VersionID, ResourceID], [Resource.VersionID, Resource.ResourceID]),)
我收到的错误信息是:
InvalidRequestError: Mapper 'Mapper|Resourcesegment|resourcesegment' 没有属性 'resource'
我已经尝试了许多不同的关系和外键配置,但没有成功。根据我在文档和各种 Stackoverflow 示例中的理解,这是我对什么应该起作用的最佳猜测。显然我错过了一些东西。
感谢任何帮助/建议/评论!
假设您尝试使用段 PK 作为资源的 FK,请尝试在 PK 属性定义上定义 FK,例如沿着:
class Resourcesegment(Base):
__tablename__ = 'resourcesegment'
VersionID = Column(String, ForeignKey(Resource.VersionID), primary_key=True)
ResourceID = Column(String, ForeignKey(Resource.ResourceID), primary_key=True)
Segment_Type = Column(String, primary_key=True)
Segment_Number = Column(Integer, primary_key=True)
Segment_Property = Column(String)
resource = relationship("Resource", back_populates="segments")
所以我在回答我自己的问题!事实证明,我上面发布的原始代码是正确的。我遇到的问题是由于我正在开发的实际模型中有一组复杂得多的表。其他表中的一个有问题,最终引发错误,使问题看起来像是上述表。当我剥离所有东西时,由于创建了这个 SO 帖子,我得到了我的简化模型,并且能够将问题隔离到更大模型的另一部分。
一个警告:SQLAlchemy 发出的错误消息可能非常混乱,如果不做一些额外的调试工作,不一定能够查明实际问题。