question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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:open
  • Created 3 years ago
  • Reactions:5
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
jkimbocommented, Jul 15, 2020

@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:

class PersonType(DjangoObjectType):
    class Meta:
        model = Person
        use_connection = True

    def resolve_gender(person, info):
      if person.gender:
        return person.gender
      return None
0reactions
jeremystretchcommented, Jun 29, 2021

I’ve run into this as well. It seems that another workaround is to add an “empty” choice to the set of choices:

field_choices = (
    ('', '--------'),
    ('foo', 'Foo'),
    ('bar', 'Bar'),
)

However, this is redundant to setting blank=True on the field and IMO should be avoided. Would love to see the field convertor pick up blank=True and adjust accordingly on its own.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Django Rest Framework with ChoiceField - Stack Overflow
Essentially what I'm trying to do is to have the get/post/put methods use the display value of the choice field instead of the...
Read more >
Model field reference - Django documentation
One exception is when a CharField has both unique=True and blank=True set. ... field options like default because they can't be serialized by...
Read more >
Tutorial 1: Serialization - Django REST framework
Tutorial 1: Serialization. Introduction. This tutorial will cover creating a simple pastebin code highlighting Web API. Along the way it will introduce the ......
Read more >
Serializers - Django REST framework - Tom Christie
Serializers; Declaring Serializers; Serializing objects ... However, it's not a trivial problem, and it will take some serious design work.
Read more >
How to Serialize Data With Django REST Framework
Data can be serialized in DRF in just a few different methods, ... CharField(blank=True, null=True, max_length=85) ... This should fix the problem.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found