2016-10-10 23 views
0

我已經有一組關係在生產中運行SQLAlchemy 0.9.10一年多了,我期待升級到1.0+。所有測試在簡單升級包後都會通過,但是現在正在記錄新的警告。SQLAlchemy:拒絕多個一對多的列副本

SAWarning:關係 'A.C' 將列test_c.a_id複製到柱 test_a.id,其與關係(一個或多個)相沖突: 'A·B'(拷貝 test_b.a_id到test_a.id)。考慮將viewonly = True應用於 只讀關係,或者使用foreign()註釋提供標記 可寫列的主連接條件。

我儘可能地簡化了表格來演示。

的想法是,父A有表現爲一對那些由每個孩子的家長表示他們的「電流」 ID兩個一對多子女關係(BC)。

class A(Base): 
    __tablename__ = 'test_a' 

    id = Column(BigInteger, primary_key=True, autoincrement='ignore_fk') 
    b_id = Column(BigInteger) 
    c_id = Column(BigInteger) 

    __table_args__ = (
     ForeignKeyConstraint(
      ['id', 'b_id'], 
      ['test_b.a_id', 'test_b.id'], 
      use_alter=True, 
      name='a_b_fk', 
     ), 
     ForeignKeyConstraint(
      ['id', 'c_id'], 
      ['test_c.a_id', 'test_c.id'], 
      use_alter=True, 
      name='a_c_fk', 
     ), 
    ) 


class B(Base): 
    __tablename__ = 'test_b' 

    id = Column(BigInteger, autoincrement=True, primary_key=True) 
    a_id = Column(ForeignKey('test_a.id'), primary_key=True) 


class C(Base): 
    __tablename__ = 'test_c' 

    id = Column(BigInteger, autoincrement=True, primary_key=True) 
    a_id = Column(ForeignKey('test_a.id'), primary_key=True) 


# A has exactly one *current* B 
A.b = sa_orm.relationship(
    B, 
    primaryjoin=sa_sql.and_(A.id == B.a_id, 
          A.b_id == B.id), 
    uselist=False, 
) 

# Every C refers to a single A 
C.a = sa_orm.relationship(
    A, 
    primaryjoin=C.a_id == A.id, 
    foreign_keys=[C.a_id], 
) 

# Conversely, every A has zero or one C 
A.c = sa_orm.relationship(
    C, 
    primaryjoin=sa_sql.and_(A.id == C.a_id, 
          A.c_id == C.id), 
    uselist=False, 
) 

使用viewonly不是一個選項,因爲關係中的某些列會寫入。 我試過每個組合都可以想到關於關係定義的foreign(),但是我仍然沒有能夠在仍然具有代碼功能時得到警告停止。在閱讀完文檔和SA代碼庫的很大一部分之後,我似乎被困在如何設置它。

據我所知,我需要在BC上表示A.id的值是不可變的。

  • 我在正確的軌道上嗎?
  • 有沒有什麼值得在the docs以外尋求幫助的例子呢?
  • 我的疼痛是由primaryjoin使用and_()這一事實引起的嗎?

回答

1

你的問題來自於你有兩個關係的事實,可以修改A.id,進而從事實,你已經把它命名爲兩個獨立的關係的一部分莖。儘管技術上SQL允許你這樣做,但SQLAlchemy在它允許你建模的模式中更加嚴格。

正確的解決方案是不要讓A.id成爲連接的一部分,因爲它不是必須的。 b_idc_id列包含您需要的所有信息以找到BC表中的右列。如果您對數據完整性感到擔憂,您可以保留對外部密鑰A.id的引用。