I'm doing a join like this in SQLAlchemy:
items = Item.query\
.outerjoin((ItemInfo, ItemInfo.item_id==Item.id))
items.add_columns(ItemInfo.count)
This causes SQLAlchemy to return tuples:
>>> items.first()
(<Item ...>, 2)
I'd much prefer it if the "count" value would instead be returned as an attribute of the item, i.e. I want to do:
>>> items.first().count
2
Is this supported?
Community Size. Without any doubt, SQLAlchemy has the largest community among Python ORM frameworks. If community is important to you (and I think it should be), SQL Alchemy should be your choice. It doesn't mean though that you won't find any help for other frameworks such as Django.
As the documentation says, all() returns the result of the query as a list.
filter() - filter on SQL expressions. method sqlalchemy.orm.Query. first() Return the first result of this Query or None if the result doesn't contain any row.
Actually, "items.first().count" would work, since the tuple you get back is a named tuple...but guessing you don't want to see items.first().item.foo.
The second way you could do this would be just to run the result of your query() through a function that constructs the kind of result you want:
def process(q):
for item, count in q:
item.count = count
yield count
edit: here is a generalized version:
from sqlalchemy.orm.query import Query
class AnnotateQuery(Query):
_annotations = ()
def annotate(self, key, expr):
q = self.add_column(expr)
q._annotations = self._annotations + (key, )
return q
def __iter__(self):
if not self._annotations:
return super(AnnotateQuery, self).__iter__()
else:
for row in super(AnnotateQuery, self):
item, remaining = row[0], row[1:]
for i, key in enumerate(self._annotations):
setattr(item, key, remaining[i])
yield item
# session usage:
Session = sessionmaker(query_cls=AnnotateQuery)
# query usage:
q = Session.query(Item).outerjoin(...).annotate('count', Item.count)
The third, is that you alter the Item class to support this function. You'd use column_property()
to apply a select subquery to your class: http://www.sqlalchemy.org/docs/orm/mapper_config.html#sql-expressions-as-mapped-attributes . If you wanted the loading of the attribute to be conditional, you'd use deferred: http://www.sqlalchemy.org/docs/orm/mapper_config.html#deferred-column-loading .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With