如果我有两个表:A(id,...其他一些列)和B(id,......其他一些列)。我需要将评论(另一个表:id,text,author)与A和B对象相关联。
我是否可以为此目的创建第四个表:comment_id,table_id(A或B或其他),item_id?我的意思是一些sqlalchemy方式?
现在我只知道这两个解决方案: http://bpaste.net/show/27149/ - 对于每个A和B,将有单独的表格和评论。我不认为这是一个好主意,因为那些表(应该)是相同的,如果我想看到一些作者的所有评论 - 它将比其他方式更难,如果有一天会有C表 - 我将需要为其评论创建一个表...
另一种解决方案 - http://bpaste.net/show/27148/。我认为更好,但我仍然需要为每个需要评论项目的表创建一个关联表。
有什么想法吗?提前谢谢。
答案 0 :(得分: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
它仍然是一种相对hacky的方式,但它通过使用外键保留了引用完整性。
如果你想找到存储表名的解决方案,你可以尝试这样的事情:
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
答案 1 :(得分:0)
我也会选择第二种解决方案。但是,正如您所说,可能会有第三个表C
,那么您可以将B_Comment
和A_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_id
和b_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)
# ...