Use of GraphQL in Django

Introduction

Features

  • Request the data you want, no more, no less
  • Get multiple resources with just one request
  • Describe all possibilities, type system
  • Almost all languages ​​supported

who is using

Insert image description here

document

background

  • There are many types of interface definitions in traditional restful, trying to simplify interface definitions
  • When using restframework to define restful resource interfaces in Django, in-depth queries may occur, resulting in sometimes excessive queries.
  • For example, when the front-end user needs to query the interface for display in the drop-down box, and the user only needs the id and value values, it will cause redundancy of useless fields and affect the interface return performance.
  • When a table has many fields, for example, interface 1 has a total of 40 fields, page A needs 5 fields for display, and page B needs another 10 fields for display. At this time, we need to define the return interface according to user needs to improve performance, and the data will not be exposed

Practical problems

Insert image description here

Insert image description here

question

  • The requested data volume of 40kB can be reduced according to the user, that is, the returned data volume can be <40KB.
  • The back-end data actually takes 783ms, but the data transmission takes a total of 5s.
    How to use it in Django?
    Installation
pip install graphene-django

django configuration

INSTALLED_APPS = [
    "django.contrib.staticfiles", 
    "graphene_django"
    ]
GRAPHENE = {
    
    
    "SCHEMA": "test_api.schema.schema" # 下文中需要定义schema.py文件
}

Demo

Define database model

from django.db import models


class Category(models.Model):
    name = models.CharField(max_length=100, help_text="名称")
    id = models.BigAutoField(primary_key=True)


class Ingredient(models.Model):
    id = models.BigAutoField(primary_key=True)
    name = models.CharField(max_length=100, help_text="名称")
    notes = models.TextField(help_text="笔记")
    category = models.ForeignKey(
        Category, related_name="category", on_delete=models.CASCADE
    )

    def __str__(self):
        return self.name

Define serializer

from graphene_django.rest_framework.mutation import SerializerMutation
from rest_framework.serializers import ModelSerializer

from ..models import Category, Ingredient


class CategorySerializer(ModelSerializer):
    class Meta:
        model = Category
        fields = "__all__"


class IngredientSerializer(ModelSerializer):
    class Meta:
        model = Ingredient
        fields = "__all__"

Define interface

import graphene
from graphene import relay
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
from graphene_django.rest_framework.mutation import SerializerMutation

from ..models import Category, Ingredient

from ..serializer import CategorySerializer, IngredientSerializer


# 为查询添加查询总数
class CountableConnectionBase(relay.Connection):
    class Meta:
        abstract = True

    total_count = graphene.Int()

    def resolve_total_count(self, info, **kwargs):
        return self.iterable.count()


# Ingredient 查看过滤
class IngredientFilter(DjangoObjectType):
    class Meta:
        model = Ingredient
        fields = "__all__"
        filter_fields = {
    
    
            "name": ['exact', "contains", "istartswith"],
            "category": ["exact"],
            'category__name': ['exact'],
        }
        interfaces = (relay.Node,)
        connection_class = CountableConnectionBase

    extra_field = graphene.String()

    def resolve_extra_field(self: Ingredient, info):
        return "hello!" + str(self.id)


# CategoryFilter 查询过滤
class CategoryFilter(DjangoObjectType):
    class Meta:
        model = Category
        fields = "__all__"
        filter_fields = {
    
    
            "name": ['exact', "contains", "istartswith"],
        }
        interfaces = (relay.Node,)
        connection_class = CountableConnectionBase


# CategoryMutation 修改或新增
class CategoryMutation(SerializerMutation):
    class Meta:
        serializer_class = CategorySerializer


# IngredientMutation 修改或新增
class IngredientMutation(SerializerMutation):
    class Meta:
        serializer_class = IngredientSerializer


# 汇总query接口
class ApiQuery(graphene.ObjectType):
    search_category = DjangoFilterConnectionField(CategoryFilter)
    search_ingredient = DjangoFilterConnectionField(IngredientFilter)


# 汇总操作类接口
class ApiMutation(graphene.ObjectType):
    update_category = CategoryMutation.Field()
    update_ingredient = IngredientMutation.Field()

Summarize all interfaces

import graphene

from .api import ApiQuery, ApiMutation


class Query(ApiQuery):
    # 新增时提供多继承即可
    pass


class Mutation(ApiMutation):
    # 新增时提供多继承即可
    pass


schema = graphene.Schema(query=Query, mutation=Mutation)

start up

python manage.py runserver 0.0.0.0:8080
  • Interface documentation
    Insert image description here
    Insert image description here

Summarize

  • When querying, you can use django_filter for quick query
  • The usage is basically similar to the drf framework.
  • The in-depth query involved in the interface is implemented through connection. If there is no change requirement in the returned field, no in-depth query will be performed.

Guess you like

Origin blog.csdn.net/xzpdxz/article/details/128436581