使用复合主键和外键的SQLAlchemy

2024-04-26 00:17:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用声明性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' has no property 'resource'

我尝试过很多不同的关系和外键配置,但都没有成功。根据我在文档和各种Stackoverflow示例中的理解,这是我对应该如何工作的最佳猜测。很明显我遗漏了一些东西。在

感谢您的帮助/建议/意见!在


Tags: keyfromimporttruestringsqlalchemy关系column
2条回答

所以我要回答我自己的问题!原来我在上面发布的原始代码是正确的。我遇到的问题是由于我正在开发的实际模型中有一组更复杂的表。另一个表有一个问题,最后抛出一个错误,使它看起来像是上面的表有问题。当我剥离了所有的东西,作为创建这个SO post的结果,我得到了我的简化模型,并能够将问题隔离到更大模型的另一部分。在

一个警告:来自SQLAlchemy的错误消息可能非常令人困惑,并且不一定能够准确地指出实际的问题,而不需要做一些额外的调试工作。在

假设您正在尝试使用段PKs作为FKs to Resource,请尝试在PK属性定义上定义FKs,例如,沿着以下行:

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")

相关问题 更多 >