Support Django Connection resolving in an async context

This commit is contained in:
Josh Warwick 2023-03-30 19:49:27 +01:00
parent 6a5b28d09f
commit 74998afb69

View File

@ -9,7 +9,8 @@ from graphql_relay import (
offset_to_cursor,
)
from promise import Promise
from asgiref.sync import sync_to_async
from asyncio import get_running_loop
from graphene import Int, NonNull
from graphene.relay import ConnectionField
@ -228,20 +229,43 @@ class DjangoConnectionField(ConnectionField):
# eventually leads to DjangoObjectType's get_queryset (accepts queryset)
# or a resolve_foo (does not accept queryset)
iterable = resolver(root, info, **args)
if info.is_awaitable(iterable):
async def await_result():
queryset_or_list = await iterable
if queryset_or_list is None:
queryset_or_list = default_manager
if is_async(queryset_resolver):
resolved = await sync_to_async(queryset_resolver)(connection, resolved, info, args)
# TODO: create an async_resolve_connection which uses the new Django queryset async functions
async_resolve_connection = sync_to_async(cls.resolve_connection)
if is_awaitable(resolved):
return async_resolve_connection(connection, args, await resolved, max_limit=max_limit)
return async_resolve_connection(connection, args, resolved, max_limit=max_limit)
return await_result()
if iterable is None:
iterable = default_manager
# thus the iterable gets refiltered by resolve_queryset
# but iterable might be promise
iterable = queryset_resolver(connection, iterable, info, args)
on_resolve = partial(
cls.resolve_connection, connection, args, max_limit=max_limit
)
if Promise.is_thenable(iterable):
return Promise.resolve(iterable).then(on_resolve)
try:
get_running_loop()
except RuntimeError:
pass
else:
return sync_to_async(cls.resolve_connection)(connection, args, iterable, max_limit=max_limit)
return on_resolve(iterable)
return cls.resolve_connection(connection, args, iterable, max_limit=max_limit)
def wrap_resolve(self, parent_resolver):
return partial(