diff --git a/graphene_django/fields.py b/graphene_django/fields.py index e755b93..5576454 100644 --- a/graphene_django/fields.py +++ b/graphene_django/fields.py @@ -67,6 +67,10 @@ class DjangoConnectionField(ConnectionField): @classmethod def merge_querysets(cls, default_queryset, queryset): + if default_queryset.query.distinct and not queryset.query.distinct: + queryset = queryset.distinct() + elif queryset.query.distinct and not default_queryset.query.distinct: + default_queryset = default_queryset.distinct() return queryset & default_queryset @classmethod diff --git a/graphene_django/tests/models.py b/graphene_django/tests/models.py index 6ae705d..029b318 100644 --- a/graphene_django/tests/models.py +++ b/graphene_django/tests/models.py @@ -19,6 +19,10 @@ class FilmDetails(models.Model): class Film(models.Model): + genre = models.CharField(max_length=2, help_text='Genre', choices=[ + ('do', 'Documentary'), + ('ot', 'Other') + ], default='ot') reporters = models.ManyToManyField('Reporter', related_name='films') diff --git a/graphene_django/tests/test_query.py b/graphene_django/tests/test_query.py index cb2bde4..09ca702 100644 --- a/graphene_django/tests/test_query.py +++ b/graphene_django/tests/test_query.py @@ -5,6 +5,8 @@ from django.db import models from django.utils.functional import SimpleLazyObject from py.test import raises +from django.db.models import Q + import graphene from graphene.relay import Node @@ -17,6 +19,8 @@ from .models import ( Article, CNNReporter, Reporter, + Film, + FilmDetails, ) pytestmark = pytest.mark.django_db @@ -431,6 +435,60 @@ def test_should_query_node_filtering(): assert result.data == expected +@pytest.mark.skipif(not DJANGO_FILTER_INSTALLED, + reason="django-filter should be installed") +def test_should_query_node_filtering_with_distinct_queryset(): + class FilmType(DjangoObjectType): + + class Meta: + model = Film + interfaces = (Node, ) + filter_fields = ('genre',) + + class Query(graphene.ObjectType): + films = DjangoConnectionField(FilmType) + + # def resolve_all_reporters_with_berlin_films(self, args, context, info): + # return Reporter.objects.filter(Q(films__film__location__contains="Berlin") | Q(a_choice=1)) + + def resolve_films(self, info, **args): + return Film.objects.filter(Q(details__location__contains="Berlin") | Q(genre__in=['ot'])).distinct() + + f = Film.objects.create( + ) + fd = FilmDetails.objects.create( + location="Berlin", + film=f + ) + + schema = graphene.Schema(query=Query) + query = ''' + query NodeFilteringQuery { + films { + edges { + node { + genre + } + } + } + } + ''' + + expected = { + 'films': { + 'edges': [{ + 'node': { + 'genre': 'OT' + } + }] + } + } + + result = schema.execute(query) + assert not result.errors + assert result.data == expected + + @pytest.mark.skipif(not DJANGO_FILTER_INSTALLED, reason="django-filter should be installed") def test_should_query_node_multiple_filtering(): @@ -676,7 +734,7 @@ def test_should_query_promise_connectionfields(): def resolve_all_reporters(self, info, **args): return Promise.resolve([Reporter(id=1)]) - + schema = graphene.Schema(query=Query) query = ''' query ReporterPromiseConnectionQuery { @@ -724,7 +782,7 @@ def test_should_query_connectionfields_with_last(): def resolve_all_reporters(self, info, **args): return Reporter.objects.all() - + schema = graphene.Schema(query=Query) query = ''' query ReporterLastQuery { @@ -779,7 +837,7 @@ def test_should_query_connectionfields_with_manager(): def resolve_all_reporters(self, info, **args): return Reporter.objects.all() - + schema = graphene.Schema(query=Query) query = ''' query ReporterLastQuery { @@ -1012,7 +1070,7 @@ def test_proxy_model_fails(): """ This test asserts that if you try to query for a proxy model, that query will fail with: - GraphQLError('Expected value of type "CNNReporterType" but got: + GraphQLError('Expected value of type "CNNReporterType" but got: CNNReporter.',) This is because a proxy model has the identical model definition