Add sessionmaker #1704
-
First Check
Commit to Help
Example CodeSession = sessionmaker(engine)DescriptionAdd an sqlalchemy compatible sessionmaker that generates SqlModel sessions Wanted SolutionI would like to have a working sessionmaker Wanted Codefrom sqlmodel import sessionmakerAlternativesNo response Operating SystemmacOS Operating System DetailsNo response SQLModel Version0.0.4 Python Version3.9.6 Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 12 comments
-
|
Please add this because now it give error that .exec() does not exist on session if you using sqlalchemy import. |
Beta Was this translation helpful? Give feedback.
-
|
I faced the same issue and it looks like SQLAlchemy's |
Beta Was this translation helpful? Give feedback.
-
|
Why do you want a sessionmaker instead of using the new/future and more modern approach of using a Just for completeness, AFAIK, the sessionmaker exists mainly because there was no |
Beta Was this translation helpful? Give feedback.
-
My understanding is that the point of the sessionmaker is so that you don't have to pass the configuration (e.g. the engine) to the Session every time. https://docs.sqlalchemy.org/en/14/orm/session_basics.html#using-a-sessionmaker |
Beta Was this translation helpful? Give feedback.
-
|
You can achieve the desired functionality like this: from sqlmodel import Session as SQLModelSession
from contextlib import contextmanager
engine = ...
@contextmanager
def Session():
session = SQLModelSession(engine)
try:
yield session
finally:
session.close()Then, you can use with Session() as session:
... |
Beta Was this translation helpful? Give feedback.
-
|
I faced a similar issue when I tried to call I found that if you use Sessionmaker like the below, you will get an instance of from sqlalchemy.orm import sessionmaker
SessionLocal = sessionmaker(autoflush=False , bind=engine)to fix the issue, just like @olzhasar mentioned, you have to pass from sqlmodel import Session as SQLModelSession
SessionLocal = sessionmaker(class_ = SQLModelSession, autoflush=False , bind=engine)
def get_session():
with SessionLocal() as session:
yield session
Session = Annotated[SQLModelSession, Depends(get_session)]
# endpoint
@router.get("/db-test")
async def db_test(session: Session):
statement = select(User)
results = session.exec(statement)
user = results.first()
return user |
Beta Was this translation helpful? Give feedback.
-
|
@seanhuang514 provided a workaround. If the underlying issue were understood it would be trivial to fix. Then the workaround would be unnecessary. sessionmaker has kwarg
^^ makes a subclass of >>> from sqlalchemy.orm.session import sessionmaker
>>> from sqlalchemy.orm.session import Session as Session_
>>>
>>> from sqlmodel.orm.session import Session
>>>
>>> msg = "Good guys finish last! Brand your Session as SessionSM"
>>> assert Session.__name__ != Session_.__name__, msg
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Good guys finish last! Brand your Session as SessionSM
>>> SesMaker = sessionmaker(class_=Session)
>>> Session_.__mro__
(<class 'sqlalchemy.orm.session.Session'>, <class 'sqlalchemy.orm.session._SessionClassMethods'>, <class 'sqlalchemy.event.registry.EventTarget'>, <class 'object'>)
>>> Session.__mro__
(<class 'sqlmodel.orm.session.Session'>, <class 'sqlalchemy.orm.session.Session'>, <class 'sqlalchemy.orm.session._SessionClassMethods'>, <class 'sqlalchemy.event.registry.EventTarget'>, <class 'object'>)
>>> SesMaker.class_.__mro__
(<class 'sqlalchemy.orm.session.Session'>, <class 'sqlmodel.orm.session.Session'>, <class 'sqlalchemy.orm.session.Session'>, <class 'sqlalchemy.orm.session._SessionClassMethods'>, <class 'sqlalchemy.event.registry.EventTarget'>, <class 'object'>)
>>> mro_dodgy = [kls.__qualname__ for kls in SesMaker.class_.__mro__]
>>> mro_dodgy
['Session', 'Session', 'Session', '_SessionClassMethods', 'EventTarget', 'object']
>>> assert mro_dodgy.count("Session") == 1
FalseAfter the refactor this ^^ test should pass. Failing now cuz "Session" occurs 3 times. The solution is: class naming cannot be "Session". Name it anything else, except:
My suggestion for naming:
SM is short for sqlmodel. seanhuang514 suggestion, i object to.
After renaming both classes, sessions created with Bite the bullet, take the bitter pill, and refactor! Every test (docs, issues, discussions, web article, AI bot response) that uses Session or AsyncSession will need to be modified to use new class naming. Unfortunately the refactor will be a breaking change (major version release) for anyone importing Please relabel this as a (subtle) bug rather than a feature request. Gentlemen grab the popcorn and beer. What comes after is going to be epic! CC @tiangolo |
Beta Was this translation helpful? Give feedback.
-
|
To help visualize the issue, a fixed mro would look precisely like: Notice "Session" occurs only one. "SessionSM" could be added to 'sqlalchemy.orm.session' namespace whereas "Session" couldn't because it already exists within 'sqlalchemy.orm.session' namespace. Once you see it, you can't unsee it. |
Beta Was this translation helpful? Give feedback.
-
|
#81 does not fix the issue. It simply reflects a desperate desire for sqlmodel to have a wrapper of sessionmaker. The wrapped sessionmaker suffers from / repeats the same issue. This children is why we write tests to prove code, not only works, but actually resolves the issue. No such tests came along with the PR. The PR is also ridiculous and childish, but may bring a smile to your face. Just for the comic value, recommend reading it. Whoever closed the PR is now vindicated. Thanks for saving us from going down the wrong path. |
Beta Was this translation helpful? Give feedback.
-
|
Created upstream discussion to confirm this is can be elevated to SQLA issue status |
Beta Was this translation helpful? Give feedback.
-
|
Fixing sqlmodel#75 seanhuang514 example. The point is to demonstrate The line:
Renaming Session to SQLModelSession has no effect on method availability or class behavior. The .exec() method is lost only when using the wrong session class — not due to import naming. |
Beta Was this translation helpful? Give feedback.
-
|
Please read sqlalchemy/sqlalchemy#13054 to see how two classes can have the same sqlmodel.orm.session.Session and sqlmodel.ext.asyncio.session.AsyncSession do not have to be renamed. It's a good idea to avoid confusion, but it's not absolutely necessary. |
Beta Was this translation helpful? Give feedback.
You can achieve the desired functionality like this:
Then, you can use
Sessionas a context manager without passing the engine every time: