Skip to content

Commit db34d2e

Browse files
authored
fix: foreign key nullable and custom resolver (#1446)
* fix: nullable one to one relation * fix: makefile
1 parent 9a773b9 commit db34d2e

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed

Diff for: Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ dev-setup:
1010

1111
.PHONY: tests ## Run unit tests
1212
tests:
13-
py.test graphene_django --cov=graphene_django -vv
13+
PYTHONPATH=. py.test graphene_django --cov=graphene_django -vv
1414

1515
.PHONY: format ## Format code
1616
format:

Diff for: graphene_django/converter.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -302,12 +302,15 @@ def custom_resolver(root, info, **args):
302302
reversed_field_name = root.__class__._meta.get_field(
303303
field_name
304304
).remote_field.name
305-
return _type.get_queryset(
306-
_type._meta.model.objects.filter(
307-
**{reversed_field_name: root.pk}
308-
),
309-
info,
310-
).get()
305+
try:
306+
return _type.get_queryset(
307+
_type._meta.model.objects.filter(
308+
**{reversed_field_name: root.pk}
309+
),
310+
info,
311+
).get()
312+
except _type._meta.model.DoesNotExist:
313+
return None
311314

312315
return custom_resolver
313316

Diff for: graphene_django/tests/models.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ class Pet(models.Model):
1919
class FilmDetails(models.Model):
2020
location = models.CharField(max_length=30)
2121
film = models.OneToOneField(
22-
"Film", on_delete=models.CASCADE, related_name="details"
22+
"Film",
23+
on_delete=models.CASCADE,
24+
related_name="details",
25+
null=True,
26+
blank=True,
2327
)
2428

2529

Diff for: graphene_django/tests/test_query.py

+71
Original file line numberDiff line numberDiff line change
@@ -2062,3 +2062,74 @@ def resolve_person(self, info, name):
20622062
assert result.data["person"] == {
20632063
"pets": [{"name": "Jane's dog"}],
20642064
}
2065+
2066+
2067+
def test_should_query_nullable_one_to_one_relation_with_custom_resolver():
2068+
class FilmType(DjangoObjectType):
2069+
class Meta:
2070+
model = Film
2071+
2072+
@classmethod
2073+
def get_queryset(cls, queryset, info):
2074+
return queryset
2075+
2076+
class FilmDetailsType(DjangoObjectType):
2077+
class Meta:
2078+
model = FilmDetails
2079+
2080+
@classmethod
2081+
def get_queryset(cls, queryset, info):
2082+
return queryset
2083+
2084+
class Query(graphene.ObjectType):
2085+
film = graphene.Field(FilmType, genre=graphene.String(required=True))
2086+
film_details = graphene.Field(
2087+
FilmDetailsType, location=graphene.String(required=True)
2088+
)
2089+
2090+
def resolve_film(self, info, genre):
2091+
return Film.objects.filter(genre=genre).first()
2092+
2093+
def resolve_film_details(self, info, location):
2094+
return FilmDetails.objects.filter(location=location).first()
2095+
2096+
schema = graphene.Schema(query=Query)
2097+
2098+
Film.objects.create(genre="do")
2099+
FilmDetails.objects.create(location="London")
2100+
2101+
query_film = """
2102+
query getFilm($genre: String!) {
2103+
film(genre: $genre) {
2104+
genre
2105+
details {
2106+
location
2107+
}
2108+
}
2109+
}
2110+
"""
2111+
2112+
query_film_details = """
2113+
query getFilmDetails($location: String!) {
2114+
filmDetails(location: $location) {
2115+
location
2116+
film {
2117+
genre
2118+
}
2119+
}
2120+
}
2121+
"""
2122+
2123+
result = schema.execute(query_film, variables={"genre": "do"})
2124+
assert not result.errors
2125+
assert result.data["film"] == {
2126+
"genre": "DO",
2127+
"details": None,
2128+
}
2129+
2130+
result = schema.execute(query_film_details, variables={"location": "London"})
2131+
assert not result.errors
2132+
assert result.data["filmDetails"] == {
2133+
"location": "London",
2134+
"film": None,
2135+
}

0 commit comments

Comments
 (0)