The SQLAlchemy manual says* that the Session.scalars()
method returns ORM objects.
*Selecting ORM Entries
The following code shows two examples one of which returns an ORM object but the other does not. The first uses a select statement which selects a single ORM object. The second example does not return an ORM object. It is identical except for the introduction of SQLAlchemy’s intersect()
function. It is only returning the first column of the desired object.
Although it is possible to select the primary keys of records and then carry out a second select for ORM objects that seems like a kludge. Is there a more elegant solution?
from sqlalchemy import create_engine, select, intersect
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, Session
class Base(DeclarativeBase):
pass
class Movie(Base):
__tablename__ = "movie"
title: Mapped[str]
id: Mapped[int] = mapped_column(primary_key=True)
def __repr__(self):
return (
f"{self.__class__.__qualname__}("
f"title={self.title!r}, "
f"id={self.id!r})"
)
engine = create_engine("sqlite+pysqlite:///:memory:")
Base.metadata.create_all(engine)
with Session(engine) as session:
movie_1 = Movie(title="Great Movie 1")
movie_2 = Movie(title="Great Movie 2")
session.add_all((movie_1, movie_2))
statement = select(Movie).where(Movie.title == "Great Movie 1")
print("n", statement)
result = session.scalars(statement).all()
print(f"{result=}")
stmt_isec = intersect(statement)
# In case you're wondering, the next line has the same effect as
# the unary intersect.
# stmt_isec = intersect(*[statement, statement])
print("n", stmt_isec)
result = session.scalars(stmt_isec).all()
print(f"{result=}")