Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide setting to enable/disable converting choices to enums globally #1477

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,15 @@ Default: ``False``
# ]


``DJANGO_CHOICE_FIELD_ENUM_CONVERT``
--------------------------------------

When set to ``True`` Django choice fields are automatically converted into Enum types.

Can be disabled globally by setting it to ``False``.

Default: ``True``

``DJANGO_CHOICE_FIELD_ENUM_V2_NAMING``
--------------------------------------

Expand Down
6 changes: 5 additions & 1 deletion graphene_django/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,17 @@ def convert_choice_field_to_enum(field, name=None):


def convert_django_field_with_choices(
field, registry=None, convert_choices_to_enum=True
field, registry=None, convert_choices_to_enum=None
):
if registry is not None:
converted = registry.get_converted_field(field)
if converted:
return converted
choices = getattr(field, "choices", None)
if convert_choices_to_enum is None:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A reason why I moved it into convert_django_field_with_choices and not implemented it on construct_fields or DjangoObjectType is, that django-graphene-plus uses convert_django_field_with_choices directly and would skip/ignore the setting or would need to manually look it up.
See: https://github.com/0soft/graphene-django-plus/blob/master/graphene_django_plus/input_types.py#L28

convert_choices_to_enum = bool(
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CONVERT
)
if choices and convert_choices_to_enum:
EnumCls = convert_choice_field_to_enum(field)
required = not (field.blank or field.null)
Expand Down
2 changes: 2 additions & 0 deletions graphene_django/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
# Max items returned in ConnectionFields / FilterConnectionFields
"RELAY_CONNECTION_MAX_LIMIT": 100,
"CAMELCASE_ERRORS": True,
# Automatically convert Choice fields of Django into Enum fields
"DJANGO_CHOICE_FIELD_ENUM_CONVERT": True,
# Set to True to enable v2 naming convention for choice field Enum's
"DJANGO_CHOICE_FIELD_ENUM_V2_NAMING": False,
"DJANGO_CHOICE_FIELD_ENUM_CUSTOM_NAME": None,
Expand Down
116 changes: 116 additions & 0 deletions graphene_django/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,122 @@ class Query(ObjectType):
}"""
)

def test_django_objecttype_convert_choices_global_false(
self, graphene_settings, PetModel
):
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CONVERT = False

class Pet(DjangoObjectType):
class Meta:
model = PetModel
fields = "__all__"

class Query(ObjectType):
pet = Field(Pet)

schema = Schema(query=Query)

assert str(schema) == dedent(
"""\
type Query {
pet: Pet
}

type Pet {
id: ID!
kind: String!
cuteness: Int!
}"""
)

def test_django_objecttype_convert_choices_true_global_false(
self, graphene_settings, PetModel
):
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CONVERT = False

class Pet(DjangoObjectType):
class Meta:
model = PetModel
fields = "__all__"
convert_choices_to_enum = True

class Query(ObjectType):
pet = Field(Pet)

schema = Schema(query=Query)

assert str(schema) == dedent(
"""\
type Query {
pet: Pet
}

type Pet {
id: ID!
kind: TestsPetModelKindChoices!
cuteness: TestsPetModelCutenessChoices!
}

\"""An enumeration.\"""
enum TestsPetModelKindChoices {
\"""Cat\"""
CAT

\"""Dog\"""
DOG
}

\"""An enumeration.\"""
enum TestsPetModelCutenessChoices {
\"""Kind of cute\"""
A_1

\"""Pretty cute\"""
A_2

\"""OMG SO CUTE!!!\"""
A_3
}"""
)

def test_django_objecttype_convert_choices_enum_list_global_false(
self, graphene_settings, PetModel
):
graphene_settings.DJANGO_CHOICE_FIELD_ENUM_CONVERT = False

class Pet(DjangoObjectType):
class Meta:
model = PetModel
convert_choices_to_enum = ["kind"]
fields = "__all__"

class Query(ObjectType):
pet = Field(Pet)

schema = Schema(query=Query)

assert str(schema) == dedent(
"""\
type Query {
pet: Pet
}

type Pet {
id: ID!
kind: TestsPetModelKindChoices!
cuteness: Int!
}

\"""An enumeration.\"""
enum TestsPetModelKindChoices {
\"""Cat\"""
CAT

\"""Dog\"""
DOG
}"""
)


@with_local_registry
def test_django_objecttype_name_connection_propagation():
Expand Down
6 changes: 3 additions & 3 deletions graphene_django/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


def construct_fields(
model, registry, only_fields, exclude_fields, convert_choices_to_enum
model, registry, only_fields, exclude_fields, convert_choices_to_enum=None
):
_model_fields = get_model_fields(model)

Expand All @@ -47,7 +47,7 @@ def construct_fields(
continue

_convert_choices_to_enum = convert_choices_to_enum
if not isinstance(_convert_choices_to_enum, bool):
if isinstance(_convert_choices_to_enum, list):
# then `convert_choices_to_enum` is a list of field names to convert
if name in _convert_choices_to_enum:
_convert_choices_to_enum = True
Expand Down Expand Up @@ -148,7 +148,7 @@ def __init_subclass_with_meta__(
connection_class=None,
use_connection=None,
interfaces=(),
convert_choices_to_enum=True,
convert_choices_to_enum=None,
_meta=None,
**options,
):
Expand Down