Add BlankField and mount enums using it

This commit is contained in:
Jonathan Kim 2020-07-22 09:36:29 +01:00
parent 8571bc465a
commit fd2dd3adae
2 changed files with 74 additions and 9 deletions

View File

@ -1,11 +1,17 @@
from collections import OrderedDict
from functools import partial, wraps
from django.db import models
from django.utils.encoding import force_str
from django.utils.module_loading import import_string
from graphql import assert_valid_name
from graphene import (
ID,
UUID,
Boolean,
Date,
DateTime,
Dynamic,
Enum,
Field,
@ -14,24 +20,39 @@ from graphene import (
List,
NonNull,
String,
UUID,
DateTime,
Date,
Time,
)
from graphene.types.resolver import get_default_resolver
from graphene.types.json import JSONString
from graphene.utils.str_converters import to_camel_case
from graphql import assert_valid_name
from .settings import graphene_settings
from .compat import ArrayField, HStoreField, JSONField, PGJSONField, RangeField
from .fields import DjangoListField, DjangoConnectionField
from .fields import DjangoConnectionField, DjangoListField
from .settings import graphene_settings
from .utils import import_single_dispatch
from .utils.str_converters import to_const
singledispatch = import_single_dispatch()
class BlankValueField(Field):
def get_resolver(self, parent_resolver):
resolver = self.resolver or parent_resolver
# create custom resolver
def blank_field_wrapper(func):
@wraps(func)
def wrapped_resolver(*args, **kwargs):
return_value = func(*args, **kwargs)
if return_value == "":
return None
return return_value
return wrapped_resolver
return blank_field_wrapper(resolver)
def convert_choice_name(name):
name = to_const(force_str(name))
try:
@ -68,7 +89,8 @@ def convert_choices_to_named_enum_with_descriptions(name, choices):
def description(self):
return named_choices_descriptions[self.name]
return Enum(name, list(named_choices), type=EnumWithDescriptionsType)
return_type = Enum(name, list(named_choices), type=EnumWithDescriptionsType)
return return_type
def generate_enum_name(django_model_meta, field):
@ -105,9 +127,12 @@ def convert_django_field_with_choices(
return converted
choices = getattr(field, "choices", None)
if choices and convert_choices_to_enum:
enum = convert_choice_field_to_enum(field)
EnumCls = convert_choice_field_to_enum(field)
required = not (field.blank or field.null)
converted = enum(description=field.help_text, required=required)
converted = EnumCls(description=field.help_text, required=required).mount_as(
BlankValueField
)
else:
converted = convert_django_field(field, registry)
if registry is not None:

View File

@ -394,3 +394,43 @@ def test_generate_enum_name(graphene_settings):
generate_enum_name(model_meta, field)
== "SomeLongAppNameSomeObjectFizzBuzzChoices"
)
def test_choice_enum_blank_value():
"""Test that choice fields with blank values work"""
class ReporterType(DjangoObjectType):
class Meta:
model = Reporter
fields = (
"first_name",
"a_choice",
)
class Query(graphene.ObjectType):
reporter = graphene.Field(ReporterType)
def resolve_reporter(root, info):
return Reporter.objects.first()
schema = graphene.Schema(query=Query)
# Create model with empty choice option
Reporter.objects.create(
first_name="Bridget", last_name="Jones", email="bridget@example.com"
)
result = schema.execute(
"""
query {
reporter {
firstName
aChoice
}
}
"""
)
assert not result.errors
assert result.data == {
"reporter": {"firstName": "Bridget", "aChoice": None},
}