Why is Session#query deprecated? #1284
-
First Check
Commit to Help
Example Codesession.query(MyModel) # <= this is deprecated
session.query(MyModel).all() # <= this returns all records
sesssion.exec(statement)
# ^ This requires a statement to be constructed ahead which makes it
# difficult for composition in certain cases DescriptionSession#query has been deprecated but its an incredibly useful part of the API. My use case is that I want to have methods that do the following: With the current query method, I can do this very easily. With the new API, there's no way to do this. The reason given for the old API is that types break, but you can easily specify Query[T] as the return type and all is solved. Here's a complete example: from sqlalcemy.orm import Query
class MagicSQLModel(SQLModel):
@classmethod
def query(cls: type[T], session: Session | None = None) -> Query[T]:
if not session:
with db_session() as s:
session = s
return session.query(cls)
class MyModel(MagicSQLModel, table=True):
# ....
MyModel.query().all() # <= This is typed properly With the new API I'd have to create an intermediary object which will be perpetually incomplete: # Note there are minor errors (e.g. exists)
class AutoQuery(Generic[T]):
def __init__(self, model: type[T], session: Session):
"""Initialize with a shared session."""
self.model = model
self.session = session
self.statement = select(model)
def where(self, *conditions) -> "AutoQuery[T]":
"""Apply WHERE conditions to the query."""
self.statement = self.statement.where(*conditions)
return self
def all(self) -> list[T]:
"""Execute and return all results."""
return self.session.exec(self.statement).all()
def first(self) -> T | None:
"""Execute and return the first result."""
return self.session.exec(self.statement).first()
def last(self) -> T | None:
"""Execute and return the last result."""
return self.session.exec(self.statement.order_by(self.model.id.desc())).first()
def count(self) -> int:
"""Execute and return the count of results."""
return self.session.exec(self.statement).count()
def find(self, id: int) -> T | None:
"""Execute and return a single result by ID."""
return self.session.exec(self.statement.where(self.model.id == id)).first()
def exists(self) -> bool:
"""Check if any record matches the query."""
return self.session.exec(self.statement.exists()).scalar()
def order(self, *columns: str) -> "AutoQuery[T]":
"""Sort results by specified columns."""
self.statement = self.statement.order_by(*columns)
return self
def limit(self, n: int) -> "AutoQuery[T]":
"""Limit the number of results returned."""
self.statement = self.statement.limit(n)
return self
def offset(self, n: int) -> "AutoQuery[T]":
"""Skip the first `n` results."""
self.statement = self.statement.offset(n)
return self
def delete(self) -> int:
"""Delete matching records and return affected row count."""
stmt = delete(self.model).where(*self.statement.whereclause)
result = self.session.exec(stmt)
self.session.commit()
return result.rowcount
class MagicSQLModel(SQLModel, table=True)
@classmethod
def query(cls: type[T], session = None) -> AutoQuery[T]: # this should be implemented in your new base class
with Session(engine) as s:
session = s
return AutoQuery(cls, session) Operating SystemmacOS Operating System DetailsThis isn't related SQLModel Version0.0.22 Python Version3.10.13 Additional ContextThis is just a simple question about the deprecation of Session#query |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I think that's because it's deprecated on SQLAlchemy's side and SQLModel just reflects that: |
Beta Was this translation helpful? Give feedback.
I think that's because it's deprecated on SQLAlchemy's side and SQLModel just reflects that:
https://docs.sqlalchemy.org/en/20/orm/queryguide/query.html