【问题标题】:Sqlalichemy : Loading related objects ids in parent propertySqlalchemy:在父属性中加载相关对象 id
【发布时间】:2012-03-05 17:56:12
【问题描述】:

具有以下表格和映射

class A:
    def __init__(self):
        self.id = None
        self.b_ids = {}
        self.b_s = {}

class B:
    def __init__ (self):
        self.id = None
        self.a_id = None
        self.a = None

a = Table('t_a', meta,
    Column('id',Integer, autoincrement=True, primary_key=True),
    )

b = Table('t_b', meta,
    Column('id',Integer, autoincrement=True, primary_key=True),
    Column('a_id', Integer, ForeignKey('t_a.id')),
    )

mapper(A, a)
mapper(B, b, properties={'a' : relationship(A, backref="b_s")})

当我加载“A”时,我可以在“b_s”属性中获取相关的“B”对象。但我想要的是 A.b_ids 属性中相关 B 的 id 列表。有没有办法做到这一点?

我试过了:

mapper(A, a, properties={'b_ids' : 
                         column_property(select(
                                                [b.c.id], 
                                                a.c.id==b.c.a_id))
                         })

但它给出的错误:'ProgrammingError: (ProgrammingError) more than one row returned by a subquery used as an expression'

【问题讨论】:

    标签: python orm sqlalchemy


    【解决方案1】:

    我尝试将 Association_proxy 放在映射器属性中。但它不允许。此外,alchemy 文档说“代理是一个 Python 属性,与映射器关系不同,它是在你的类中定义的”。所以我假设我们不能在 mapper() 中保留这个映射。

    无论如何,我无法将模型类修改为其生成的代码。所以我尝试了以下方法:

    a = Table('t_a', meta,
        Column('id',Integer, autoincrement=True, primary_key=True),
        )
    
    b = Table('t_b', meta,
        Column('id',Integer, autoincrement=True, primary_key=True),
        Column('a_id', Integer, ForeignKey('t_a.id')),
        )
    
    mapper(A, a)
    mapper(B, b, properties={'a' : relationship(A, backref="b_s")})
    
    A.b_ids=association_proxy('b_s', 'id')
    

    这似乎有效。那么这样做可以吗?还是有更好的办法?

    问候, 小小

    【讨论】:

    • 如果你已经获得了一个类,那么在事后坚持这个属性就是如何做到这一点,是的。
    【解决方案2】:

    column_property() 用于在 SELECT 语句中添加另一列,例如:

    SELECT a.x, a.y, (SELECT b.id FROM b where a.id=b.a_id) AS b_id FROM a
    

    在 SQL 中,这是 SELECT 语句的列子句中的子查询,它需要为每一行准确返回一行/列 - 在 SQLAlchemy 中,我们称之为“标量选择”。

    在这种情况下,您正在寻找一个列表,因此它没有嵌入到那里的主列子句中。这就是数据库为此返回错误的原因。您的映射上已经有一个“b ids”列表,格式为“b_s”。您只想从中提取“id”,这可以通过关联代理轻松完成:

    from sqlalchemy.ext.associationproxy import association_proxy
    
    class A(object):
        # ... other things
        b_ids = association_proxy('b_s', 'id')
    

    当您访问“a.b_ids”时,它将查看“b_s”中的每个条目并提取“id”属性,返回一个与“b_s”集合类型兼容的集合,在本例中为一个 Python 列表。

    【讨论】:

    • 非常感谢您的回答。我添加了一些疑问作为答案,因为它不适合 cmets。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多