🐍
【phython】FastAPI作成
はじめに
記事を書くのがずいぶん久しぶりになってしまった。
週に一回は記事を書くと決めていたのだが、怠けてしまった。まとめて書こうとしているとついつい先延ばしにしがちです。
今週からは週に一回書くようにします
内容
前回記事を書いたのはだいぶ前になるが、以前の意地ではDBの作成について書きました。
今回は、作ったDBから APIを作るところになる。
結論としては以下のライブラリを使用することにした。
Docker
フォルダ階層
-- mysql
∟ data
∟ init.d
∟ my.cnf
-- pyhon
∟ src
∟ Dockerfile
-- root
docker-compose.yml
docker-compose.yml
version: "3.9"
services:
python3:
restart: always
depends_on:
- db
build:
context: ./python
container_name: "python3"
ports:
- "8000:8000"
volumes:
- ./python/src:/python
db:
image: mysql:latest
container_name: db
environment:
- MYSQL_DATABASE=python_sample
- MYSQL_USER=docker
- MYSQL_PASSWORD=docker
- MYSQL_ROOT_PASSWORD=docker
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
- ./mysql/init.d:/docker-entrypoint-initdb.d
ports:
- target: 3306
published: 3306
protocol: tcp
mode: host
command: --port 3306
tty: true
Dockerfile(python)
Dockerfile
FROM python:3.7
WORKDIR /python
ADD requirements.txt .
RUN pip install -r requirements.txt
CMD ["uvicorn", "main:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
requirements.txt
uvicorn
fastapi
mysqlclient
sqlalchemy
pyhonの内容
まぁ、 Fast APIの公式サイトにも書いてあるがHTTPメソッドごとに機能を切り分けているっぽいです。
HTTPメソッドについては以下の記事をご確認ください。
超簡単にいうと以下の表な感じだ。
HTTPメソッド | 内容 |
---|---|
Get | 取得 |
Post | 登録 |
Put | 更新 |
Delete | 削除 |
まずはSQL接続情報を定義します。(docker-composeで定義した内容)
db.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
host = "db:3306"
db_name = "python_sample"
user = "docker"
password = "docker"
DATABASE = 'mysql://%s:%s@%s/%s?charset=utf8' % (
user,
password,
host,
db_name,
)
ENGINE = create_engine(
DATABASE,
encoding="utf-8",
echo=True
)
session = scoped_session(
sessionmaker(
autocommit=False,
autoflush=False,
bind=ENGINE
)
)
Base = declarative_base()
Base.query = session.query_property()
次に、SQLで定義されたテーブル構造をPythonのモデルとして再定義します。
model.py
from sqlalchemy import Column, Integer, String
from pydantic import BaseModel
from db import Base
from db import ENGINE
# テーブル定義
class TestUserTable(Base):
__tablename__ = 'test_user'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(30), nullable=False)
email = Column(String(128), nullable=False)
# モデル定義
class TestUser(BaseModel):
id: int
name: str
email: str
def main():
# テーブル構築
Base.metadata.create_all(bind=ENGINE)
if __name__ == "__main__":
main()
最後にAPIを書きます。
main.py
from fastapi import FastAPI
from db import session
from model import TestUserTable, TestUser
app = FastAPI()
# ユーザー情報一覧取得
@app.get("/test_users")
def get_user_list():
users = session.query(TestUserTable).all()
return users
# ユーザー情報取得(id指定)
@app.get("/test_users/{user_id}")
def get_user(user_id: int):
user = session.query(TestUserTable).\
filter(TestUserTable.id == user_id).first()
return user
# ユーザ情報登録
@app.post("/test_users")
def post_user(user: TestUser):
db_test_user = TestUser(name=user.name,
email=user.email)
session.add(db_test_user)
session.commit()
# ユーザ情報更新
@app.put("/test_users/{user_id}")
def put_users(user: TestUser, user_id: int):
target_user = session.query(TestUserTable).\
filter(TestUserTable.id == user_id).first()
target_user.name = user.name
target_user.email = user.email
session.commit()
実行してみた。
実行
# curl -X 'GET' 'http://localhost:8000/test_users' -H 'accept: application/json'
結果
[{"email":"tanaka.taro@example.com","id":1,"name":"tanaka taro"},{"email":"yamada.hanako@example.com","id":2,"name":"yamada hanako"}]
最後に
あとはポーリングしてDBに突っ込む処理を掛ければ一通り実装が出来そうである。
モチベーションを下げずに来週も書こうかと思います。
Discussion