继承自sqlalchemy中相同多态类型的两个模型的多对一关系

时间:2019-11-20 00:04:45

标签: python-3.x database sqlalchemy

我有一个多态基类,如:

class Addressable(Base):
    addressable_id = Column(Integer, nullable=False, primary_key=True)
    addressable_type = Column(String, nullable=False)
    addresses = relationship('Address')

    __mapper_args__ = {'polymoprhic_on': addressable_type}

用于允许子类使用以下命令添加任意数量的地址:

class Address(Base):
    # ...
    addressable_id = Column(Integer, ForeignKey('Addressable.addressable_id')

就我的测试(到目前为止,有限的)所言,这部分工作正常。并不是两个子类之间存在多对一的关系。

class CompanyLocation(Addressable):
   __mapper_args_ = {'polymprophic_identity': 'CompanyLocation'}
   company_location_id = Column(Integer, ForeignKey(Addressable.addressable_id), primary_key=True)
   company_id = Column(CompanyId, ForeignKey('Company.company_id'), nullable=False)

class Company(Addressable):
    __mapper_args_ = {'polymorphic_identity': 'Company'}
    company_id = Column(Integer, ForeignKey(Addressable.addressable_id), primary_key=True)
    locations = relationship(CompanyLocation, foreign_keys=CompanyLocation.company_location_id,
                             backref='company')

测试时是否可以:

company = Company() 
company.addresses.append(Address(name='foo'))
location = CompanyLocation()
company.locations.append(location)
session.add(company)
session.commit()

assert company.addresses[0].name == 'foo'  # Works!
assert company.locations[0] == location

我很困惑:

E    assert <Company object at 0x119e151d0> == <CompanyLocation object at 0x117edc950>

某种程度上,locations拥有公司本身的价值,而不是公司的价值。如果我尝试向公司添加第二个地点,则操作失败,因为该条目不是唯一的(这很有意义,因为它以某种方式使用自己的PK作为FK?)同样,location.company会退回{ {1}}个对象。

如果我删除了CustomerLocation调用,并将append显式添加到customer = relationship('Customer', foreign_keys=customer_id, back_populates='locations')类中,则对CompanyLocation的调用将导致一个空列表。但是,这样做确实至少可以将呼叫固定到company.locations


我做了什么?

底层,我们正在使用PostgresQL,并且正在使用sqlalchemy 1.3.11

就上下文而言,这里的用例是我们的客户需要将地址附加到公司实体(例如,帐单地址),该地址可能不同于其各自位置的地址(其中有些地址也有自己的帐单或帐单)。邮寄地址)。

1 个答案:

答案 0 :(得分:0)

好吧,在尝试了几种不同的解决方案后,我开始使用它。我仍然不明白为什么上述操作失败,但是在我使用primaryjoin而不是foreign_keys之后,例如

class Company:
    # . . .
    locations = relationship("CompanyLocation", back_populates='company', primaryjoin='Company.company_id == CompanyLocation.company_id')