概要
勉強用に、PythonでPostgresqlを制御しようと思います。の続きです。
前回でPostgreSQLと、データベース/テーブルまでは用意したので、今回はAPIを作成しようと思います。
実行環境
実行環境は以下の通りです。
- ubuntu 20.04
- python 3.8
- postgresql: v13
- pipenv 2020.06
使用ライブラリ
以下をインストールしています。
pipenv install sqlalchemy pipenv install Fastapi==0.61.2 pipenv install psycopg2==2.8.6 pipenv install fastapi-sqlalchemy pipenv install pydantic[dotenv]
対象ソース
GitHubにあります。
ソース説明
以下がソース内容です。
|-- Pipfile |-- Pipfile.lock |-- README.md |-- app | |-- run.py <--------- ここから起動開始 | |-- settings | | `-- settings.py <-- 設定ファイル(.env)を読む | |-- urls.py <--------- 受信するURLを記述 |-- layer | |-- __init__.py | |-- infra | | |-- __init__.py | | `-- db <-------- DB関連の内容 | | |-- __init__.py | | |-- action.py <--- CRUD処理を記述 | | |-- db.py <--- engine | | |-- models.py <--- ORM | | `-- schemas.py <--- 受送信のスキーマ | `-- present `-- migration <----- マイグレーション(yoyo-migrations) |-- migrations | `-- 0001_create_addr.py `-- yoyo.ini
データベース環境の指定方法
.envファイルに置くことにしました。
.envに以下のように記述すると、アクセスできるようにしてあります。
DATABASE_URI = 'postgresql://testuser:testuserp@localhost/testdb'
起動
以下で起動します。
$ pipenv run uvicorn app.run:app --reload --host 0.0.0.0 --port 18000
SQLAlchemyの使用方法
大まかにSQLAlchemyの使い方は2つあります。
- SQLAlchemy Core(主にSQLを素で使用する)
- SQLAlchemy ORM(modelを作成し、modelで制御する)
また、使用する際は、以下のような考慮点を自分で組み合わせて開発する必要があります。
- engine(DB接続先)をどのように管理するか
- ORMの場合、modelをどのように作成するか
- sessionをどのように管理するか
今回は、ORMを使用する方針にしました。
そして実質上”fastapi-sqlalchemy”にお任せになってしまいました。
今回のプログラムでは、以下のように使用しています。
DB(engine): layer/infra/db/db.py内で作成(DATABASE_URIもここで指定)する。
model: SQLAlchemy ORMを、layer/infra/db/models.pyで定義する。
session: “fastapi-sqlalchemy”内(DBSessionMiddleware)で作成する。session取得は以下のように行う。
from fastapi_sqlalchemy import db
fastAPI + SQLAlchemyの実現方法はいろいろあると思いますが、現時点では、これが一番お手軽な方法だと思います。
動作確認
作成は以下のようになります。
$ curl -X POST -H "Content-Type: application/json" -d '{"name":"ttttt83iksks", "addr":"100", "ipaddr":"192.168.0.0/16"}' http://localhost:18000/addrs/create
作成したデータは以下のように取得できます。
$ curl http://localhost:18000/addrs/find/4 | jq . { "StatusCode": 200, "ErrorCode": "", "Result": { "update_time": "2020-11-15T14:29:15.784526+09:00", "create_time": "2020-11-15T14:29:15.784509+09:00", "addr": "100", "id": 4, "ipaddr": "192.168.0.0/16", "name": "ttttt83iksks" } }
全体が以下です。
$ curl http://localhost:18000/addrs | jq . { "StatusCode": 200, "ErrorCode": "", "Result": [ { "update_time": "2020-11-15T14:15:58.246082+09:00", "create_time": "2020-11-15T14:15:58.246061+09:00", "addr": "100", "id": 1, "ipaddr": "192.168.0.0/16", "name": "ttttt83iksks" }, { "update_time": "2020-11-15T14:23:10.404737+09:00", "create_time": "2020-11-15T14:23:10.404714+09:00", "addr": "100", "id": 2, "ipaddr": "192.168.0.0/16", "name": "ttttt83iksks" }, { "update_time": "2020-11-15T14:26:29.539578+09:00", "create_time": "2020-11-15T14:26:29.539551+09:00", "addr": "100", "id": 3, "ipaddr": "192.168.0.0/16", "name": "ttttt83iksks" }, { "update_time": "2020-11-15T14:29:15.784526+09:00", "create_time": "2020-11-15T14:29:15.784509+09:00", "addr": "100", "id": 4, "ipaddr": "192.168.0.0/16", "name": "ttttt83iksks" } ] }
updateは以下の通りです。
$ curl -X POST -H "Content-Type: application/json" -d '{"id":4 , "name":"ttttt83iksks", "addr":"住んでいるところ", "ipaddr":"192.168.1.0/16"}' http://localhost:18000/addrs/update {"StatusCode":200,"ErrorCode":"","Result":{}} $ curl "http://localhost:18000/addrs/find/4" | jq . { "StatusCode": 200, "ErrorCode": "", "Result": { "update_time": "2020-11-15T16:21:48.230994+09:00", "create_time": "2020-11-15T14:29:15.784509+09:00", "addr": "住んでいるところ", "id": 4, "ipaddr": "192.168.1.0/16", "name": "ttttt83iksks" } }
削除は以下の通りです。
$ curl -X POST -H "Content-Type: application/json" -d '{"id":4}' http://localhost:18000/addrs/delete {"StatusCode":200,"ErrorCode":"","Result":"delete success"} $ curl "http://localhost:18000/addrs/find/4" | jq . { "StatusCode": 200, "ErrorCode": "", "Result": null }
OpenAPI(/docs)
この時点で自動作成した/docsは以下の通りです。
終わりに
APIを作成するだけなら結構簡単に作れました。
次は(出来たら) Nuxt.jsか何かで、これらAPIを使用して入出力を行う画面を作成したいと思います。
参考
https://fastapi.tiangolo.com/ja/
https://qiita.com/t-iguchi/items/d01b24fed05db43fd0b8