Duplicate types when using SerializerMutation with a Model having "choices"
Note: for support questions, please use stackoverflow. This repository's issues are reserved for feature requests and bug reports.
- What is the current behavior?
When defining a Mutation with the parent SerializerMutation, graphene will try to generate two types with the same name, resulting in the error AssertionError: Found different types with the same name in the schema: xxx, xxx.
- If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via a github repo, https://repl.it or similar.
Define these classes
class Demo(models.Model):
class YesNoChoices(models.TextChoices):
YES = "y"
NO = "n"
field_with_choices = models.CharField(max_length=1, choices=YesNoChoices)
class DemoSerializer(serializers.ModelSerializer):
class Meta:
model = Demo
fields = ["field_with_choices"]
class DemoMutation(SerializerMutation):
class Meta:
serializer_class = DemoSerializer
class Mutation(object):
demo_mutation = DemoMutation.Field()
then run
python manage.py graphql_schema
- What is the expected behavior?
Types should be created in a clean manner without naming conflicts, resulting in a valid schema.
-
What is the motivation / use case for changing the behavior?
-
Please tell us about your environment:
- Version: graphene-django: 2.15.0, python 3.10.6
- Platform: Ubuntu 22.04
-
Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)
Most likely relates to graphql-python/graphene#1384, where Enums are used. I cannot seem influence how the SerializerMutation handles the choices, however.
This is unlikely to be related to graphene, but rather an issue of the SerializerMutation in Graphene Django. Graphene itself does not automatically generate any enums and as such is unlikely the root cause of this issue. Moving to graphene-django.
You could probably look into how the serializer mutation generates the input graphene types from the models. I'm not an expert with graphene-django, but in graphene-sqlalchemy there's an enum registry in registry.py. Maybe SerializerMutation instead calls fromEnum again instead of looking at the registry, causing the error because the enum was already generated for your Schema Models.
The issue is the following: As I expected, the Serializer tries to get a matching graphene type from the model field: https://github.com/graphql-python/graphene-django/blob/4517e3222499a1aca7c1110204ce5b27d9c911be/graphene_django/rest_framework/serializer_converter.py#L13-L15
When it hits a Choices field, it calls the django converter for enum fields:
https://github.com/graphql-python/graphene-django/blob/4517e3222499a1aca7c1110204ce5b27d9c911be/graphene_django/rest_framework/serializer_converter.py#L159-L163
Which will always create a new Enum type, disregarding wether or not the current Choices type already has a corresponding graphene Enum. https://github.com/graphql-python/graphene-django/blob/4517e3222499a1aca7c1110204ce5b27d9c911be/graphene_django/converter.py#L89-L100
At this point we can assume that the Choices type was already converted to a graphene Enum once, as part of the Schema for the Model. Now the SerializerMutation causes a second conversion, leading to duplicate types with the same name. This can be fixed using a registry, please check out graphene-sqlalchemy's registry.py and converter.py for further reference 🙂