Query for list of attribute instead of tuples in SQLAlchemy

I’m querying for the ids of a model, and get a list of (int,) tuples back instead of a list of ids. Is there a way to query for the attribute directly?

result = session.query(MyModel.id).all()

I realize it’s possible to do

results = [r for (r,) in results]

Is it possible for the query to return that form directly, instead of having to process it myself?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

When passing in ORM-instrumented descriptors such as a column, each result is a named tuple, even for just one column. You could use the column name in a list comprehension to ‘flatten’ the list (you can drop the .all() call, iteration retrieves the objects too):

result = [r.id for r in session.query(MyModel.id)]

or use the fact that it’s a tuple when looping a for loop and unpack it to a single-element tuple of targets:

result = session.query(MyModel.id)
for id, in result:
    # do something with the id

The latter could also be used in a list comprehension:

[id for id, in session.query(MyModel.id)]

You don’t really have any options to force the row results to be just the single id value.

Method 2

It’s strange that SQLalchemy is not providing a proper solution. In sqlalchemy if select a member variable such as a column then each result is a named tuple as @Martijn said. I came to a solution for this using zip function of python

ZIP Method

Zip official docuementation

zip(seq1 [, seq2 […]]) -> [(seq1[0], seq2[0] …), (…)]
Return a list of tuples, where each tuple contains the i-th element
from each of the argument sequences. The returned list is truncated
in length to the length of the shortest argument sequence.

Coming to your example

result = session.query(MyModel.id).all()
result = zip(*result)[0]

Output:

[id1, id2, id3...]

How it will work it will flatten list of tuples given as argument if you pass the list like

[(key11, key21), (key12,key22)]

Zip will convert this list of tuples into

[(key11, key12), (key21, key22)]

In your case you want every Initial value of tupe that is of the MyModel so you can take the 0th tuple from the list.

Chain Method

from itertools import chain
result = session.query(MyModel.id).all()  # result [(id1,), (id2,), (id3,)]
result = list(chain(*result))

Output

[id1, id2, id3]

For loop

result = session.query(MyModel.id).all()  # result [(id1,), (id2,), (id3,)]
result = [id for id, in result]

Output

[id1, id2, id3]

Method 3

q_stringlist = [q[0] for q in session.query((distinct(Table.column))).all()]

for Flask SQLAlchemy

q_stringlist = [q[0] for q in db.session.query((distinct(Table.column))).all()]


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x