Получение свойств отношения «многие ко многим» с использованием SQLAlchemy - PullRequest
0 голосов
/ 07 февраля 2010

У меня есть отношение многие ко многим, в котором таблица отношений содержит больше столбцов, чем только первичный ключ. В качестве примера рассмотрим систему слайд-шоу, в которой у каждого изображения может быть свой собственный тайм-аут и другой тайм-аут в зависимости от слайд-шоу. Глупый пример, но это будет сделано ради иллюстрации;)

Итак, я думаю, я бы сделал что-то вроде следующего (используя декларативное):

show_has_image = Table( 'show_has_image',
      DeclarativeBase.metadata,
      Column( 'show_id', Integer, ForeignKey( 'show.id' ) ),
      Column( 'image_id', Integer, ForeignKey( 'image.id' ) ),
      Column( 'timeout', Integer, default=5 ),
      PrimaryKeyConstraint( 'show_id', 'image_id' )
      )

class Show(DeclarativeBase):
   __tablename__ = "show"

   id = Column( Integer, primary_key = True )
   name  = Column( Unicode(64), nullable = False)

class Image(DeclarativeBase):
   __tablename__ = "image"

   id   = Column( Integer, primary_key = True )
   name = Column( Unicode(64), nullable = False)
   data = Column(Binary, nullable = True)
   show = relation( "Show",
         secondary=show_has_image,
         backref="images" )

Как мне получить доступ к значению "тайм-аут"? Я не могу найти ничего в документах по этому поводу. Пока что получить изображения просто:

show = DBSession.query(Show).filter_by(id=show_id).one()
for image in show.images:
    print image.name
    # print image.timeout <--- Obviously this cannot work, as SA has no idea
    #                          how to map this field.

Я был бы более чем счастлив, если бы он работал так, как я только что обрисовал в предыдущем коде. Конечно, я могу добавить свойство timeout к классу Image, которое будет извлекать значение динамически. Но это приведет к ненужным запросам SQL.

Я бы предпочел, чтобы все это возвращалось в одном запросе. В SQL это просто:

    SELECT i.name, si.timeout
      FROM show s
INNER JOIN show_has_image si ON (si.show_id = s.id)
INNER JOIN image i ON (si.image_id = i.id)
     WHERE s.id = :show_id

1 Ответ

1 голос
/ 08 февраля 2010

Вы можете определить промежуточную модель на основе таблицы show_has_image (использовать составной первичный ключ) и определить отношения к ней. Затем используйте association_proxy, чтобы определить Show.images свойство.

...