Skip to content

Commit bb6da28

Browse files
committed
Merge branch 'master' into form_mutations
2 parents a9e5beb + 883d177 commit bb6da28

File tree

7 files changed

+87
-17
lines changed

7 files changed

+87
-17
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ env:
3838
matrix:
3939
fast_finish: true
4040
include:
41+
- python: '3.4'
42+
env: TEST_TYPE=build DJANGO_VERSION=2.0
43+
- python: '3.5'
44+
env: TEST_TYPE=build DJANGO_VERSION=2.0
45+
- python: '3.6'
46+
env: TEST_TYPE=build DJANGO_VERSION=2.0
4147
- python: '2.7'
4248
env: TEST_TYPE=build DJANGO_VERSION=1.8
4349
- python: '2.7'

examples/starwars/models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,23 @@
55

66
class Character(models.Model):
77
name = models.CharField(max_length=50)
8-
ship = models.ForeignKey('Ship', blank=True, null=True, related_name='characters')
8+
ship = models.ForeignKey('Ship', on_delete=models.CASCADE, blank=True, null=True, related_name='characters')
99

1010
def __str__(self):
1111
return self.name
1212

1313

1414
class Faction(models.Model):
1515
name = models.CharField(max_length=50)
16-
hero = models.ForeignKey(Character)
16+
hero = models.ForeignKey(Character, on_delete=models.CASCADE)
1717

1818
def __str__(self):
1919
return self.name
2020

2121

2222
class Ship(models.Model):
2323
name = models.CharField(max_length=50)
24-
faction = models.ForeignKey(Faction, related_name='ships')
24+
faction = models.ForeignKey(Faction, on_delete=models.CASCADE, related_name='ships')
2525

2626
def __str__(self):
2727
return self.name

graphene_django/fields.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ def get_manager(self):
6767

6868
@classmethod
6969
def merge_querysets(cls, default_queryset, queryset):
70+
if default_queryset.query.distinct and not queryset.query.distinct:
71+
queryset = queryset.distinct()
72+
elif queryset.query.distinct and not default_queryset.query.distinct:
73+
default_queryset = default_queryset.distinct()
7074
return queryset & default_queryset
7175

7276
@classmethod

graphene_django/filter/filterset.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ def filter_for_reverse_field(cls, f, name):
5757
Global IDs (the default implementation expects database
5858
primary keys)
5959
"""
60-
rel = f.field.remote_field if hasattr(f.field, 'remote_field') else f.field.rel
60+
try:
61+
rel = f.field.remote_field
62+
except AttributeError:
63+
rel = f.field.rel
64+
6165
default = {
6266
'name': name,
6367
'label': capfirst(rel.related_name)

graphene_django/forms/converter.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,6 @@ def convert_form_field_to_id(field):
8585
return ID(required=field.required)
8686

8787

88-
@convert_form_field.register(forms.DateField)
89-
@convert_form_field.register(forms.DateTimeField)
90-
def convert_form_field_to_datetime(field):
91-
return DateTime(description=field.help_text, required=field.required)
92-
93-
9488
@convert_form_field.register(forms.TimeField)
9589
def convert_form_field_to_time(field):
9690
return Time(description=field.help_text, required=field.required)

graphene_django/tests/models.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ class Pet(models.Model):
1515

1616
class FilmDetails(models.Model):
1717
location = models.CharField(max_length=30)
18-
film = models.OneToOneField('Film', related_name='details')
18+
film = models.OneToOneField('Film', on_delete=models.CASCADE, related_name='details')
1919

2020

2121
class Film(models.Model):
22+
genre = models.CharField(max_length=2, help_text='Genre', choices=[
23+
('do', 'Documentary'),
24+
('ot', 'Other')
25+
], default='ot')
2226
reporters = models.ManyToManyField('Reporter',
2327
related_name='films')
2428

@@ -70,8 +74,8 @@ class Article(models.Model):
7074
headline = models.CharField(max_length=100)
7175
pub_date = models.DateField()
7276
pub_date_time = models.DateTimeField()
73-
reporter = models.ForeignKey(Reporter, related_name='articles')
74-
editor = models.ForeignKey(Reporter, related_name='edited_articles_+')
77+
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE, related_name='articles')
78+
editor = models.ForeignKey(Reporter, on_delete=models.CASCADE, related_name='edited_articles_+')
7579
lang = models.CharField(max_length=2, help_text='Language', choices=[
7680
('es', 'Spanish'),
7781
('en', 'English')

graphene_django/tests/test_query.py

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from django.utils.functional import SimpleLazyObject
66
from py.test import raises
77

8+
from django.db.models import Q
9+
810
import graphene
911
from graphene.relay import Node
1012

@@ -17,6 +19,8 @@
1719
Article,
1820
CNNReporter,
1921
Reporter,
22+
Film,
23+
FilmDetails,
2024
)
2125

2226
pytestmark = pytest.mark.django_db
@@ -431,6 +435,60 @@ class Query(graphene.ObjectType):
431435
assert result.data == expected
432436

433437

438+
@pytest.mark.skipif(not DJANGO_FILTER_INSTALLED,
439+
reason="django-filter should be installed")
440+
def test_should_query_node_filtering_with_distinct_queryset():
441+
class FilmType(DjangoObjectType):
442+
443+
class Meta:
444+
model = Film
445+
interfaces = (Node, )
446+
filter_fields = ('genre',)
447+
448+
class Query(graphene.ObjectType):
449+
films = DjangoConnectionField(FilmType)
450+
451+
# def resolve_all_reporters_with_berlin_films(self, args, context, info):
452+
# return Reporter.objects.filter(Q(films__film__location__contains="Berlin") | Q(a_choice=1))
453+
454+
def resolve_films(self, info, **args):
455+
return Film.objects.filter(Q(details__location__contains="Berlin") | Q(genre__in=['ot'])).distinct()
456+
457+
f = Film.objects.create(
458+
)
459+
fd = FilmDetails.objects.create(
460+
location="Berlin",
461+
film=f
462+
)
463+
464+
schema = graphene.Schema(query=Query)
465+
query = '''
466+
query NodeFilteringQuery {
467+
films {
468+
edges {
469+
node {
470+
genre
471+
}
472+
}
473+
}
474+
}
475+
'''
476+
477+
expected = {
478+
'films': {
479+
'edges': [{
480+
'node': {
481+
'genre': 'OT'
482+
}
483+
}]
484+
}
485+
}
486+
487+
result = schema.execute(query)
488+
assert not result.errors
489+
assert result.data == expected
490+
491+
434492
@pytest.mark.skipif(not DJANGO_FILTER_INSTALLED,
435493
reason="django-filter should be installed")
436494
def test_should_query_node_multiple_filtering():
@@ -676,7 +734,7 @@ class Query(graphene.ObjectType):
676734

677735
def resolve_all_reporters(self, info, **args):
678736
return Promise.resolve([Reporter(id=1)])
679-
737+
680738
schema = graphene.Schema(query=Query)
681739
query = '''
682740
query ReporterPromiseConnectionQuery {
@@ -724,7 +782,7 @@ class Query(graphene.ObjectType):
724782

725783
def resolve_all_reporters(self, info, **args):
726784
return Reporter.objects.all()
727-
785+
728786
schema = graphene.Schema(query=Query)
729787
query = '''
730788
query ReporterLastQuery {
@@ -779,7 +837,7 @@ class Query(graphene.ObjectType):
779837

780838
def resolve_all_reporters(self, info, **args):
781839
return Reporter.objects.all()
782-
840+
783841
schema = graphene.Schema(query=Query)
784842
query = '''
785843
query ReporterLastQuery {
@@ -1012,7 +1070,7 @@ def test_proxy_model_fails():
10121070
"""
10131071
This test asserts that if you try to query for a proxy model,
10141072
that query will fail with:
1015-
GraphQLError('Expected value of type "CNNReporterType" but got:
1073+
GraphQLError('Expected value of type "CNNReporterType" but got:
10161074
CNNReporter.',)
10171075
10181076
This is because a proxy model has the identical model definition

0 commit comments

Comments
 (0)