I'm trying to have a unique interface for two concrete classes that are similar and inherit from a common abstract class.
My django model classes:
class Metadata(models.Model):
name = models.CharField(max_length=255)
sequence = models.PositiveSmallIntegerField()
is_choices = False
class Meta:
abstract = True
class MetadataScalar(Metadata):
string_format = models.CharField(max_length=255, blank=True, null=True)
class MetadataChoices(Metadata):
is_choices = True
choices = models.CharField(max_length=255, blank=True, null=True)
My graphene-django api:
class MetadataNode(DjangoObjectType):
class Meta:
interfaces = (Node,)
connection_class = Connection
model = Metadata
fields = '__all__'
class MetadataScalarNode(MetadataNode):
class Meta:
interfaces = (Node,)
connection_class = Connection
model = MetadataScalar
fields = '__all__'
class MetadataChoicesNode(MetadataNode):
class Meta:
interfaces = (Node,)
connection_class = Connection
model = MetadataChoices
fields = '__all__'
class CreateMetadata(ClientIDMutation):
metadata = Field(MetadataNode)
class Input:
name = String(max_length=255, required=True)
sequence = Int(required=True)
string_format = String()
choices = List(String)
@classmethod
def mutate_and_get_payload(cls, root, info, **input):
if 'string_format' in input:
metadata = MetadataScalar.objects.create(
name=input.get('name'),
sequence=input.get('sequence'),
string_format=input.get('string_format')
)
elif 'choices' in input:
metadata = MetadataChoices.objects.create(
name=input.get('name'),
sequence=input.get('sequence'),
choices=','.join(input.get('choices'))
)
return CreateMetadata(metadata=metadata)
When querying the graphql mutation corresponding to CreateMetadata
, the metadata concrete class is successfully created. ;-)
The problem is that when the query asks for the created concrete Metadata
in the result (here either MetadataScalar
or MetadataChoices
), graphql cannot find a node for the concrete class and outputs the following error message:
Expected value of type "MetadataNode" but got: MetadataScalar.
For your information, here is one example query:
mutation {
createMetadata (input: {
stringFormat: "foo"
sequence: 12
name: "bar"
}) {
metadata {
name
sequence
}
}
}
How to make it work nicely, without having to specify two different result types (metadataScalar
and metadataChoices
variables) in the second part of the query?