diff --git a/graphene_django/fields.py b/graphene_django/fields.py index 0fe123d..80107ea 100644 --- a/graphene_django/fields.py +++ b/graphene_django/fields.py @@ -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(