如何用AssociationProxy让Group表的users代理返回含关联额外字段的结构?
问题
我有一个标准的关联表:
class GroupUserAssociation(Base): __tablename__ = "group_user_associations" group_id: Mapped[int] = mapped_column(ForeignKey("groups.id"), primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), primary_key=True) group: Mapped["Group"] = relationship(back_populates="user_associations") user: Mapped["User"] = relationship(back_populates="group_associations") membership_state: Mapped[GroupMembershipState] # 字符串类型枚举
而我的“左表”定义如下:
class Group(BaseEntity): __tablename__ = "groups" ... user_associations: Mapped[List["GroupUserAssociation"]] = relationship( "GroupUserAssociation", back_populates="group", ) # 我希望users代理返回形如{"user": association.user, "membership_state": association.membership_state}的结构 users: AssociationProxy = association_proxy( ...需要实现的代码... )
请问如何实现上述users字段的预期结构?我曾研究过association_proxy的proxy_factory参数,但文档说明不够清晰,无法掌握其用法。
解决方案
要实现返回包含user和membership_state的字典结构,你可以通过association_proxy的getter、setter参数配合转换逻辑实现,分两种场景处理:
只读场景(仅获取数据)
如果只需要从Group读取users数据,仅配置getter即可完成转换:
from sqlalchemy.ext.associationproxy import association_proxy class Group(BaseEntity): __tablename__ = "groups" # ... 其他字段 ... user_associations: Mapped[List["GroupUserAssociation"]] = relationship( "GroupUserAssociation", back_populates="group", ) users: AssociationProxy = association_proxy( "user_associations", getter=lambda assoc: {"user": assoc.user, "membership_state": assoc.membership_state} )
读写场景(支持添加新关联)
如果需要通过Group.users添加新的用户关联,需额外配置setter和proxy_factory:
class Group(BaseEntity): __tablename__ = "groups" # ... 其他字段 ... user_associations: Mapped[List["GroupUserAssociation"]] = relationship( "GroupUserAssociation", back_populates="group", ) users: AssociationProxy = association_proxy( "user_associations", getter=lambda assoc: {"user": assoc.user, "membership_state": assoc.membership_state}, setter=lambda obj: GroupUserAssociation( user=obj["user"], membership_state=obj["membership_state"] ), proxy_factory=lambda: [] )
参数说明
getter:定义从GroupUserAssociation实例到目标字典的转换逻辑。setter:定义从目标字典到GroupUserAssociation实例的转换逻辑,用于写入操作。proxy_factory:指定代理集合的类型,这里用lambda: []生成列表,默认值也是列表,可省略,显式声明更清晰。
使用示例
# 读取数据 for item in group.users: print(item["user"].id, item["membership_state"]) # 添加新关联(读写场景) group.users.append({ "user": some_user_instance, "membership_state": GroupMembershipState.ACTIVE })
内容的提问来源于stack exchange,提问作者agnivesh
相关产品推荐
相关产品推荐

