query practices in_ example delete best auth and python orm sqlalchemy

python - practices - SQLAlchemy Relación muchos a muchos en una sola tabla



sqlalchemy models (2)

Tengo un modelo SQLAlchemy configurado en mi aplicación que debe imitar la funcionalidad de "seguidores" en Twitter, es decir. los usuarios tienen una relación de muchos a muchos entre sí (seguidores y seguidores). Las tablas están estructuradas de la siguiente manera (sa es el módulo 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) )

Sin embargo, me encontré con una especie de obstáculo al intentar utilizar orm.mapper para crear esta relación, ya que la tabla secundaria hace referencia a la misma tabla principal en ambas direcciones. ¿Cómo haría para mapear esta relación con el ORM?


En este caso, debe escribir secondaryjoin condiciones de primaryjoin y secondaryjoin explícitamente:

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), ), }, )

He escrito este ejemplo detallado para ayudarlo a comprender mejor lo que primaryjoin secondaryjoin parámetros primaryjoin y secondaryjoin . Claro, puedes hacer que backref con backref .

Por cierto, no necesita la columna de id en la tabla siguiente, use en su lugar la clave primaria compuesta. De hecho, debe definir una restricción única de follower_id y followee_id pair de todos modos (ya sea como clave única primaria o adicional).


También puedes hacer esto de manera declarativa.

Aquí hay un ejemplo similar basado en el código anterior, yo uso el 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")