使用以下表格和映射
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)由用作表达式的子查询返回的多行[
答案 0 :(得分:4)
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语句的columns子句中的子查询,它需要为每一行返回一行/列 - 在SQLAlchemy中,我们将其称为“标量选择”。
在这种情况下,您正在寻找一个列表,因此没有嵌入到主列子句中。这就是数据库为此返回错误的原因。您的映射上已经有一个“b ID”列表,格式为“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列表。
答案 1 :(得分:0)
我尝试将association_proxy放在mapper属性中。但它不允许。炼金术文档也说“代理是一个Python属性,与mapper关系不同,在你的类中定义”。所以我假设我们不能保持这个内部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')
这似乎有效。这样做是可以的吗?或者有更好的方法吗?
此致 Litty