代码之家  ›  专栏  ›  技术社区  ›  Travis

一个表上的多对多关系

  •  13
  • Travis  · 技术社区  · 15 年前

    我在应用程序中建立了一个sqlAlchemy模型,它应该模仿Twitter上“关注者”的功能,即用户与其他人(关注者和关注者)之间有多对多的关系。表的结构如下(sa是sqlAlchemy模块):

    t_users = sa.Table("users", meta.metadata,
        sa.Column("id", sa.types.Integer, primary_key=True),
        sa.Column("email", sa.types.String(320), unique=True, nullable=False),
        ...etc...
        )
    
    t_follows = sa.Table("follows", meta.metadata,
        sa.Column("id", sa.types.Integer, primary_key=True),
        sa.Column("follower_id", sa.types.Integer, sa.ForeignKey('users.id'), nullable=False),
        sa.Column("followee_id", sa.types.Integer, sa.ForeignKey('users.id'), nullable=False)
        )
    

    不过,我遇到了一些障碍,试图使用orm.mapper来创建这种关系,因为次表在两个方向都引用了相同的主表。如何将此关系映射到ORM?

    2 回复  |  直到 13 年前
        1
  •  7
  •   Denis Otkidach    15 年前

    你必须写 primaryjoin secondaryjoin 这种情况下的明确条件:

    mapper(
        User, t_users,
        properties={
            'followers': relation(
                User,
                secondary=t_follows,
                primaryjoin=(t_follows.c.followee_id==t_users.c.id),
                secondaryjoin=(t_follows.c.follower_id==t_users.c.id),
            ),
            'followees': relation(
                User,
                secondary=t_follows,
                primaryjoin=(t_follows.c.follower_id==t_users.c.id),
                secondaryjoin=(t_follows.c.followee_id==t_users.c.id),
            ),
        },
    )
    

    我写了这个详细的示例来帮助您更好地理解 基本连接 二次连接 参数平均值。当然,你可以用 backref .

    顺便说一句,你不需要 id 下表中的列,请改用复合主键。实际上,您应该定义 follower_id followee_id 无论如何配对(作为主键或附加的唯一键)。

        2
  •  19
  •   Kurt Telep    13 年前

    您也可以声明地这样做。

    下面是一个基于上述代码的类似示例,我确实使用了backref。

    VolumeRelationship = Table(
        'VolumeRelationship', Base.metadata,
        Column('ParentID', Integer, ForeignKey('Volumes.ID')),
        Column('VolumeID', Integer, ForeignKey('Volumes.ID'))
        )
    
    class Volume(Base):
        """ Volume Object """
        __tablename__ = "Volumes"
    
        id = Column('ID', Integer, primary_key=True, nullable=False)
        type = Column('Type', String(25))
        name = Column('Name', String(25))
        poolid = Column('pool', Integer, ForeignKey('Pools.ID'))
        parents = relation(
                        'Volume',secondary=VolumeRelationship,
                        primaryjoin=VolumeRelationship.c.VolumeID==id,
                        secondaryjoin=VolumeRelationship.c.ParentID==id,
                        backref="children")