Skip to content

Commit a64ba65

Browse files
zbyte64jkimbo
authored andcommitted
convert DRF ChoiceField to Enum (#537)
* convert DRF ChoiceField to Enum, also impacts FilePathField * Pep8 fixes * DRF multiple choices field converts to list of enum * apply black formatting
1 parent cd73cab commit a64ba65

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

graphene_django/converter.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import OrderedDict
12
from django.db import models
23
from django.utils.encoding import force_text
34

@@ -39,6 +40,8 @@ def convert_choice_name(name):
3940

4041
def get_choices(choices):
4142
converted_names = []
43+
if isinstance(choices, OrderedDict):
44+
choices = choices.items()
4245
for value, help_text in choices:
4346
if isinstance(help_text, (tuple, list)):
4447
for choice in get_choices(help_text):
@@ -52,6 +55,19 @@ def get_choices(choices):
5255
yield name, value, description
5356

5457

58+
def convert_choices_to_named_enum_with_descriptions(name, choices):
59+
choices = list(get_choices(choices))
60+
named_choices = [(c[0], c[1]) for c in choices]
61+
named_choices_descriptions = {c[0]: c[2] for c in choices}
62+
63+
class EnumWithDescriptionsType(object):
64+
@property
65+
def description(self):
66+
return named_choices_descriptions[self.name]
67+
68+
return Enum(name, list(named_choices), type=EnumWithDescriptionsType)
69+
70+
5571
def convert_django_field_with_choices(
5672
field, registry=None, convert_choices_to_enum=True
5773
):
@@ -63,16 +79,7 @@ def convert_django_field_with_choices(
6379
if choices and convert_choices_to_enum:
6480
meta = field.model._meta
6581
name = to_camel_case("{}_{}".format(meta.object_name, field.name))
66-
choices = list(get_choices(choices))
67-
named_choices = [(c[0], c[1]) for c in choices]
68-
named_choices_descriptions = {c[0]: c[2] for c in choices}
69-
70-
class EnumWithDescriptionsType(object):
71-
@property
72-
def description(self):
73-
return named_choices_descriptions[self.name]
74-
75-
enum = Enum(name, list(named_choices), type=EnumWithDescriptionsType)
82+
enum = convert_choices_to_named_enum_with_descriptions(name, choices)
7683
required = not (field.blank or field.null)
7784
converted = enum(description=field.help_text, required=required)
7885
else:

graphene_django/rest_framework/serializer_converter.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import graphene
55

66
from ..registry import get_global_registry
7+
from ..converter import convert_choices_to_named_enum_with_descriptions
78
from ..utils import import_single_dispatch
89
from .types import DictType
910

@@ -130,7 +131,6 @@ def convert_serializer_field_to_time(field):
130131
@get_graphene_type_from_serializer_field.register(serializers.ListField)
131132
def convert_serializer_field_to_list(field, is_input=True):
132133
child_type = get_graphene_type_from_serializer_field(field.child)
133-
134134
return (graphene.List, child_type)
135135

136136

@@ -145,5 +145,13 @@ def convert_serializer_field_to_jsonstring(field):
145145

146146

147147
@get_graphene_type_from_serializer_field.register(serializers.MultipleChoiceField)
148-
def convert_serializer_field_to_list_of_string(field):
149-
return (graphene.List, graphene.String)
148+
def convert_serializer_field_to_list_of_enum(field):
149+
child_type = convert_serializer_field_to_enum(field)
150+
return (graphene.List, child_type)
151+
152+
153+
@get_graphene_type_from_serializer_field.register(serializers.ChoiceField)
154+
def convert_serializer_field_to_enum(field):
155+
# enums require a name
156+
name = field.field_name or field.source or "Choices"
157+
return convert_choices_to_named_enum_with_descriptions(name, field.choices)

graphene_django/rest_framework/tests/test_field_converter.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,17 @@ def test_should_url_convert_string():
6060
assert_conversion(serializers.URLField, graphene.String)
6161

6262

63-
def test_should_choice_convert_string():
64-
assert_conversion(serializers.ChoiceField, graphene.String, choices=[])
63+
def test_should_choice_convert_enum():
64+
field = assert_conversion(
65+
serializers.ChoiceField,
66+
graphene.Enum,
67+
choices=[("h", "Hello"), ("w", "World")],
68+
source="word",
69+
)
70+
assert field._meta.enum.__members__["H"].value == "h"
71+
assert field._meta.enum.__members__["H"].description == "Hello"
72+
assert field._meta.enum.__members__["W"].value == "w"
73+
assert field._meta.enum.__members__["W"].description == "World"
6574

6675

6776
def test_should_base_field_convert_string():
@@ -174,7 +183,7 @@ def test_should_file_convert_string():
174183

175184

176185
def test_should_filepath_convert_string():
177-
assert_conversion(serializers.FilePathField, graphene.String, path="/")
186+
assert_conversion(serializers.FilePathField, graphene.Enum, path="/")
178187

179188

180189
def test_should_ip_convert_string():
@@ -189,9 +198,9 @@ def test_should_json_convert_jsonstring():
189198
assert_conversion(serializers.JSONField, graphene.types.json.JSONString)
190199

191200

192-
def test_should_multiplechoicefield_convert_to_list_of_string():
201+
def test_should_multiplechoicefield_convert_to_list_of_enum():
193202
field = assert_conversion(
194203
serializers.MultipleChoiceField, graphene.List, choices=[1, 2, 3]
195204
)
196205

197-
assert field.of_type == graphene.String
206+
assert issubclass(field.of_type, graphene.Enum)

0 commit comments

Comments
 (0)