Python SQLAlchemy单个表上的多对多关系

Python SQLAlchemy单个表上的多对多关系,python,orm,sqlalchemy,Python,Orm,Sqlalchemy,我在我的应用程序中设置了一个SQLAlchemy模型,该模型应该模仿Twitter上“追随者”的功能,即用户之间有多对多的关系(追随者和追随者)。这些表的结构如下(sa是sqlalchemy模块): 然而,我在尝试使用orm.mapper创建这种关系时遇到了一些障碍,因为次表在两个方向上都引用了相同的主表。如何将此关系映射到ORM?在这种情况下,您必须明确地编写primaryjoin和secondaryjoin条件: mapper( User, t_users, properti

我在我的应用程序中设置了一个SQLAlchemy模型,该模型应该模仿Twitter上“追随者”的功能,即用户之间有多对多的关系(追随者和追随者)。这些表的结构如下(sa是sqlalchemy模块):


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

在这种情况下,您必须明确地编写
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),
        ),
    },
)
我编写这个详细的示例是为了帮助您更好地理解
primaryjoin
secondaryjoin
参数的含义。当然,您可以使用
backref
使其成为分拣机


顺便说一句,您不需要下表中的
id
列,而是使用复合主键。事实上,您应该定义
follower\u id
followee\u id
对的唯一约束(作为主键或附加唯一键)。

您也可以声明性地执行此操作

下面是一个基于上述代码的类似示例,我确实使用了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")

谢谢,这很有效。您的意思是下表不需要ID列,可以使用复合PK吗?我看不出这对用户表有什么作用。是的,这是一个错误。我的意思是如下表所示。我遇到了这个问题,不得不以声明的方式来做,这是未来发现者的等价物。@DenisOtkidach您能简单地阐述一下次要连接和主要连接的作用吗?正如@Zion所说,详细阐述主要连接和次要连接会有所帮助。然而,这里有一个文档:对我来说,我必须将类似的
外键=[VolumeRelationship.c.VolumeID,VolumeRelationship.c.ParentID])
添加到
Volume.parents
,否则我就没有了
参考表错误
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")