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.

DjangoObjectType interprets string choices fields as required in schema even with blank=True attribute

See original GitHub issue

To reproduce this problem, create a Django model with a choices field with blank=True:

class MyModel(models.Model):
    PERIODIC_INTERVAL_CHOICES = (('Weekly', 'Weekly'),
         ('Bi-Weekly', 'Bi-Weekly'),
          ('Monthly', 'Monthly'),
          ('Quarterly', 'Quarterly'),
          ('Semi-Annually', 'Semi-Annually'),
          'Annually', 'Annually'))
    
    payment_frequency = models.CharField(
        blank=True,
        choices=PERIODIC_INTERVAL_CHOICES,
        max_length=13)

The schema generated by DjangoObjectType will show incorrectly show that this field payment_frequency is required. This is incorrect – the expected behavior is that it NOT required.

I have been able to fix this issue by patching how the value of required is determined in graphene.converter.convert_django_field_with_choices (shown for graphene-django 2.0.0) :

def convert_django_field_with_choices(field, registry=None):
    # Modified from graphene_django.converter import convert_django_field_with_choices
    # to adjust "required"
    choices = getattr(field, 'choices', None)
    if choices:
        meta = field.model._meta
        name = to_camel_case('{}_{}'.format(meta.object_name, field.name))
        choices = list(get_choices(choices))
        named_choices = [(c[0], c[1]) for c in choices]
        named_choices_descriptions = {c[0]: c[2] for c in choices}

        class EnumWithDescriptionsType(object):

            @property
            def description(self):
                return named_choices_descriptions[self.name]

        enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType)
        required = not (field.blank or field.null or field.default)  # MODIFIED FROM ORIGINAL
        return enum(description=field.help_text, required=required)
    return convert_django_field(field, registry)

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8

github_iconTop GitHub Comments

5reactions
coltonbhcommented, Jul 15, 2019

Just want to add a bump to this thread after spending some time dealing with this issue. Django specifies that empty CharFields should be represented as “” rather than None so that there is only one representation of an empty field (“” rather than “” and None). This means setting blank=True and NOT setting null=True on the CharField model definition (https://docs.djangoproject.com/en/2.2/ref/models/fields/#null). Graphene-django v2.4.0 does not handle this case correctly. CharFields with blank=True show as required and will raise an error: "Expected a value of type "{field_from_choices_array}" but received: ", Graphene-django is saying the field is required to be defined and that the “” value is not allowed; however, the “” character is indeed an allowed character for this field in django–in fact it’s the idiomatic character for an empty CharField.

While this thread suggests that explicitly defining the blank field is more idiomatic, django already has a default value for blank CharFields, “”, and using this seems like a sensible default for Graphene-django rather than requiring the “” field to be explicitly defined a la this thread on every CHOICES array that is set on a CharField(blank=True).

Additionally, if I define a “” choice for my CharField(blank=True) as per the suggestions in the links above, graphene-django returns an “A_” value for the blank field–less than ideal.

I’d suggest that and CharField(blank=True) with a choices set should be correctly identified by graphene in the schema as NOT required and to correctly handle a “” value from django by returning a “” value to the GQL client.

0reactions
cansincommented, Jun 16, 2020

I am still having this exact issue even after the #714 . Anyone else experiencing the same problem?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Queries & ObjectTypes - Graphene-Python
Graphene-Django ships with a special DjangoObjectType that automatically transforms a ... set all fields that should be exposed using the fields attribute.
Read more >
Django ForeignKey field ignored by graphene-django when ...
When you look into the debugger you will see that field.related_model is already resolved: Django does this, graphene doesn't even see the ...
Read more >
Django + Graphene: From REST to GraphQL - FullStack Labs
The DjangoObjectType by default includes all the fields in the model, but we can explicitly add or exclude any fields we want. The...
Read more >
Graphene Documentation - Read the Docs
If you want to expose your data through GraphQL - read the Installation, Schema and Queries section. For more advanced use, check out...
Read more >
JSONField Models in Graphene Django - Jerry Ng
The meta field is returned as a JSON string rather than a JSON ... meta field type in your DjangoObjectType to GenericScalar such...
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