Enums in Django and Graphene always result in null
Asked Answered
P

0

6

I am having some issues trying to use enums with Django and Graphene. Even though the values of the enum are persisted in the SQLite and are retrieved properly, it keeps resulting in an error. Below is a sample of the error.

{
  "message": "Cannot return null for non-nullable field DjangoObject.vanillaEnum.",
  "locations": [
    {
      "line": 10,
      "column": 5
    }
  ]
},

I'm using Django 2.0.3 and Graphene 2.0.1 with Anaconda3 5.0.0 and Python 3.6.4. I managed to reproduce the error using a trivial example, which is available on my GitHub account.

In the models.py, I defined a Python Enum and a Django model that uses that enum. The models here work as intended (AFAIK) without involving any Graphene dependencies. The default SQLite database also appears to have the correct values.

models.py

import enum
from django.db import models

@enum.unique
class VanillaEnum(enum.Enum):
    RED = enum.auto()
    BLUE = enum.auto()
    GREEN = enum.auto()

    @classmethod
    def choices(cls):
        return tuple((x, x) for x in cls)

class DjangoModel(models.Model):
    name = models.CharField(max_length=20)
    vanilla_enum = models.CharField(choices=VanillaEnum.choices(), default=VanillaEnum.GREEN, max_length=20)

    def __str__(self):
        return f'name={self.name}, vanilla_enun={self.vanilla_enum}'

Next, in the schema.py, I defined the two enums. One uses the graphene.Enum.from_enum to convert the VanillaEnum into one that supposedly Graphene can use. The second one is an enum using graphene.Enum. The second enum is my control case, which should work. But it still results in the same error as above.

Then I defined two objects, a native Graphene object that uses both enums as fields, and a Django-Graphene object that is mapped to the model.

schema.py

import graphene
from graphene_django import DjangoObjectType
from djangographeneenum.models import DjangoModel, VanillaEnum

ConvertedEnum = graphene.Enum.from_enum(VanillaEnum)

class GrapheneEnum(graphene.Enum):
    RED = 1
    BLUE = 2
    GREEN = 3

class GrapheneObject(graphene.ObjectType):
    name = graphene.String()
    converted_enum = graphene.Field(ConvertedEnum)
    graphene_enum = graphene.Field(GrapheneEnum)

    def __str__(self):
        return f'name={self.name}, converted_enum={self.converted_enum}, graphene_enum={self.graphene_enum}'

class DjangoObject(DjangoObjectType):
    class Meta:
        model = DjangoModel

class Query(graphene.ObjectType):
    graphene_object = graphene.Field(GrapheneObject)
    django_model = graphene.List(DjangoObject)

    def resolve_graphene_object(self, info):
        graphene_object = GrapheneObject(name='Abc', converted_enum=ConvertedEnum.RED, graphene_enum=GrapheneEnum.BLUE)
        print(f'graphene_object: {graphene_object}')
        return graphene_object

    def resolve_django_model(self, info):
        django_model = DjangoModel.objects.get_or_create(name='RED Model', vanilla_enum=VanillaEnum.RED)
        print(f'django_model: {django_model}')
        django_model = DjangoModel.objects.get_or_create(name='BLUE Model', vanilla_enum=VanillaEnum.BLUE)
        print(f'django_model: {django_model}')
        django_model = DjangoModel.objects.get_or_create(name='GREEN Model', vanilla_enum=VanillaEnum.GREEN)
        print(f'django_model: {django_model}')
        objects_all = DjangoModel.objects.all()
        for x in objects_all:
            print(f'django_model: {x}')
        return objects_all

Below is a partial output. The enums in the native Graphene object both show up as null. And for the mapped Django model, the entire object is null and not just the enum field.

  "data": {
    "grapheneObject": {
      "name": "Abc",
      "convertedEnum": null,
      "grapheneEnum": null
    },
    "djangoModel": [
      null,
      null,
      null,
      null
    ]
  }

So, what am I missing?

Putout answered 11/3, 2018 at 15:32 Comment(2)
For people with the same problem, there is a related issue here: github.com/graphql-python/graphene/issues/558 A workaround is to use GrapheneEnum.BLUE.value instead of GrapheneEnum.BLUE; as ChristopherZ has commented on the issue, this is apparently not a solution for himPeroration
I had the familiar issue. Changing the way I store values in the database helped. See my comment github.com/graphql-python/graphene-django/issues/…Commonality

© 2022 - 2024 — McMap. All rights reserved.