使用SQLAlchemy检索多对多关系属性

0 投票
1 回答
666 浏览
提问于 2025-04-15 19:00

我有一个多对多的关系,其中关系表不仅仅包含主键,还包含更多的列。举个例子,想象一下一个幻灯片系统,每张图片可以有自己的超时时间,而且根据不同的幻灯片,这个超时时间也可能不同。这是个有点傻的例子,但为了说明问题就这样吧;)

所以我想我会做类似下面这样的事情(使用声明式方法):

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.

我非常希望它能像我在之前的代码中描述的那样工作。当然,我可以在Image类中添加一个timeout属性,这样就能动态获取这个值。但这样会导致不必要的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

你可以根据show_has_image这个表来定义一个中间模型(使用复合主键),并为它定义关系。然后可以使用association_proxy来定义Show.images这个属性。

撰写回答