graphql-python / graphene-django

Build powerful, efficient, and flexible GraphQL APIs with seamless Django integration.
http://docs.graphene-python.org/projects/django/en/latest/
MIT License
4.3k stars 769 forks source link

Cannot reference Object defined later in file when using DjangoListField #1225

Open liliserf opened 3 years ago

liliserf commented 3 years ago

When trying to reference an object that's defined later in the file...

This works:

class Foo(graphene.ObjectType):
    bars = graphene.List(graphene.NonNull(lambda: Bar))

class Bar(graphene.ObjectType):
    baz = graphene.String()

This does not work:

class Foo(graphene.ObjectType):
    bars = DjangoListField(lambda: Bar)

class Bar(graphene.ObjectType):
    baz = graphene.String()

When using DjangoListField it returns:

web_1       | Traceback (most recent call last):
web_1       |   File "/usr/local/lib/python3.9/threading.py", line 954, in _bootstrap_inner
web_1       |     self.run()
web_1       |   File "/usr/local/lib/python3.9/threading.py", line 892, in run
web_1       |     self._target(*self._args, **self._kwargs)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/utils/autoreload.py", line 54, in wrapper
web_1       |     fn(*args, **kwargs)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
web_1       |     self.check(display_num_errors=True)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 387, in check
web_1       |     all_issues = self._run_checks(
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 377, in _run_checks
web_1       |     return checks.run_checks(**kwargs)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/core/checks/registry.py", line 72, in run_checks
web_1       |     new_errors = check(app_configs=app_configs)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/core/checks/urls.py", line 13, in check_url_config
web_1       |     return check_resolver(resolver)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/core/checks/urls.py", line 23, in check_resolver
web_1       |     return check_method()
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/urls/resolvers.py", line 399, in check
web_1       |     for pattern in self.url_patterns:
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/utils/functional.py", line 80, in __get__
web_1       |     res = instance.__dict__[self.name] = self.func(instance)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/urls/resolvers.py", line 584, in url_patterns
web_1       |     patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/utils/functional.py", line 80, in __get__
web_1       |     res = instance.__dict__[self.name] = self.func(instance)
web_1       |   File "/usr/local/lib/python3.9/site-packages/django/urls/resolvers.py", line 577, in urlconf_module
web_1       |     return import_module(self.urlconf_name)
web_1       |   File "/usr/local/lib/python3.9/importlib/__init__.py", line 127, in import_module
web_1       |     return _bootstrap._gcd_import(name[level:], package, level)
web_1       |   File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
web_1       |   File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
web_1       |   File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
web_1       |   File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
web_1       |   File "<frozen importlib._bootstrap_external>", line 855, in exec_module
web_1       |   File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
web_1       |   File "/usr/src/app/book_club/urls.py", line 10, in <module>
web_1       |     from .club_api.schema import views as graphql_views
web_1       |   File "/usr/src/app/book_club/club_api/schema/views.py", line 8, in <module>
web_1       |     from book_club.app_schema import schema as app_schema
web_1       |   File "/usr/src/app/book_club/app_schema.py", line 5, in <module>
web_1       |     from book_club.club_api.schema import app_mutations, app_queries
web_1       |   File "/usr/src/app/book_club/club_api/schema/app_mutations.py", line 44, in <module>
web_1       |     from .app_objects import (
web_1       |   File "/usr/src/app/book_club/club_api/schema/app_objects.py", line 1012, in <module>
web_1       |     class Foo(graphene.ObjectType):
web_1       |   File "/usr/src/app/book_club/club_api/schema/app_objects.py", line 1013, in Foo
web_1       |     bars = DjangoListField(lambda: Bar)
web_1       |   File "/usr/local/lib/python3.9/site-packages/graphene_django/fields.py", line 32, in __init__
web_1       |     self._underlying_type, DjangoObjectType
web_1       |   File "/usr/local/lib/python3.9/site-packages/graphene_django/fields.py", line 38, in _underlying_type
web_1       |     while hasattr(_type, "of_type"):
web_1       |   File "/usr/local/lib/python3.9/site-packages/graphene/types/structures.py", line 25, in of_type
web_1       |     return get_type(self._of_type)
web_1       |   File "/usr/local/lib/python3.9/site-packages/graphene/types/utils.py", line 45, in get_type
web_1       |     return _type()
web_1       |   File "/usr/src/app/book_club/club_api/schema/app_objects.py", line 1013, in <lambda>
web_1       |     bars = DjangoListField(lambda: Bar)
web_1       | NameError: name 'Bar' is not defined
indigane commented 2 years ago

This also happens with string imports, which are commonly used to work around these kind of import issues.

The cause is this assertion in DjangoListField https://github.com/graphql-python/graphene-django/blob/775644b/graphene_django/fields.py#L33-L35

If commented out, everything works as expected.