У меня есть отношение многие ко многим, в котором таблица отношений содержит больше столбцов, чем только первичный ключ. В качестве примера рассмотрим систему слайд-шоу, в которой у каждого изображения может быть свой собственный тайм-аут и другой тайм-аут в зависимости от слайд-шоу. Глупый пример, но это будет сделано ради иллюстрации;)
Итак, я думаю, я бы сделал что-то вроде следующего (используя декларативное):
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