哇哦…用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

按照图像所示,在左侧列出以下查询,并执行。
{
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
}
}
}
}
}

我使用了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的教程。