SQLAlchemy以一种关系处理多个路径

时间:2018-10-04 15:39:15

标签: python sqlalchemy

请注意:该问题是相关的,但与我当前打开的其他问题SQLAlchemy secondary join relationship on multiple foreign keys无关。

单个类中的SQLAlchemy documentation describes handling multiple join paths 用于多种关系

from sqlalchemy import Integer, ForeignKey, String, Column
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()

class Customer(Base):
    __tablename__ = 'customer'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    billing_address_id = Column(Integer, ForeignKey("address.id"))
    shipping_address_id = Column(Integer, ForeignKey("address.id"))

    billing_address = relationship("Address")
    shipping_address = relationship("Address")

class Address(Base):
    __tablename__ = 'address'
    id = Column(Integer, primary_key=True)
    street = Column(String)
    city = Column(String)
    state = Column(String)
    zip = Column(String)

在同一部分中,文档显示了三种定义关系的单独方法:

  1. billing_address = relationship("Address", foreign_keys=[billing_address_id])

  2. billing_address = relationship("Address", foreign_keys="[Customer.billing_address_id]")

  3. billing_address = relationship("Address", foreign_keys="Customer.billing_address_id")

在(1)和(2)中可以看到,SQLAlchemy允许您定义一个Foreign_keys列表。实际上,文档明确指出:

  

在此特定示例中,在任何情况下都不需要该列表,因为我们只需要一个列:billing_address = relationship("Address", foreign_keys="Customer.billing_address_id")

但是我无法确定如何使用列表符号在单个关系中指定多个外键

对于班级

class PostVersion(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ...
    tag_1_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_2_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_3_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_4_id = db.Column(db.Integer, db.ForeignKey("tag.id"))
    tag_5_id = db.Column(db.Integer, db.ForeignKey("tag.id"))

class Tag(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tag = db.Column(db.String(127))

我尝试了以下所有操作:

  1. tags = db.relationship("Tag", foreign_keys=[tag_1_id, tag_2_id, tag_3_id, tag_4_id, tag_5_id])导致
  

sqlalchemy.exc.AmbiguousForeignKeysError:无法确定关系AnnotationVersion.tags的父/子表之间的联接条件-有多个链接表的外键路径。指定'foreign_keys'参数,并提供这些列的列表,这些列应被视为包含对父表的外键引用。

  1. tags = db.relationship("Tag", foreign_keys="[tag_1_id, tag_2_id, tag_3_id, tag_4_id, tag_5_id]")导致
  

sqlalchemy.exc.InvalidRequestError:初始化映射器Mapper | AnnotationVersion | annotation_version时,表达式'[tag_1_id,tag_2_id,tag_3_id,tag_4_id,tag_5_id]'找不到名称(“名称'tag_1_id未定义”)。如果这是一个类名,请考虑在定义了两个从属类之后,将这个Relationship()添加到该类中。

列表样式的许多其他变体,使用内部和外部引号,使用表名和类名。

在这个问题过程中,我实际上已经解决了这个问题。由于似乎没有直接的文档,我将自己回答而不删除此问题。

1 个答案:

答案 0 :(得分:0)

关键是定义主联接上的关系并指定uselist参数。

tags = db.relationship("Tag", primaryjoin="or_(PostVersion.tag_1_id==Tag.id,"
     "PostVersion.tag_2_id==Tag.id, PostVersion.tag_3_id==Tag.id,"
     "PostVersion.tag_4_id==Tag.id, PostVersion.tag_5_id==Tag.id)",
     uselist=True)