diff --git a/graphene_django/fields.py b/graphene_django/fields.py index 35bd3f0..1bbe1f3 100644 --- a/graphene_django/fields.py +++ b/graphene_django/fields.py @@ -20,17 +20,20 @@ from .utils import maybe_queryset class DjangoListField(Field): def __init__(self, _type, *args, **kwargs): - from .types import DjangoObjectType - if isinstance(_type, NonNull): _type = _type.of_type # Django would never return a Set of None vvvvvvv super().__init__(List(NonNull(_type)), *args, **kwargs) + @property + def type(self): + from .types import DjangoObjectType + assert issubclass( self._underlying_type, DjangoObjectType - ), "DjangoListField only accepts DjangoObjectType types" + ), "DjangoListField only accepts DjangoObjectType types as underlying type" + return super().type @property def _underlying_type(self): diff --git a/graphene_django/tests/models.py b/graphene_django/tests/models.py index 67e2667..ece1bb6 100644 --- a/graphene_django/tests/models.py +++ b/graphene_django/tests/models.py @@ -6,6 +6,9 @@ CHOICES = ((1, "this"), (2, _("that"))) class Person(models.Model): name = models.CharField(max_length=30) + parent = models.ForeignKey( + "self", on_delete=models.CASCADE, null=True, blank=True, related_name="children" + ) class Pet(models.Model): diff --git a/graphene_django/tests/test_fields.py b/graphene_django/tests/test_fields.py index d1c119c..e0d9ba6 100644 --- a/graphene_django/tests/test_fields.py +++ b/graphene_django/tests/test_fields.py @@ -12,17 +12,18 @@ from .models import ( Article as ArticleModel, Film as FilmModel, FilmDetails as FilmDetailsModel, + Person as PersonModel, Reporter as ReporterModel, ) class TestDjangoListField: def test_only_django_object_types(self): - class TestType(ObjectType): - foo = String() + class Query(ObjectType): + something = DjangoListField(String) - with pytest.raises(AssertionError): - DjangoListField(TestType) + with pytest.raises(TypeError): + Schema(query=Query) def test_only_import_paths(self): list_field = DjangoListField("graphene_django.tests.schema.Human") @@ -262,6 +263,69 @@ class TestDjangoListField: ] } + def test_same_type_nested_list_field(self): + class Person(DjangoObjectType): + class Meta: + model = PersonModel + fields = ("name", "parent") + + children = DjangoListField(lambda: Person) + + class Query(ObjectType): + persons = DjangoListField(Person) + + schema = Schema(query=Query) + + query = """ + query { + persons { + name + children { + name + } + } + } + """ + + p1 = PersonModel.objects.create(name="Tara") + PersonModel.objects.create(name="Debra") + + PersonModel.objects.create( + name="Toto", + parent=p1, + ) + PersonModel.objects.create( + name="Tata", + parent=p1, + ) + + result = schema.execute(query) + + assert not result.errors + assert result.data == { + "persons": [ + { + "name": "Tara", + "children": [ + {"name": "Toto"}, + {"name": "Tata"}, + ], + }, + { + "name": "Debra", + "children": [], + }, + { + "name": "Toto", + "children": [], + }, + { + "name": "Tata", + "children": [], + }, + ] + } + def test_get_queryset_filter(self): class Reporter(DjangoObjectType): class Meta: