Skip to content

Commit 8834113

Browse files
committed
fix: nullable one to one relation
1 parent 3172710 commit 8834113

File tree

3 files changed

+85
-7
lines changed

3 files changed

+85
-7
lines changed

graphene_django/converter.py

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

313316
return custom_resolver
314317

graphene_django/tests/models.py

Lines changed: 5 additions & 1 deletion
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

graphene_django/tests/test_query.py

Lines changed: 71 additions & 0 deletions
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)