Skip to main content
 首页 » 编程设计

python之双向多对多attribute_mapped_collection,sqlalchemy

2025年05月04日21xing901022

我有 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 对象的[列表],我想要一个镜像接口(interface),以拉出a 实例通过字典中的标识符键与 b 实例相关。镜像 b 上的关系语句并引用同一个关联表是行不通的,所以我正在考虑一个我还不知道如何在 sqlalchemy 中实现的领域。

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

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

请您参考如下方法:

我相信这就是您正在寻找的(您只需要在与另一个 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>}