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
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
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
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.