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?
GrapheneEnum.BLUE.value
instead ofGrapheneEnum.BLUE
; as ChristopherZ has commented on the issue, this is apparently not a solution for him – Peroration