【问题标题】:Populating a SQLAlchemy many-to-many relationship using ID's instead of objects使用 ID 而不是对象填充 SQLAlchemy 多对多关系
【发布时间】:2014-03-07 04:40:04
【问题描述】:

情况:

所以,我在 SQLAlchemy 中有一个基本的多对多关系,使用 association table
例如,一个人可以参加很多聚会,而一个聚会可以有很多人作为客人:

class Person(Base):
    __tablename__ = 'person'
    id      = Column(Integer, primary_key=True)
    name    = db.Column(db.String(50))


class SexyParty(Base):
    __tablename__ = 'sexy_party'
    id      = Column(Integer, primary_key=True)
    guests  = relationship('Person', secondary='guest_association',
                        lazy='dynamic', backref='parties')

guest_association = Table(
    'guest_association',
    Column('user_id',       Integer(), ForeignKey('person.id')),
    Column('sexyparty.id',  Integer(), ForeignKey('sexyparty.id'))
)

通常,如果我想在聚会中添加客人名单,我会这样做:

my_guests = [prince, olivia, brittany, me]
my_party.guests = guests
db.session.commit()

...其中prince、olivia 和brittany 都是<Person> 实例,而my_party 是<SexyParty> 实例。

我的问题

我想使用个人 ID 而不是实例将客人添加到聚会中。 例如:

guest_ids = [1, 2, 3, 5]
my_party.guests = guest_ids  # <-- This fails, because guest_ids
                             # are not <Person> instances

我总是可以从数据库中加载实例,但这需要一个不必要的数据库查询,只是为了设置一个简单的多对多关系。

如何使用 person_id 的列表设置 .guests 属性? 必须有一种简单的方法来做到这一点,因为关联表最终表示使用 ID 的多对多关系......

提前致谢,希望问题清楚。

【问题讨论】:

    标签: python sql sqlalchemy many-to-many flask-sqlalchemy


    【解决方案1】:
    from sqlalchemy import *
    from sqlalchemy.orm import *
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class Person(Base):
        __tablename__ = 'person'
        id      = Column(Integer, primary_key=True)
        name    = Column(String(50))
    
    
    class SexyParty(Base):
        __tablename__ = 'sexy_party'
        id      = Column(Integer, primary_key=True)
        guests  = relationship('Person', secondary='guest_association',
                            lazy='dynamic', backref='parties')
    
    guest_association = Table(
        'guest_association', Base.metadata,
        Column('user_id',       Integer(), ForeignKey('person.id'), primary_key=True),
        Column('sexyparty_id',  Integer(), ForeignKey('sexy_party.id'), primary_key=True)
    )
    
    
    e = create_engine("sqlite://", echo=True)
    Base.metadata.create_all(e)
    
    sess = Session(e)
    
    p1 = Person(id=1, name='p1')
    p2 = Person(id=2, name='p2')
    p3 = Person(id=3, name='p3')
    p4 = Person(id=4, name='p4')
    
    sp1 = SexyParty(id=1)
    
    sess.add_all([sp1, p1, p2, p3, p4])
    sess.commit()
    
    # method one.  use insert()
    sess.execute(guest_association.insert().values([(1, 1), (2, 1)]))
    
    # method two.  map, optional association proxy
    from sqlalchemy.ext.associationproxy import association_proxy
    
    class GuestAssociation(Base):
        __table__ = guest_association
        party = relationship("SexyParty", backref="association_recs")
    
    SexyParty.association_ids = association_proxy(
                        "association_recs", "user_id",
                        creator=lambda uid: GuestAssociation(user_id=uid))
    
    sp1.association_ids.extend([3, 4])
    sess.commit()
    

    【讨论】:

    • docs 用于关联代理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2015-03-16
    • 1970-01-01
    • 2022-01-13
    • 2020-09-12
    • 1970-01-01
    相关资源
    最近更新 更多