黄色が好きな広稀です。AMBLでシステムエンジニアをしています。
本記事では、Python 3.6 以降でAPI を構築するための、モダンで高速(高パフォーマンス)な、Web フレームワークであるFAST APIを用いて、簡単にREST APIを構築する方法を紹介します!この記事のREST APIの構築は中級者向けで、2時間位で作れるものとなっています!読み物としては約15分となります。
はじめに
本記事の対象者
- Pythonを触ったことがある
- curlコマンドを使ったことがある
- REST APIを簡単に作ってみたい
- REST APIの概要を既に知っている
- Dockerで構築してみたい
- Docker Composeをある程度は使ったことがある
本記事を作成する際に用いた開発環境
記載しているバージョンは記事作成当時(2022/07/09)のものです。
- macOS 12.4
- VSCode 1.69.0
- Python 3.10.5
- fastapi 0.78.0
- MySQL 8.0.29
- Docker 20.10.16
- Docker compose 1.29.2
FAST APIとは
FastAPI は、API を構築するための、モダンで高速なWeb フレームワークです。
高速で、学習コストも低いため、手軽に導入することができます。
またSwagger UIで手軽に構築したAPIを試すこともできます。
この記事で構築するもの
この記事ではREST APIを用いてアイテム情報の新規作成、参照、更新、削除を行うことができるようなシステムを構築していきます。
環境構築
今回はDockerを用いて開発環境を構築します。
ファイル構成
ファイル構成は以下になります。
各ファイルはこのディレクトリ構成で配置してください。
├── docker-compose.yml
├── mysql
│ ├── conf
│ │ └── my.conf
│ ├── db
│ │ └── create_data.sql
└── src
├── Dockerfile
├── app
│ ├── db.py
│ ├── log
│ ├── main.py
│ └── model.py
└── requirements.txt
Docker関連のファイル作成
FAST APIの説明なので、Docker関連の説明は省きます。
まずはdocker-compose.ymlファイルを作成します。
version: '3'
services:
api:
build: ./src
container_name: api
restart: always
ports:
- 8080:8080
depends_on:
- 'db'
environment:
- TZ=Asia/Tokyo
db:
image: mysql:oracle
container_name: fastapi_mysql
ports:
- 3306:3306
volumes:
- ./mysql/conf/my.conf:/etc/mysql/conf.d/my.cnf
- ./mysql/store:/var/lib/mysql
- ./mysql/db:/docker-entrypoint-initdb.d
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=fastapi
- MYSQL_PASSWORD=passw0rd
- MYSQL_DATABASE=fastapi
- TZ=Asia/Tokyo
restart: always
Dockerfileを作成します。
FROM python:latest
WORKDIR /fast_api_app/src
COPY requirements.txt .
# コンテナ内で必要なパッケージをインストール
RUN pip install --no-cache-dir --trusted-host pypi.python.org -r requirements.txt
COPY app/main.py ./app/
COPY app/model.py ./app/
COPY app/db.py ./app/
ENV PYTHONPATH /fast_api_app
EXPOSE 8080
# FastAPIを8080ポートで待機
WORKDIR /fast_api_app/src/app
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8080"]
テーブルの初期データ(create_data.sql)を作成します。
CREATE TABLE fastapi.items
(
id INT NOT NULL
AUTO_INCREMENT,
item_name text NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON
UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY
(id)
);
-- サンプルレコード作成
INSERT INTO fastapi.items
( -- columns to insert data into
item_name
)
VALUES
( -- first row: values for the columns in the list above
'item1'
),
( -- second row: values for the columns in the list above
'item2'
),
( -- third row: values for the columns in the list above
'item3'
);
my.confファイルを作成します。
[mysqld]
character-set-server=utf8
[mysql]
default-character-set=utf8
[client]
default-character-set=utf8
requrements.txtを作成します。
uvicorn
fastapi
DB関連の処理実装
db.pyを作成します。
ここにはDBに接続するための情報を書きます。
"""
create db transaction
"""
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
host: str = 'db'
port: int = 3306
db_name: str = 'fastapi'
user = 'fastapi'
password = 'passw0rd'
uri = f'mysql://{user}:{password}@{host}:{port}/{db_name}?charset=utf8'
engine = create_engine(uri, encoding='utf8', echo=True)
session = scoped_session(
sessionmaker(
autocommit=False,
autoflush=False,
bind=engine)
)
base = declarative_base()
base.query = session.query_property()
model.pyの作成をします。
ここではテーブルの情報や、モデルを定義します。
"""
model.
"""
from datetime import datetime
from pydantic import BaseModel
from sqlalchemy import Column, DATETIME, FetchedValue, Integer, Text
from src.app.db import base
class ItemsTable(base):
"""
table.
"""
__tablename__ = 'items'
id = Column(Integer, primary_key=True, autoincrement=True)
item_name = Column(Text, nullable=False)
created_at = Column(DATETIME, FetchedValue())
updated_at = Column(DATETIME, FetchedValue())
class Item(BaseModel):
"""
Item model.
"""
id: int
item_name: str
created_at: datetime
updated_at: datetime
class ItemCreate(BaseModel):
"""
Item create
"""
item_name: str
REST APIの実装
ここからは、FAST APIを用いてAPIを実装していきます。
- 全てのItemを取得する処理
- 1つのItemを取得する処理
- Itemを新規作成する処理
- 既にあるItemを更新する処理
- 既にあるItemを削除する処理
これら5つの処理をmain.pyに実装していきます。
まずは前段で作成したDBやモデルのインポートを行います。
from fastapi import FastAPI
from src.app.db import session
from src.app.model import ItemCreate, ItemsTable
全てのItemを取得する処理は次になります。
@app.get("/items")
def get_items():
"""
get all items
:return:
"""
items = session.query(ItemsTable).all()
return items
1つのItemを取得する処理は次のようになります。
idを元に参照します。
@app.get("/items/{_id}")
def get_item(_id: int):
"""
get an item.
:param _id:
:return:
"""
item = session.query(ItemsTable).filter(ItemsTable.id == _id).first()
return item
Itemを新規作成する処理は次のようになります。
@app.post("/items")
def create_item(item: ItemCreate):
"""
create an item
:param item:
:return:
"""
item_ = ItemsTable(item_name=item.item_name)
session.add(item_)
session.commit()
item = session.query(ItemsTable) \
.filter(ItemsTable.item_name == item.item_name) \
.first()
return item
既に存在するItemを更新する処理はこのようになります。
idを元に更新を行います。
@app.put("/items/{_id}")
def update_item(item: ItemCreate, _id: int):
"""
:param item:
:param _id:
:return:
"""
target_item: ItemsTable = session.query(ItemsTable) \
.filter(ItemsTable.id == _id) \
.first()
target_item.item_name = item.item_name
session.commit()
new_item = session.query(ItemsTable) \
.filter(ItemsTable.id == _id) \
.first()
return new_item
既に存在するItemを削除する処理はこのようになります。
idを元に削除を行います。
@app.delete("/items/{_id}")
def delete_item(_id: int):
"""
delete item.
:return:
"""
item = session.query(ItemsTable).filter(ItemsTable.id == _id).first()
session.delete(item)
session.commit()
return item
実行してみよう!
docker-compose.ymlがあるディレクトリでDocker Composeのコマンドを実行します。
$ docker-compose up -d --build
以下が表示されたら、起動完了です。
Creating fastapi_mysql ... done
Creating api ... done
http://localhost:8080/docs をブラウザで開きます。
すると、画像のようなページが表示されます。
右端の下三角をクリックします。
すると、メニューが展開されます。
表示された、「try it out」をクリックして「Execute」をクリックしてみましょう。
するとこのようなレスポンスが返ってきます(画面は一例で異なる場合があります)。
新規作成、更新、削除も実行してみてください。
【新規作成の実行結果】
【更新の実行結果】
【削除の実行結果】
まとめ
いかがでしたでしょうか!?
容易にREST APIを実装することができました。
Swagger UIがあるので、実行確認もwebページを開くことで
簡単に確認することができました。
次回の記事もお楽しみに!
あなたもAMBLで働いてみませんか?
AMBLは事業拡大に伴い、一緒に働く仲間を通年で募集しています。
データサイエンティスト、Webアプリケーションエンジニア、AWSエンジニア、ITコンサルタント、サービス運用エンジニアなどさまざまな職種とポジションで、自分の色を出してくださる方をお待ちしています。ご興味のある方は、採用サイトもご覧ください。
●AMBL採用ページ
-メンバーインタビュー (1日の仕事の流れ/やりがい/仕事内容)
-プロジェクトストーリー (プロジェクトでの実績/苦労エピソード)
●募集ページ
プリセールス/ エンジニア/ クリエイター/ データサイエンティスト /営業・コンサルタント /コーポレート /サービス企画 /教育担当