2012-04-16 47 views
1

如果我有兩個表:A(id,...其他一些列)和B(id,...其他一些列)。我需要將評論(另一個表:id,文本,作者)與A和B對象關聯起來。如何構建不同類型的一對多關係?

我可以爲此創建第四張表:comment_id,table_id(A或B或其他人),item_id?我的意思是一些sqlalchemy方式?

現在我只知道這兩個解決方案: http://bpaste.net/show/27149/ - 對於每個A和B,將有單獨的表格與評論。我認爲這不是一個好主意,因爲這些表格(應該)是相同的,如果我想看到某個作者的所有評論 - 這將比其他方式更困難,如果有一天會有C表格 - 我將需要創建一個表的評論...

另一種解決方案 - http://bpaste.net/show/27148/。我認爲更好,但我仍然需要爲每個需要評論項目的表創建關聯表。

任何想法?提前致謝。

回答

2

你可以嘗試:

class Comment(Base): 
    __tablename__ = 'comments' 

    id = Column(Integer, primary_key=True) 
    a_id = Column(Integer, ForeignKey('a.id'), nullable=True) 
    b_id = Column(Integer, ForeignKey('b.id'), nullable=True) 
    text = Column(UnicodeText, nullable=False) 

    def __init__(self, text): 
     self.text = text 

它仍然是做一個相對哈克的方式,但它通過使用外鍵保留參照完整性。

如果你想要去的地方你存儲表名的解決方案,你可以嘗試這樣的事:

class A(Base): 
    __tablename__ = 'as' 

    id = Column(Integer, primary_key=True) 
    name = Column(Unicode, nullable=False, unique=True) 
    comments = relationship("Comment", 
        primaryjoin="and_(A.id==Comment.id, " 
         "Comment.model=='A')") 

    def __init__(self, name): 
     self.name = name 

class Comment(Base): 
    __tablename__ = 'comments' 

    id = Column(Integer, primary_key=True) 
    text = Column(UnicodeText, nullable=False) 
    model = Column(String(50), nullable=False) 

    def __init__(self, text): 
     self.text = text 

我沒有測試此我自己,因此,如果您遇到問題,有一個看看Specifying Alternate Join Conditions或評論,我會做更多的研究。

爲主題的深入說明,請參閱Mike Bayer's blog entry on Polymorphic Associations

+0

謝謝你的努力!我覺得第一種方式可以工作,但這並不好,imho:每個評論都會有太多未使用的列(不僅有A和B,還有更多)。第二個是好的,但我覺得沒有用我不確定它是在sqlalchemy中實現的。 – kishkin 2012-04-16 15:16:22

+0

@kishkin我在SQLalchemy的創建者 – mensi 2012-04-16 15:17:23

+0

中加入了一個關於該主題的深入討論的鏈接。感謝,現在會閱讀。 – kishkin 2012-04-16 15:18:38

0

我會去的第二個解決方案了。但是,正如你說的有可能是第三個表C,那麼你可以把B_CommentA_Comment作爲字段在一個單一的關聯表,如:

class Comment(Base): 
    id = Column(Integer, primary_key=True) 
    a_id = Column(Integer, ForeignKey('as.id'), primary_key=True, nullable=True) 
    b_id = Column(Integer, ForeignKey('bs.id'), primary_key=True, nullable=True) 
    text = Column(UnicodeText, nullable=False) 
    # ... 

而且你可以使用一個查詢,如:session.query(Comment).filter_by(a=whatever)

我想你可以添加一些約束,這樣a_idb_id不是同時NULL

這裏是另一種方式來做到這一點(我不知道這是否是這樣做的標準方式,但它應該工作...

class Letter(Base): 
    id = ... 

class A(Base): 
    letter_id = Column(Integer, ForeignKey('letters.id'), primary_key=True, nullable=False) 
    # ... 

class Comment(Base): 
    letter_id = Column(Integer, ForeignKey('letters.id'), primary_key=True, nullable=True) 
    # ... 
+0

我是我不確定t是個好主意,每個評論都會有很多未使用的列。或者實際上可以嗎? – kishkin 2012-04-16 15:22:18

+0

@kishkin我認爲你是對的,但它比擁有許多未使用的**表**更好。我會添加另一種方式,這可能會更適合你的情況。 – jadkik94 2012-04-16 15:26:38

+0

有點像一個id堆棧的一切? – kishkin 2012-04-16 15:58:12

相關問題