【问题标题】:Bidirectional many-to-many attribute_mapped_collection, sqlalchemy双向多对多attribute_mapped_collection,sqlalchemy
【发布时间】:2012-10-11 15:45:09
【问题描述】:

我有 2 个类作为多对多关系 A 和 B,在此处缩短以显示基本关系:

class A(Base):

    bclss = relationship("B",
                          backref = "aclss",
                          secondary = "a_b_association",
                          collection_class = attribute_mapped_collection('identifier'))   

    a_b_association_table = Table('a_b_association', Base.metadata,
                             Column('a_id', Integer, ForeignKey('a.id')),
                             Column('b_id', Integer, ForeignKey('b.id')) )

所以 A 的实例可以添加 B 的实例,并在以标识符为键的字典中引用...但是 B 实例仅包含其 a 对象的 [列表],我想要一个镜像接口来拉出a 实例通过字典中的标识符键与 b 实例相关。镜像 b 上的关系语句并引用相同的关联表不起作用,所以我正在考虑一个我不完全知道如何在 sqlalchemy 中实现的领域。

所以,即使这不是 100% 清楚,我的问题是:

如何在多对多关系中相关的两个项目上获取字典、属性映射集合,其中每一方都可以通过字典键提取相关项目,而不是我得到的:不对称的一侧字典/另一侧列表界面。

【问题讨论】:

    标签: python orm sqlalchemy relationship


    【解决方案1】:

    我相信这就是您正在寻找的(您只需在与另一个 attribute_mapped_collection 的多对多关系中定义一个 backref 关系):

    from sqlalchemy import Column, ForeignKey, Integer, String, Table, create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import backref, relationship, sessionmaker
    from sqlalchemy.orm.collections import attribute_mapped_collection
    
    
    Base = declarative_base()
    
    
    class A(Base):
        __tablename__ = 'a'
    
        id = Column(Integer, primary_key=True)
    
    
    a_b_association_table = Table(
        'a_b_association', Base.metadata,
        Column('a_id', Integer, ForeignKey('a.id')),
        Column('b_id', Integer, ForeignKey('b.id'))
    )
    
    
    class B(Base):
        __tablename__ = 'b'
    
        id = Column(String, primary_key=True)
    
        a_instances = relationship(
            A,
            backref = backref(
                'b_instances',
                collection_class = attribute_mapped_collection('id'),
            ),
            secondary = a_b_association_table,
            collection_class = attribute_mapped_collection('id'),
        )
    
    
    engine = create_engine('sqlite://')
    Base.metadata.bind = engine
    Base.metadata.create_all()
    
    Session = sessionmaker(bind=engine)
    
    session = Session()
    
    a1, a2, a3 = A(id=1), A(id=2), A(id=3)
    b1, b2, b3 = B(id='a'), B(id='b'), B(id='c')
    
    session.add_all([a1, a2, a3, b1, b2, b3])
    session.flush()
    
    print(a1.b_instances)
    print(b1.a_instances)
    a1.b_instances[b1.id] = b1
    a1.b_instances[b2.id] = b2
    b1.a_instances[a1.id] = a1
    b1.a_instances[a2.id] = a2
    session.flush()
    session.expunge_all()
    a1 = session.query(A).get(1)
    b1 = session.query(B).get('a')
    print(a1.b_instances)
    print(b1.a_instances)
    

    输出:

    {}
    {}
    {u'a': <__main__.B object at 0x2816490>, u'b': <__main__.B object at 0x28b0350>}
    {1: <__main__.A object at 0x28ac9d0>, 2: <__main__.A object at 0x28b0650>}
    

    【讨论】:

    • 这基本上是我首先做的,然后在此之后返回并给出不同的名称而不是镜像名称。您需要为每个类设置两对参考,而不是在每个类上反转同一对参考。后者是我得到错误的地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 2019-07-29
    • 2011-05-20
    • 1970-01-01
    相关资源
    最近更新 更多