哇哦…用FastAPI搭建GraphQL太容易了吧…?

我自己的介绍

你好,我是ZOZO Technologies的内定者Satto。
最近我经常使用FastAPI,发现它支持GraphQL和WebSocket,太方便了!
感觉真是太好了!

※ This article is Day 17 of ZOZO Technologies #5.
Yesterday, @e_tyubo published an article titled “Dealing with Incorrect autocrlf Configuration in Git for Windows.”
In addition, ZOZO Technologies is updating five advent calendars every day!

※ 本文是ZOZO技术#5的第17天。
昨天,@e_tyubo发布了一篇名为“在Git for Windows中处理错误的autocrlf配置”的文章。
此外,ZOZO技术每天更新五个圣诞日历!

    • ZOZOテクノロジーズ#1

 

    • ZOZOテクノロジーズ#2

 

    • ZOZOテクノロジーズ#3

 

    ZOZOテクノロジーズ#4

总结

我想介绍一种使用FastAPI快速构建GraphQL的方法。

以下是本文的结构。

    • FastAPI?GraphQLとは?

 

    • FastAPI×GraphQLで楽々ハローワールド

 

    SQLAlchemyを使ってDB接続

FastAPI是什么?

这是一个运行在Python3.6及以上版本上的高效API框架。
https://fastapi.tiangolo.com/
我认为在2019年初左右它引起了一些讨论。

具有与Node.js和Go相当的性能表现,并且以类似Flask的编写方式,轻松构建RESTful API、GraphQL和WebSocket。我认为这是一种在限定时间的开发中非常有效的框架,比如在黑客马拉松等竞赛中。

此外,由于Swagger的自动生成,可以大幅缩短进行操作检查和创建文档的时间。

GraphQL 是什么?

Facebook开发了一种开源语言,旨在解决传统RESTful API的问题。

(Translation: Facebook developed an open-source language to solve the problems of traditional RESTful API.)

特点是通过使用一个终点,可以在一次查询中获取所需的数据,并且只获取所需数据量。

通过这个优点,我们可以避免在传统的RESTful API中获取数据时附加了不必要的数据。这样就可以降低能耗和网络带宽,实现了更高效的通信。

你好 GraphQL。

暂且搁置代码的说明,我们来试着运行一下。

$ git clone https://github.com/sattosan/hello_fastapi_graphql.git

# コンテナをビルド&起動
$ docker-compose up -d --build

GraphQL的操作验证

当容器启动后,请访问以下链接:
http://127.0.0.1:8000/graphql

Screenshot from 2019-12-14 03-00-14.png

按照图像所示,在左侧列出以下查询,并执行。

{
  hello(name: "FastAPI")
}

您是否能够看到右侧的响应显示?

代码的解释

现在,我们立刻来查看代码的内容吧。

行动环境

    • Ubuntu 18.04.3 および macOS Catalina 10.15.3

 

    • Python 3.8

 

    FastAPI 0.45.0

文件结构

由于使用Python的各种软件包,这次我们使用Docker Compose来构建环境。

.
├── api
│   └── main.py
├── docker
│   └── uvicorn
│       ├── Dockerfile
│       └── requirements.txt
└── docker-compose.yml

使用Docker Compose进行环境配置。

    Composeファイル
version: "3"

services:
  # FastAPI
  api:
    container_name: "api"
    build: ./docker/uvicorn
    restart: always
    tty: true
    ports:
      - 8000:8000
    volumes:
      - ./api:/usr/src/api
    FastAPIのコンテナを定義
FROM python:3.8

WORKDIR /usr/src/api
ADD requirements.txt ./
# requirements.txtにリストされたパッケージをインストールする
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# FastAPIを8000ポートで待機
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
    必要なPythonのパッケージを一気にインストールするためにリスト化したもの
uvicorn
fastapi
graphene

使用FastAPI创建GraphQL的端点

和RESTful API不同,GraphQL只有一个端点。

这次我们将使用FastAPI,创建一个服务器来公开GraphQL模式在端点/graphql上,并创建一个名为GraphiQL的Web用户界面,用于方便执行查询。

使用Starlette库可以为实现这些功能提供支持。

import graphene
from fastapi import FastAPI
from starlette.graphql import GraphQLApp


# Grapheneを利用したGraphQLスキーマを作成する
class Query(graphene.ObjectType):
    # 引数nameを持つフィールドhelloを作成
    hello = graphene.String(name=graphene.String(default_value="stranger"))

    # フィールドhelloに対するユーザへ返すクエリレスポンスを定義
    def resolve_hello(self, info, name):
        return "Hello " + name


# FastAPIを利用するためのインスタンスを作成
app = FastAPI()
# GraphQLのエンドポイント
app.add_route("/graphql", GraphQLApp(schema=graphene.Schema(query=Query)))

使用SQLAlchemy进行数据库连接。

我們將準備一個DB,然後編輯現有檔案以便能夠使用GraphQL檢索數據。

我们使用SQLite构建数据库,并使用SQLAlchemy作为ORM模块来操作数据。

如果您想立即尝试,请访问此处,完成的代码已经在GitHub上。

文件添加和编辑

文件结构已更改如下。

.
├── api
│   ├── main.py    # 編集
│   ├── models.py  # 追加
│   ├── schema.py  # 追加
│   └── init_data.py # 追加
├── docker
│   └── uvicorn
│       ├── Dockerfile
│       └── requirements.txt # 編集
└── docker-compose.yml

追加包装

为了在FastAPI容器中进行与数据库和数据的交互,需要添加graphene_sqlalchemy来处理SQLAlchemy和GraphQL的操作。

uvicorn
fastapi
graphene
SQLAlchemy # 追加
graphene_sqlalchemy # 追加

表格模型的定义 de

创建用于与SQLite通信的db_session,定义Department和Employee表。

# flask_sqlalchemy/models.py
from sqlalchemy import *
from sqlalchemy.orm import (scoped_session, sessionmaker, relationship,
                            backref)
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))

Base = declarative_base()
# クエリを扱うために宣言
Base.query = db_session.query_property()


class Department(Base):
    __tablename__ = 'department'
    id = Column(Integer, primary_key=True)
    name = Column(String)


class Employee(Base):
    __tablename__ = 'employee'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    hired_on = Column(DateTime, default=func.now())
    department_id = Column(Integer, ForeignKey('department.id'))
    department = relationship(
        Department,
        backref=backref('employees',
                        uselist=True,
                        cascade='delete,all'))

模式定义

定义Employee和Department来获取特定雇员信息和部门信息。

另外,还提供了用于获取特定节点的节点”node”以及获取所有员工信息和部门信息的”all_employees”和”all_department”。

import graphene
from graphene import relay
from graphene_sqlalchemy import SQLAlchemyObjectType, SQLAlchemyConnectionField
from models import Department as DepartmentModel, Employee as EmployeeModel


class Department(SQLAlchemyObjectType):
    class Meta:
        model = DepartmentModel
        interfaces = (relay.Node, )


class DepartmentConnections(relay.Connection):
    class Meta:
        node = Department


class Employee(SQLAlchemyObjectType):
    class Meta:
        model = EmployeeModel
        interfaces = (relay.Node, )


class EmployeeConnections(relay.Connection):
    class Meta:
        node = Employee


class Query(graphene.ObjectType):
    node = relay.Node.Field()
    # デフォルトでは、ソートが有効化されている
    all_employees = SQLAlchemyConnectionField(EmployeeConnections)
    # ソートを無効化
    all_departments = SQLAlchemyConnectionField(DepartmentConnections, sort=None)


schema = graphene.Schema(query=Query)

修改FastAPI的代码

将定义的模式和查询发送到GraphQLApp以便处理。
另外,还添加了在关闭时删除数据库会话的事件。

from fastapi import FastAPI
from starlette.graphql import GraphQLApp

from models import db_session
from schema import schema

# FastAPIのインスタンスを作成
app = FastAPI()

# GraphQLを提供するためのエンドポイントを定義
app.add_route("/graphql", GraphQLApp(schema=schema))

# APIサーバシャットダウン時にDBセッションを削除
@app.on_event("shutdown")
def shutdown_event():
    db_session.remove()

插入测试数据

在SQLite中创建的表格内输入以下命令,插入测试数据。

$ docker-compose run --rm api python init_data.py

init_data.py是整理测试数据的文件。

# 初期データを流し込むためのスクリプト.以下を実行してTableにデータを流し込む
# docker-compose run --rm api python init_data.py
from models import engine, db_session, Base, Department, Employee
Base.metadata.create_all(bind=engine)

# Tableに流し込む初期データ
engineering = Department(name='Engineering')
db_session.add(engineering)
hr = Department(name='Human Resources')
db_session.add(hr)

peter = Employee(name='Peter', department=engineering)
db_session.add(peter)
roy = Employee(name='Roy', department=engineering)
db_session.add(roy)
tracy = Employee(name='Tracy', department=hr)
db_session.add(tracy)
db_session.commit()

重新构建集装箱 jí

由于各种更改,需要重新构建容器。

$ docker-compose up -d --build

尝试使用GraphQL请求DB的数据

让我们访问以下链接,尝试使用GraphQL获取插入到数据库中的数据。

请尝试发送这样的查询。

{
  allEmployees {
    edges {
      node {
        id
        name
        department {
          name
        }
      }
    }
  }
}
Screenshot from 2019-12-15 01-34-50.png

我使用了allEmployees方法,成功获取了所有员工的信息。

总结

在这次的讲座中,我介绍了使用FastAPI构建GraphQL的方法。
使用仅仅几行代码就可以完成构建,对于想要尝试一下的人来说,
我认为FastAPI是最佳选择。

明天是@hmsnakr的文章发布日!敬请期待!!

请提供更多的上下文。

https://fastapi.tiangolo.com/tutorial/graphql/ 这个链接是关于如何使用FastAPI构建GraphQL API的教程。

https://docs.graphene-python.org/projects/sqlalchemy/en/latest/tutorial/ 这个链接是关于如何使用Graphene和SQLAlchemy构建GraphQL API的教程。

广告
将在 10 秒后关闭
bannerAds