With the following tables and mappings
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")})
When I load ‘A’ I can get the related ‘B’ objects in the ‘b_s’ property. But What I want is a list of ids of related Bs in the A.b_ids property. Is there a way to do this?
I tried :
mapper(A, a, properties={'b_ids' :
column_property(select(
[b.c.id],
a.c.id==b.c.a_id))
})
But its giving error: ‘ProgrammingError: (ProgrammingError) more than one row returned by a subquery used as an expression’
column_property() is used to add another column to the SELECT statement, such as this:
In SQL, that’s a subquery in the columns clause of the SELECT statement, and it needs to return exactly one row/column for each row – in SQLAlchemy we call this a “scalar select”.
In this case you’re looking for a list, so that’s not embedded into the main columns clause there. That’s why the database returns an error for that. Your mapping already has a list of “b ids” on it, in the form of “b_s”. You just want to extract the “id” from that, and this can be done pretty easily with the association proxy:
When you access “a.b_ids”, it will look at each entry within “b_s” and extract the “id” attribute, returning a collection that’s compatible with the type of collection of “b_s”, which in this case is a Python list.