Open Tibiritabara opened 5 years ago
i have exact same problem
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
it is all because both DjangoObjectType and SerializerMutation are converting choice field to graphene Enum. I am struggling with the same error. Currently I see the easiest solution to move all Django Enums to Graphene Enums and resolve everything manually
Also having the same problem -- it really seems like being able to create a DjangoObjectType
and a SerializerMutation
for the same class, without field conflicts arising, should be a core supported use-case.
DjangoObjectType
for my models and a single corresponding SerializerMutation
object (all dynamically generated with fully varying class names)convert_choices_to_enum = False
on DjangoObjectType.Meta
, which I confirmed no longer creates the enum in the Query
schema on the lookup fields, but when I add the Mutations
into the Schema the error is thrown again.convert_choices_to_enum=False
on the SerializerMutation.Meta
class has no effect.ObjectType
and Mutation
did resolve the assertion, but that isn't a tenable solution.I feel like this could be avoided if, somehow, maybe the SerializerMutation was "made aware of" the ObjectType, such that a new ObjectType isn't generated for the input/output? Looking through the source, I don't see any way to achieve this, and I'm also not confident in this hunch.
Code is here --
for model, fields, filterset, serializer in resources:
class ObjectMeta:
model = model
name = model._meta.object_name
fields = fields
filter_fields = filterset.filter_fields
interfaces = (graphene.relay.Node,)
convert_choices_to_enum = False
ObjectType = type('%sObjectType'%ObjectMeta.name, (DjangoObjectType,), {"Meta": ObjectMeta})
class MutationMeta:
serializer_class = serializer
model_operations = ['create']
convert_choices_to_enum = False
Mutation = type('%sMutation'%ObjectMeta.name, (SerializerMutation,), {"Meta": MutationMeta})
EDIT --
I've isolated this bug in a test case -- I have verified that a simple test for adding a SerializerMutation
with any simple ChoiceField
causes the error to be thrown.
I think we can all agree that this test should not fail on the last line, but it throws the error E AssertionError: Found different types with the same name in the schema: status, status
.
I have also submitted a PR #851 to allow us to disable this Enum
creation, but I think we have positive confirmation here that these Enum
types are causing schema definition collisions even in simple use cases.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I had the same problem but this was how i solved it: You must not call your Enum class more than once in your schema
Models.py
class EnumAccountTypes(models.TextChoices):
PERSONAL = 'PERSONAL', 'Personal'
BUSINESS = 'BUSINESS', 'Business'
COURIER = 'COURIER', 'Courier'
DRIVER = 'DRIVER', 'Driver'
Schema.py
from .models import EnumAccountTypes as EnumAccountInputTypes
EnumAccountTypes = graphene.Enum.from_enum(EnumAccountInputTypes)
class CreateUser(graphene.Mutation):
# Return object
user = graphene.Field(UserType)
# Arguments
class Arguments:
''' other arguments '''
account_type = graphene.Argument(
EnumAccountTypes
)
def mutate(self, info, account_type):
user = User(
account_type=account_type
)
user.save()
return CreateUser(user=user)
I had the same problem but this was how i solved it: You must not call your Enum class more than once in your schema
Models.py
class EnumAccountTypes(models.TextChoices): PERSONAL = 'PERSONAL', 'Personal' BUSINESS = 'BUSINESS', 'Business' COURIER = 'COURIER', 'Courier' DRIVER = 'DRIVER', 'Driver'
Schema.py
from .models import EnumAccountTypes as EnumAccountInputTypes EnumAccountTypes = graphene.Enum.from_enum(EnumAccountInputTypes) class CreateUser(graphene.Mutation): # Return object user = graphene.Field(UserType) # Arguments class Arguments: ''' other arguments ''' account_type = graphene.Argument( EnumAccountTypes ) def mutate(self, info, account_type): user = User( account_type=account_type ) user.save() return CreateUser(user=user)
works. nice post
I had the same problem but this was how i solved it: You must not call your Enum class more than once in your schema
Models.py
class EnumAccountTypes(models.TextChoices): PERSONAL = 'PERSONAL', 'Personal' BUSINESS = 'BUSINESS', 'Business' COURIER = 'COURIER', 'Courier' DRIVER = 'DRIVER', 'Driver'
Schema.py
from .models import EnumAccountTypes as EnumAccountInputTypes EnumAccountTypes = graphene.Enum.from_enum(EnumAccountInputTypes) class CreateUser(graphene.Mutation): # Return object user = graphene.Field(UserType) # Arguments class Arguments: ''' other arguments ''' account_type = graphene.Argument( EnumAccountTypes ) def mutate(self, info, account_type): user = User( account_type=account_type ) user.save() return CreateUser(user=user)
successfully mutation created using Enum by this method, but how to query with same Enum values
Regarding the Enum conversion, I see it as a bug, that the string of the member variable instead of the first element in the tuple is used. i.e., given the following enum:
class EnumAccountTypes(models.TextChoices):
PERSONAL = 'personal', 'Personal'
BUSINESS = 'business 'Business'
COURIER = 'courier', 'Courier'
DRIVER = 'driver', 'Driver'
The following query:
query {
user(id: "...") {
id
accountType
}
}
Results in the following result:
{
"data": {
"controllerTask": {
"id": "...",
"accountType": "PERSONAL"
}
}
}
Instead of what I would expect
{
"data": {
"controllerTask": {
"id": "...",
"accountType": "personal"
}
}
}
This should fix the situation before the bug is patched.
import warnings
import graphene
from graphene.types.typemap import TypeMap
from graphql.type.introspection import IntrospectionSchema
from my_query_module import Query
from my_mutation_module import Mutation
class EnumConflictGracefulTypeMap(TypeMap):
@staticmethod
def dict_equal(this_dict: dict, that_dict: dict) -> bool:
if set(this_dict.keys()) != set(that_dict.keys()): return False
keys = set(this_dict.keys())
if any(this_dict[key].name != that_dict[key].name for key in keys): return False
if any(this_dict[key].value != that_dict[key].value for key in keys): return False
return True
@staticmethod
def graphene_enum_to_dict(graphene_enum: graphene.Enum) -> dict:
return graphene_enum._meta.enum.__members__
def graphene_reducer(self, map, type):
try:
return super(EnumConflictGracefulTypeMap, self).graphene_reducer(map, type)
except AssertionError as e:
# re-raise other assertion errors
if not str(e).startswith('Found different types with the same name in the schema:'): raise e
# re-raise assertion errors not for enum types
if not issubclass(type, graphene.Enum): raise e
# check if two enum types are truly equal, if not, raise more specific assertion error
another_type = map[type._meta.name].graphene_type
this = self.graphene_enum_to_dict(type)
that = self.graphene_enum_to_dict(another_type)
assert self.dict_equal(this, that), (
f'Found enum types with the same name but with different definitions in the schema: \n'
f'\tEnum: {type}\n'
f'\tdefined as: {this} but also\n'
f'\tdefined as: {that}\n'
)
warnings.warn(
f'Found an enum type being mapped twice when generating the schema:\n'
f'\t{type}: {this}\n'
)
return map
class EnumConflictGracefulSchema(graphene.Schema):
def build_typemap(self):
initial_types = [
self._query,
self._mutation,
self._subscription,
IntrospectionSchema,
]
if self.types:
initial_types += self.types
# self._type_map = TypeMap(
self._type_map = EnumConflictGracefulTypeMap(
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^
# the only place where the method is modified
initial_types, auto_camelcase=self.auto_camelcase, schema=self
)
# instead of using schema = graphene.Schema(query=Query, mutation=Mutation)
schema = EnumConflictGracefulSchema(query=Query, mutation=Mutation)
I think I read this issue in the past, graphene-django is currently throwing the next exception on my end:
"Found different types with the same name in the schema: currency, currency"
The currency field is just a field with enums
There is a serializer for this model:
The schema is using the
Test
modeland there are 2 mutations, one for creation based on the serializer and a custom one:
Now, this is currently throwing the next exception when using the latest release (2.6.0):
Found different types with the same name in the schema: currency, currency.
On 2.5.0 this error does not happen.