11 мая 2019 г. 1:09

142

Используем 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. Цель этой статьи дать скорее краткий обзор, чем исчерпывающее введение, так что в этом разделе не будет подробностей.

comments powered by Disqus