Cannot serialize a CharField with Choices and blank=True
See original GitHub issue- What is the current behavior?
Trying to return a value of a field such as models.CharField(choices=some_choices, blank=True, max_length=64)
with a blank value from Graphene causes a graphql.error.base.GraphQLError: Expected a value of type "SomeChoice" but received:
Reproduction is at https://repl.it/repls/WaryRespectfulTrace#README.md
Given a model such as:
from django.db import models
from model_utils.models import UUIDModel
from django.utils.translation import gettext_lazy as _
class Person(UUIDModel, models.Model):
class Gender(models.TextChoices):
MALE = "male", _("Male")
FEMALE = "female", _("Female")
OTHER = "other", _("Other")
gender = models.CharField(choices=Gender.choices, blank=True, max_length=64)
and a type such as:
from graphene_django import DjangoObjectType
class PersonType(DjangoObjectType):
class Meta:
model = Person
use_connection = True
and a query such as:
import graphene
class Query(graphene.ObjectType):
person = graphene.Field(PersonType, id=graphene.UUID())
@classmethod
def resolve_person(cls, root, info, id):
return Person.objects.get(id=id)
Running a GraphQL such as:
query {
person(id: "some-uuid") {
id
gender
}
}
results in a graphql.error.base.GraphQLError: Expected a value of type "PersonGender" but received:
iff the person’s gender value is blank.
The stacktrace is:
Traceback (most recent call last):
File "/Users/user/.virtualenvs/code/lib/python3.7/site-packages/promise/promise.py", line 87, in try_catch
return (handler(*args, **kwargs), None)
File "/Users/user/.virtualenvs/code/lib/python3.7/site-packages/graphql/execution/executor.py", line 532, in <lambda>
exe_context, return_type, field_asts, info, path, resolved
File "/Users/user/.virtualenvs/code/lib/python3.7/site-packages/graphql/execution/executor.py", line 563, in complete_value
return complete_leaf_value(return_type, path, result)
File "/Users/user/.virtualenvs/code/lib/python3.7/site-packages/graphql/execution/executor.py", line 633, in complete_leaf_value
path=path,
graphql.error.base.GraphQLError: Expected a value of type "PersonGender" but received:
- What is the expected behavior?
The empty value should be successfully returned.
- What is the motivation / use case for changing the behavior?
Left unfixed, the clients are receiving an erroneous error (pun intended 😛). This is especially problematic when we are trying to distinguish between an error state vs a valid state.
-
Please tell us about your environment:
- Version:
Django==3.0.7
django-cors-headers==3.2.1
django-environ==0.4.5
django-extensions==2.2.9
django-filter==2.2.0
django-graphql-jwt==0.3.1
django-heroku==0.3.1
django-model-utils==4.0.0
django-polymorphic==2.1.2
django-redis-cache==2.1.0
django-rq==2.3.0
django-sendgrid-v5==0.8.1
graphene==2.1.8
graphene-django==2.10.1
graphene-stubs==0.15
graphql-core==2.3.2
graphql-relay==2.0.1
- Platform:
Python 3.7.3
- Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)
I realize a similar issue was previously reported at https://github.com/graphql-python/graphene-django/issues/503 and https://github.com/graphql-python/graphene-django/pull/714 and fixed at https://github.com/graphql-python/graphene-django/pull/714 .
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:5 (1 by maintainers)
Top GitHub Comments
@cansin thanks for the detailed error report. This does look like a bug and I’ll look into it as soon as possible. As a workaround you can update your
PersonType
DjangoObjectType with a custom resolver for the gender field:I’ve run into this as well. It seems that another workaround is to add an “empty” choice to the set of choices:
However, this is redundant to setting
blank=True
on the field and IMO should be avoided. Would love to see the field convertor pick upblank=True
and adjust accordingly on its own.