Используем GraphQL для Django приложений
GraphQL - это стандарт объявления структуры данных и способов получения данных, которую Facebook разработал в качестве альтернативы Rest API. Он не является заменой REST , а его альтернативой и это важно учесть.
Зачем Facebook понадобился создавать новый способ получения данных с сервера для клиента?
Это связано было с тем , что использование REST приводило к определенным проблемам , которые нужно было решать другим способом. И Facebook придумал концептуально простое решение: вместо того, чтобы иметь множество "глупых" endpoint, лучше иметь один "умный" endpoint, который будет способен работать со сложными запросами и придавать данным такую форму, какую запрашивает клиент.
Давайте установим библиотеку
pip install graphene_django
Файл books/models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=255)
code = models.SlugField(max_length=255, unique=True)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField(max_length=1024)
file = models.FileField(upload_to='books')
checksum = models.CharField(max_length=100, unique=True)
category = models.ForeignKey(Category, related_name='books', on_delete=models.SET_NULL,
null=True, blank=True)
tags = models.ManyToManyField(Tag, blank=True)
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
Файл books/schema.py
import graphene
from graphene_django.types import DjangoObjectType, ObjectType
from books.models import Book, Tag, Category
class CategoryType(DjangoObjectType):
class Meta:
model = Category
class BookType(DjangoObjectType):
class Meta:
model = Book
fields = ('id', 'name', 'category',)
class TagType(DjangoObjectType):
class Meta:
model = Tag
class Query(ObjectType):
book = graphene.Field(BookType, id=graphene.Int())
lastbook = graphene.Field(BookType, id=graphene.Int())
books = graphene.List(BookType)
tags = graphene.List(TagType)
def resolve_book(self, info, **kwargs):
return Book.objects.get(pk=kwargs.get('id')) if kwargs.get('id') else None
def resolve_lastbook(self, info , **kwargs):
return Book.objects.last()
def resolve_books(self, info , **kwargs):
return Book.objects.all()
def resolve_tags(self, info , **kwargs):
return Tag.objects.all()
schema = graphene.Schema(query=Query)
На практике GraphQL API построен на трёх основных строительных блоках: на схеме (schema), запросах (queries) и распознавателях (resolvers).
Шаблон запроса личных сообщений
query {
posts { # это массив
title
body
author { # мы может пойти глубже
name
avatarUrl
profileUrl
}
}
}
Resolvers(Распознаватели)
Распознаватель(Resolver) — это функция, которая возвращает данные для определенного поля.Распознаватель должен быть определен как объект с тем же именем, что и объект в схеме
import graphene
class Query(graphene.ObjectType):
title = graphene.String(name=graphene.String(default_value='Test post'))
# Распознаватель(resolver) для поля title
def resolve_title(root, info, name):
return 'Current title :' + name
schema = graphene.Schema(Query)
result = schema.execute('{ title }')
print(result)
print(result.data['title'])
Схема (schema)
Все это становится возможным благодаря типизированной схеме данных GraphQL. Цель этой статьи дать скорее краткий обзор, чем исчерпывающее введение, так что в этом разделе не будет подробностей.