Add new setting to create unique enum names

This commit is contained in:
Jonathan Kim 2020-01-11 17:07:54 +00:00
parent 6a19ab5a4b
commit edbb14e656
3 changed files with 54 additions and 2 deletions

View File

@ -22,6 +22,7 @@ from graphene.types.json import JSONString
from graphene.utils.str_converters import to_camel_case, to_const from graphene.utils.str_converters import to_camel_case, to_const
from graphql import assert_valid_name from graphql import assert_valid_name
from .settings import graphene_settings
from .compat import ArrayField, HStoreField, JSONField, RangeField from .compat import ArrayField, HStoreField, JSONField, RangeField
from .fields import DjangoListField, DjangoConnectionField from .fields import DjangoListField, DjangoConnectionField
from .utils import import_single_dispatch from .utils import import_single_dispatch
@ -68,6 +69,19 @@ def convert_choices_to_named_enum_with_descriptions(name, choices):
return Enum(name, list(named_choices), type=EnumWithDescriptionsType) return Enum(name, list(named_choices), type=EnumWithDescriptionsType)
def generate_enum_name(django_model, field):
meta = django_model._meta
if graphene_settings.CHOICES_TO_ENUM_UNIQUE_TYPE_NAME is True:
name = "DjangoModel{app_label}{object_name}{field_name}Choices".format(
app_label=to_camel_case(meta.app_label).capitalize(),
object_name=meta.object_name,
field_name=to_camel_case(field.name).capitalize(),
)
else:
name = to_camel_case("{}_{}".format(meta.object_name, field.name))
return name
def convert_django_field_with_choices( def convert_django_field_with_choices(
field, registry=None, convert_choices_to_enum=True field, registry=None, convert_choices_to_enum=True
): ):
@ -77,8 +91,7 @@ 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:
meta = field.model._meta name = generate_enum_name(field.model, field)
name = to_camel_case("{}_{}".format(meta.object_name, field.name))
enum = convert_choices_to_named_enum_with_descriptions(name, choices) enum = convert_choices_to_named_enum_with_descriptions(name, choices)
required = not (field.blank or field.null) required = not (field.blank or field.null)
converted = enum(description=field.help_text, required=required) converted = enum(description=field.help_text, required=required)

View File

@ -36,6 +36,8 @@ DEFAULTS = {
# Max items returned in ConnectionFields / FilterConnectionFields # Max items returned in ConnectionFields / FilterConnectionFields
"RELAY_CONNECTION_MAX_LIMIT": 100, "RELAY_CONNECTION_MAX_LIMIT": 100,
"CAMELCASE_ERRORS": False, "CAMELCASE_ERRORS": False,
# Set to True to enable unique naming for choice field Enum's
"CHOICES_TO_ENUM_UNIQUE_TYPE_NAME": False,
} }
if settings.DEBUG: if settings.DEBUG:

View File

@ -9,6 +9,7 @@ from graphene import Connection, Field, Interface, ObjectType, Schema, String
from graphene.relay import Node from graphene.relay import Node
from .. import registry from .. import registry
from ..settings import graphene_settings
from ..types import DjangoObjectType, DjangoObjectTypeOptions from ..types import DjangoObjectType, DjangoObjectTypeOptions
from .models import Article as ArticleModel from .models import Article as ArticleModel
from .models import Reporter as ReporterModel from .models import Reporter as ReporterModel
@ -492,3 +493,39 @@ class TestDjangoObjectType:
} }
""" """
) )
def test_django_objecttype_convert_choices_enum_naming_collisions(self, PetModel):
graphene_settings.CHOICES_TO_ENUM_UNIQUE_TYPE_NAME = True
class PetModelKind(DjangoObjectType):
class Meta:
model = PetModel
fields = ["id", "kind"]
class Query(ObjectType):
pet = Field(PetModelKind)
schema = Schema(query=Query)
assert str(schema) == dedent(
"""\
schema {
query: Query
}
enum DjangoModelTestsPetModelKindChoices {
CAT
DOG
}
type PetModelKind {
id: ID!
kind: DjangoModelTestsPetModelKindChoices!
}
type Query {
pet: PetModelKind
}
"""
)
graphene_settings.CHOICES_TO_ENUM_UNIQUE_TYPE_NAME = False