Given a SQLAlchemy ORM model like this
class Foo(Base):
__tablename__ = 'foo'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String())
In SQLAlchemy 1.4 / 2.0, the ORM's session.query idiom is being unified with the SQLAlchemy core select function*, so to fetch all Foos we would do
foos = session.execute(Foo).scalars().all()
instead of
foos = session.query(Foo).all()
In the current (sqlalchemy<=1.3) ORM we can obtain the number of Foos in the database with this query:
nfoos = session.query(Foo).count()
But how can we get the count in SQLALchemy 1.4?
session.execute(sa.select(Foo).count())
raises
AttributeError: 'Select' object has no attribute 'count'
session.execute(sa.select(Foo)).count()
raises
AttributeError: 'ChunkedIteratorResult' object has no attribute 'count'
session.execute(sa.select(sa.func.count(Foo)))
raises
sqlalchemy.exc.ArgumentError: SQL expression element expected, got
<class '__main__.Foo'>.
This works,
session.execute(sa.select(sa.func.count(Foo.id))).scalars()
but specifying an attribute seems less OO / elegant than the Query.count version. Moreover, it precludes building a query but deferring the decision of whether to retrieve the count or the model instances.
What is the idiomatic way to get the count() of an ORM query in the new SQLAlchemy 1.4 world?
* the session.query() API will still work in 1.4 and later