proglib
Сообщение

Почему специалистом по кибербезопасности быть интереснее, чем разработчиком или сисадмином? Приглашаем на вебинар от HackerU

Почему специалистом по кибербезопасности быть интереснее, чем разработчиком или сисадмином? Приглашаем на вебинар от HackerU

Сравним GraphQL и библиотеку Graphene в Python

0
11118

GraphQL – это стандарт декларирования структуры данных и способов получения данных, предложенный и реализованный Facebook.


Сравним GraphQL и библиотеку Graphene в Python
GraphQL был создан для того, чтобы заменить Rest API. Он имеет встроенную документацию с приложением GraphiQL. С его помощью пользователи получают ответ во время того, как пишут запрос.

Основы

Основным представителем Python является небольшая библиотека под названием Graphene. Но прежде нужно поговорить о некоторых фундаментальных основах GraphQL:

  • Модель – это объект, который определен с помощью GraphQL.
  • Схема определяет модели и их атрибуты.
  • Каждый атрибут модели имеет свой собственный преобразователь. Это функция, которая отвечает за получение данных для этого конкретного атрибута модели.
  • Запрос – это то, что использует пользователь, дабы получить или отправить данные в GraphQL.
  • Мутации – особые запросы, которые позволяют изменять данные конкретной модели или набора моделей.
  • GraphiQL – пользовательский интерфейс, используемый для взаимодействия с сервером GraphQL.

Теперь по поводу Python

У библиотеки Graphene есть поддержка фреймворков, таких как Flask или Django. С помощью Graphene можно определить атрибуты модели, а также анализировать запросы. Задача этой библиотеки – превратить модели SQLAlchemy или Django в объекты GraphQL.

Разберемся с библиотекой Graphene

Установка библиотеки максимально проста. Она поддерживается и на 2, и на 3 версии Python.

pip install graphene

После установки нужно импортировать эту библиотеку:

import graphene  # 1

class Query(graphene.ObjectType):  # 2

    hello = graphene.String(description='A typical hello world')  # 3

    def resolve_hello(self, args, context, info):  # 4
        return 'World'

schema = graphene.Schema(query=Query)  # 5

query = '''
    query {
      hello
    }
'''  # 6
result = schema.execute(query) # 7

В 1 строке мы импортируем пакет. Обратите внимание, что во 2 строке создается класс запроса. Все классы запросов наследуются от graphene.ObjectType. Также можно вставлять запросы в запросы. Кроме того, даже сложные объекты наследуются от graphene.ObjectType. Как правило, в классе содержатся все модели. Сейчас в нём находится только одна модель – hello. В 3 строке добавляем объект в схему. В данном случае это простая строка. В 4 пишем преобразователь для этой конкретной модели. В следующей объявляем схему и говорим ей, что query = Query. Затем вводим самый простой запрос и в 6-ой, 7-ой строках мы, наконец, выполним его. Вот как выглядит результат:

In [6]: result = schema.execute(query)

In [7]: type(result)
Out[7]: graphql.execution.base.ExecutionResult

In [8]: result.data
Out[8]: OrderedDict([('hello', 'world')])

Результат возвращается с тремя основными атрибутами: data, errors, invalid.

In [12]: result.data
Out[12]: OrderedDict([('hello', 'world')])

In [13]: result.errors

In [14]: result.invalid
Out[14]: False

data возвращает нужные нам данные, errors указывают на возможные ошибки, invalid говорит о том, является ли запрос допустимым.

Основные типы

Теперь, когда мы получили представление об основах GraphQL, рассмотрим другие типы данных и начнём разбираться с более сложными объектами.

Существует много различных типов данных. Все они разделяются на скалярные и не скалярные. Скалярные являются базовыми типами объектов. Они могут быть строками, целыми числами, логическими значениями и т. д. Не скалярные – более сложными объектами. Часто они выступают в роли контейнеров скалярных типов данных. Например, списками. Они также могут быть интерфейсами, от которых наследуются другие типы объектов, и, конечно же, существуют типы мутаций, которые вносят изменения поверх данных.

Интеграция с помощью объектно-реляционного отображения

Graphene представляет из себя комбинацию библиотеки сериализации и интерпретатора запросов GraphQL, поэтому для него было бы разумно работать с ORM. На данный момент есть поддержка Django, SQLAlchemy, а также Google App Engine. Большинство из них довольно просто интегрировать.

Django

from django.db import models

from graphene_django import DjangoObjectType

class Account(models.Model):

    birth_date = models.DateField(db_column='personbirthdate', null=True)
    created_date = models.DateTimeField(blank=True, null=True, db_column='createddate')
    is_paying_customer = models.NullBooleanField(db_column='iscustomer')
    country = models.CharField(db_column='country', max_length=3, null=True, blank=True)
    customer_number = models.CharField( db_column='cnumber', unique=True, max_length=255,
        blank=True, null=True, editable=False)

    class Meta:
        managed = False
        db_table ='accountinfo'


class AccountType(DjangoObjectType):
    class Meta:
        model = Account

Теперь можно использовать AccountType так же, как и любой другой объект. Вам даже не придется вручную добавлять объекты запроса. Если у вас установлен Django-фильтр, можно добавить graphene.Node в список интерфейсов для определенного типа. Это позволит объявить некоторые переменные в метаклассе, которые позволят типу быть легко интегрированным в запрос с помощью DjangoConnectedFilterField. Вот пример того, как это будет выглядеть с точки зрения модели Account:

class AccountNode(DjangoObjectType):
    class Meta:
        model = Account
        interfaces = (graphene.Node, )
        filter_fields = [
            'customer_number',
            'is_paying_customer',
        ]

Как это будет выглядеть в объекте запроса:

from graphene_django.filter import DjangoConnectedFilterField

class AccountQuery(graphene.AbstractType):
# Gives you a particular account
account = graphene.Node.Field(AccountNode)

# Gives you all the accounts available
all_accounts = DjangoFilterConnectionField(AccountNode, order_by='-customer_number')

Это действительно упрощает весь процесс запроса. Обратите внимание на то, что graphene.AbstractType используется для объекта AccountQuery. Вот как это выглядит:

from .queries import AccountQuery


class Query(AccountQuery, graphene.ObjectType):
    pass

schema = graphene.Schema(query=Query)

Таким образом, основной объект запроса не будет загроможден, и можно будет продолжать добавлять запросы. Обязательно следует добавить graphene.ObjectType в качестве последнего аргумента для наследования, иначе конечный объект запроса не будет конкретным.

SQLAlchemy и другие

С SQLAlchemy можно просто использовать SQLAlchemyObjectType вместо DjangoObjectType. То же самое истинно и для Google App Engine.

Интеграция с помощью фреймворков

Вот как выглядит приложение Flask GraphQL:

from flask import Flask
from flask_graphql import GraphQLView

from models import db_session
from schema import schema, Department

app = Flask(__name__)
app.debug = True

app.add_url_rule(
    '/graphql',
    view_func=GraphQLView.as_view(
        'graphql',
        schema=schema,
        graphiql=True
    )
)

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

if __name__ == '__main__':
    app.run()

Подведем итоги по GraphQL

В общем и целом, GraphQL – очень классная вещь. Декларативный синтаксис делает его довольно простым в освоении и использовании. Он явно стоит вашего внимания.

Оригинал

Другие материалы по теме:

РУБРИКИ В СТАТЬЕ

МЕРОПРИЯТИЯ

Комментарии 0

ВАКАНСИИ

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

BUG