Closed Philaeux closed 12 months ago
This is my software query btw:
@strawberry.type
class QuerySoftware:
@strawberry.field
def softwares(self, info) -> list[Annotated["Software", strawberry.lazy("..types")]]:
with info.context['session_factory']() as session:
sql = select(Software).order_by(Software.full_name)
return session.execute(sql).scalars().all()
Hi @Philaeux -- try inheriting from AsyncGraphQLView
instead. The loader assumes an async context is present.
GraphQLView
to AsyncGraphQLView
async def get_context
pip install flask[async]
Now I get this error which seems to be that something else should be in the bind. I'm passing a sessionmaker atm.
'sessionmaker' object has no attribute 'scalars'
GraphQL request:8:5
7 | language
8 | tags {
| ^
9 | __typename
Traceback (most recent call last):
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\graphql\execution\execute.py", line 528, in await_result
return_type, field_nodes, info, path, await result
^^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\schema\schema_converter.py", line 704, in _async_resolver
return await await_maybe(
^^^^^^^^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\utils\await_maybe.py", line 12, in await_maybe
return await value
^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry_sqlalchemy_mapper\mapper.py", line 389, in wrapper
for related_object in await resolver(self, info)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry_sqlalchemy_mapper\mapper.py", line 426, in resolve
related_objects = await loader.loader_for(relationship).load(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\dataloader.py", line 251, in dispatch_batch
values = await loader.load_fn(keys)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry_sqlalchemy_mapper\loader.py", line 73, in load_fn
rows = await self._scalars_all(query)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry_sqlalchemy_mapper\loader.py", line 54, in _scalars_all
return self._bind.scalars(*args, **kwargs).all()
^^^^^^^^^^^^^^^^^^
AttributeError: 'sessionmaker' object has no attribute 'scalars'
Stack (most recent call last):
File "C:\Program Files\Python311\Lib\threading.py", line 995, in _bootstrap
self._bootstrap_inner()
File "C:\Program Files\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
self.run()
File "C:\Program Files\Python311\Lib\threading.py", line 975, in run
self._target(*self._args, **self._kwargs)
File "C:\Program Files\Python311\Lib\concurrent\futures\thread.py", line 83, in _worker
work_item.run()
File "C:\Program Files\Python311\Lib\concurrent\futures\thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\asgiref\sync.py", line 285, in _run_event_loop
loop.run_until_complete(coro)
File "C:\Program Files\Python311\Lib\asyncio\base_events.py", line 640, in run_until_complete
self.run_forever()
File "C:\Program Files\Python311\Lib\asyncio\windows_events.py", line 321, in run_forever
super().run_forever()
File "C:\Program Files\Python311\Lib\asyncio\base_events.py", line 607, in run_forever
self._run_once()
File "C:\Program Files\Python311\Lib\asyncio\base_events.py", line 1919, in _run_once
handle._run()
File "C:\Program Files\Python311\Lib\asyncio\events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\asgiref\sync.py", line 353, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\flask\views.py", line 158, in dispatch_request
return await self.run(request=request)
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\http\async_base_view.py", line 186, in run
result = await self.execute_operation(
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\http\async_base_view.py", line 118, in execute_operation
return await self.schema.execute(
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\schema\schema.py", line 256, in execute
result = await execute(
File "C:\dev\obugs-backend\src\.env\Lib\site-packages\strawberry\schema\execute.py", line 156, in execute
process_errors(result.errors, execution_context)
Yes it works now, I though the binding should return the sessionmaker factory when in fact, it has to return a session object.
So I have this view now that fixes the problem, maybe it will help someone else in the future.
class MyGraphQLView(AsyncGraphQLView):
init_every_request = False
config = None
session_factory = None
async def get_context(self, request: Request, response: Response) -> Any:
return {
"config": MyGraphQLView.config,
"session_factory": MyGraphQLView.session_factory,
"sqlalchemy_loader": StrawberrySQLAlchemyLoader(bind=MyGraphQLView.session_factory()),
}
I have a backend in Flask, with SQLAlchemy models and strawberry for the GraphQL. I have been using Manual GraphQL Types and converting manually the SQLalchemy models to graphQL Types. Now, I am switching to this library to ditch these GQL Types and generate them from SQLAlchemy. It works fine for almost everything. I got a strange gevent error when fetcing relationships data.
Example of my models
Gennerate types this way
And finally I link it that way to flask:
The error I'm facing is the following:
when running the following request in graphql
If I remove the tag section in the querry, I get no error, so I guess I have an issue with relationships. From the error, I figuered it's because fetching relationship is done as an async task. However, because Flask is usin strawberry as a View, I guess It is a thread spawned for every request, but it has no event loop running on it. I figured that I would need to run a
asyncio.get_event_loop()
to spawn one in this new thread, but I'm not sure where to do it.If you guys have a better idea how to do it, or if I should just dump Flask for something not view based ?
Upvote & Fund