mirror of
https://github.com/graphql-python/graphene-django.git
synced 2025-07-05 12:53:12 +03:00
Add BlankField and mount enums using it
This commit is contained in:
parent
8571bc465a
commit
fd2dd3adae
|
@ -1,11 +1,17 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from functools import partial, wraps
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import force_str
|
from django.utils.encoding import force_str
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
from graphql import assert_valid_name
|
||||||
|
|
||||||
from graphene import (
|
from graphene import (
|
||||||
ID,
|
ID,
|
||||||
|
UUID,
|
||||||
Boolean,
|
Boolean,
|
||||||
|
Date,
|
||||||
|
DateTime,
|
||||||
Dynamic,
|
Dynamic,
|
||||||
Enum,
|
Enum,
|
||||||
Field,
|
Field,
|
||||||
|
@ -14,24 +20,39 @@ from graphene import (
|
||||||
List,
|
List,
|
||||||
NonNull,
|
NonNull,
|
||||||
String,
|
String,
|
||||||
UUID,
|
|
||||||
DateTime,
|
|
||||||
Date,
|
|
||||||
Time,
|
Time,
|
||||||
)
|
)
|
||||||
|
from graphene.types.resolver import get_default_resolver
|
||||||
from graphene.types.json import JSONString
|
from graphene.types.json import JSONString
|
||||||
from graphene.utils.str_converters import to_camel_case
|
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 .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 import import_single_dispatch
|
||||||
from .utils.str_converters import to_const
|
from .utils.str_converters import to_const
|
||||||
|
|
||||||
singledispatch = import_single_dispatch()
|
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):
|
def convert_choice_name(name):
|
||||||
name = to_const(force_str(name))
|
name = to_const(force_str(name))
|
||||||
try:
|
try:
|
||||||
|
@ -68,7 +89,8 @@ def convert_choices_to_named_enum_with_descriptions(name, choices):
|
||||||
def description(self):
|
def description(self):
|
||||||
return named_choices_descriptions[self.name]
|
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):
|
def generate_enum_name(django_model_meta, field):
|
||||||
|
@ -105,9 +127,12 @@ def convert_django_field_with_choices(
|
||||||
return converted
|
return converted
|
||||||
choices = getattr(field, "choices", None)
|
choices = getattr(field, "choices", None)
|
||||||
if choices and convert_choices_to_enum:
|
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)
|
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:
|
else:
|
||||||
converted = convert_django_field(field, registry)
|
converted = convert_django_field(field, registry)
|
||||||
if registry is not None:
|
if registry is not None:
|
||||||
|
|
|
@ -394,3 +394,43 @@ def test_generate_enum_name(graphene_settings):
|
||||||
generate_enum_name(model_meta, field)
|
generate_enum_name(model_meta, field)
|
||||||
== "SomeLongAppNameSomeObjectFizzBuzzChoices"
|
== "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},
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user