简体   繁体   中英

graphene-django: Query all the models fields and not the requested fields

I have two models:

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}'

The schema:

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()

One of the goals of GraphQL is the performance. To make it the GraphQL must request to the database only the requested fields via GraphQL request (eg: GraphiQL)

If I request the following query:

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

graphene-django library generate the follow 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

It gets all the fields of the models! Is the same of the API Rest problems and does not conest with the GraphQL guidelines.

If I request the field color from the pets model I hope that the query will be:

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

And... how does foreign key resolve with this approach?

You can try to use graphene-django-optimizer .

What it does is to optmize your query so you fetch all related objects in just one query.

In your case, this could be your resolver:

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)

And it will generate the following queryset automatically:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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