2012-04-16 3 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 - I необходимо будет создать таблицу для своих комментариев ...

Другое решение - 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 

Это еще относительно 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

+0

Спасибо за усилия! Я думаю, что первый путь будет работать, но это нехорошо, imho: будет слишком много неиспользуемых столбцов для каждого комментария (там будут не только A и B, но и многие другие). Второй вариант, я думаю, но не так хорош, как использование Идентификаторы таблиц и идентификаторы элементов. На самом деле я не уверен, что он реализован в sqlalchemy. – kishkin

+0

@kishkin Я добавил ссылку на подробное обсуждение темы создателем SQLalchemy – mensi

+0

Спасибо, буду читать сейчас. – kishkin

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) 
    # ... 
+0

Я не уверен, что я t - хорошая идея, для каждого комментария будет много неиспользуемых столбцов. Или это нормально? – kishkin

+0

@kishkin Я думаю, что вы правы, но все же лучше, чем иметь много неиспользуемых ** таблиц **.Я добавлю еще один способ, который лучше подходит вашему делу. – jadkik94

+0

Что-то вроде одного стека id за все? – kishkin

Смежные вопросы