首页 > 解决方案 > graphene-django:查询所有模型字段而不是请求的字段

问题描述

我有两个模型:

class Type(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return f'{self.name}'


class Pet(models.Model):
    name = models.CharField(max_length=255)
    color = models.CharField(max_length=255)
    type = models.ForeignKey(Type, related_name="pets", on_delete=models.CASCADE,
                             null=True, blank=True)

    def __str__(self):
        return f'{self.type.name} {self.name}'

架构:

class Type(DjangoObjectType):
    class Meta:
        model = TypeModel

    @classmethod
    def get_node(cls, info, id):
        return TypeModel.objects.get(id=id)


class TypeConnector(graphene.Connection):
    count = graphene.Int()

    class Meta:
        node = Type

    def resolve_count(root, info):
        return len(root.edges)


class Pet(DjangoObjectType):
    class Meta:
        model = PetModel
        interfaces = (relay.Node,)

    @classmethod
    def get_node(cls, info, id):
        return PetModel.objects.get(id=id)


class PetConnector(graphene.Connection):
    count = graphene.Int()

    class Meta:
        node = Pet

    def resolve_count(root, info):
        return len(root.edges)


class Schema(ObjectType):
    pets = graphene.ConnectionField(PetConnector)
    types = graphene.ConnectionField(TypeConnector)

    def resolve_pets(self, info, **kwargs):
        # TODO: Query for requested fields only
        return PetModel.objects.all()

    def resolve_types(self, info, **kwargs):
        # TODO: Query for requested fields only
        return TypeModel.objects.all()

GraphQL 的目标之一是性能。要做到这一点,GraphQL 必须通过 GraphQL 请求仅向数据库请求请求的字段(例如:GraphiQL)

如果我请求以下查询:

{
  pets {
    edges {
      node {
        color
        type {
          name
        }
      }
    }
  }
}

graphene-django 库生成以下 SQL:

2020-01-03 03:16:18.184 UTC [136] LOG:  statement: SELECT "pets_pet"."id", "pets_pet"."name", "pets_pet"."color", "pets_pet"."type_id" FROM "pets_pet"
2020-01-03 03:16:18.189 UTC [136] LOG:  statement: SELECT "pets_type"."id", "pets_type"."name" FROM "pets_type" WHERE "pets_type"."id" = 1 LIMIT 21

它得到了模型的所有领域!与 API Rest 问题相同,并且不符合 GraphQL 指南。

如果我colorpets模型中请求字段,我希望查询是:

SELECT "pets_pet"."color" FROM "pets_pet"

而且......外键如何用这种方法解决?

标签: djangographqlgraphene-pythongraphene-django

解决方案


您可以尝试使用graphene-django-optimizer

它的作用是优化您的查询,以便您在一个查询中获取所有相关对象。

在您的情况下,这可能是您的解析器:

import graphene_django_optimizer as gql_optimizer

...

class Schema(ObjectType):
    pets = graphene.ConnectionField(PetConnector)
    types = graphene.ConnectionField(TypeConnector)

    def resolve_pets(self, info, **kwargs):
        return gql_optimizer.query(PetModel.objects.all(), info)

它将自动生成以下查询集:

  Pets.objects
    .select_related('type')
    .only('color', 'type__name')

推荐阅读