From be20450a663073add7c7ace437cccaf2832cf4f3 Mon Sep 17 00:00:00 2001 From: Abram Booth Date: Fri, 21 Apr 2017 13:25:30 -0400 Subject: [PATCH 1/2] Don't break on inherited choices fields. Store converted Django fields in the registry, so choices enums are not created multiple times when inherited by child models. --- graphene_django/converter.py | 12 +++++++++-- graphene_django/registry.py | 8 +++++++- graphene_django/tests/test_query.py | 32 +++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/graphene_django/converter.py b/graphene_django/converter.py index b1a8837fa..d7965fcaa 100644 --- a/graphene_django/converter.py +++ b/graphene_django/converter.py @@ -41,6 +41,10 @@ def get_choices(choices): def convert_django_field_with_choices(field, registry=None): + if registry: + converted = registry.get_converted_field(field) + if converted: + return converted choices = getattr(field, 'choices', None) if choices: meta = field.model._meta @@ -56,8 +60,12 @@ def description(self): return named_choices_descriptions[self.name] enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType) - return enum(description=field.help_text, required=not field.null) - return convert_django_field(field, registry) + converted = enum(description=field.help_text, required=not field.null) + else: + converted = convert_django_field(field, registry) + if registry: + registry.register_converted_field(field, converted) + return converted @singledispatch diff --git a/graphene_django/registry.py b/graphene_django/registry.py index 21fed12cb..da1ee8514 100644 --- a/graphene_django/registry.py +++ b/graphene_django/registry.py @@ -2,7 +2,7 @@ class Registry(object): def __init__(self): self._registry = {} - self._registry_models = {} + self._field_registry = {} def register(self, cls): from .types import DjangoObjectType @@ -19,6 +19,12 @@ def register(self, cls): def get_type_for_model(self, model): return self._registry.get(model) + def register_converted_field(self, field, converted): + self._field_registry[field] = converted + + def get_converted_field(self, field): + return self._field_registry.get(field) + registry = None diff --git a/graphene_django/tests/test_query.py b/graphene_django/tests/test_query.py index 3ecd8eaa0..f1f5fdbd1 100644 --- a/graphene_django/tests/test_query.py +++ b/graphene_django/tests/test_query.py @@ -747,3 +747,35 @@ class Query(graphene.ObjectType): result = schema.execute(query) assert not result.errors assert result.data == expected + + +def test_should_handle_inherited_choices(): + class BaseModel(models.Model): + choice_field = models.IntegerField(choices=((0, 'zero'), (1, 'one'))) + + class ChildModel(BaseModel): + class Meta: + proxy = True + + class BaseType(DjangoObjectType): + class Meta: + model = BaseModel + + class ChildType(DjangoObjectType): + class Meta: + model = ChildModel + + class Query(graphene.ObjectType): + base = graphene.Field(BaseType) + child = graphene.Field(ChildType) + + schema = graphene.Schema(query=Query) + query = ''' + query { + child { + choiceField + } + } + ''' + result = schema.execute(query) + assert not result.errors From b5e7614b053f52f55cc9ce54b6d61246dadec683 Mon Sep 17 00:00:00 2001 From: Abram Booth Date: Tue, 31 Oct 2017 09:33:16 -0400 Subject: [PATCH 2/2] More specific None check. --- graphene_django/converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphene_django/converter.py b/graphene_django/converter.py index d7965fcaa..4ab16ab5d 100644 --- a/graphene_django/converter.py +++ b/graphene_django/converter.py @@ -41,7 +41,7 @@ def get_choices(choices): def convert_django_field_with_choices(field, registry=None): - if registry: + if registry is not None: converted = registry.get_converted_field(field) if converted: return converted @@ -63,7 +63,7 @@ def description(self): converted = enum(description=field.help_text, required=not field.null) else: converted = convert_django_field(field, registry) - if registry: + if registry is not None: registry.register_converted_field(field, converted) return converted