简体   繁体   English

如何在graphene-django中使用django抽象类?

[英]How to use a django abstract class with graphene-django?

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:我的 Django 模型类:

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:我的石墨烯-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.当查询到CreateMetadata对应的 graphql 突变时,成功创建了元数据具体类。 ;-) ;-)

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:问题是,当查询在结果中要求创建具体的Metadata (这里是MetadataScalarMetadataChoices )时, graphql找不到具体类的节点并输出以下错误消息:

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?如何让它很好地工作,而不必在查询的第二部分指定两种不同的结果类型( metadataScalarmetadataChoices变量)?

You can use Union in order to be able to specify multiple different result classes.您可以使用Union来指定多个不同的结果类。

In your case, that woud be:在您的情况下,那将是:

class MetadataScalarNode(DjangoObjectType):
    class Meta:
        interfaces = (Node,)
        connection_class = Connection
        model = MetadataScalar
        fields = '__all__'


class MetadataChoicesNode(DjangoObjectType):
    class Meta:
        interfaces = (Node,)
        connection_class = Connection
        model = MetadataChoices
        fields = '__all__'


class MetadataNode(Union):
    class Meta:
        types = (MetadataScalarNode, MetadataChoicesNode)

The graphql query wil look like: graphql 查询将如下所示:

mutation {
  createMetadata (input: {
    stringFormat: "foo"
    sequence: 12
    name: "bar"
  }) {
    metadata {
      __typename
      ... on MetadataScalarNode {
        name
        sequence
        stringFormat
      }
      ... on MetadataChoicesNode {
        name
        sequence
        choices
      }
    }
  }
}

Just try你试一试

... on metadata{
  name
  sequence
}

with your interface.与您的界面。 Union can't have any fields so you need to have duplicates if using Union vs Interfaces. Union 不能有任何字段,因此如果使用 Union 与 Interfaces,您需要有重复项。 https://docs.graphene-python.org/en/latest/types/unions/ https://docs.graphene-python.org/en/latest/types/unions/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM