スクリプトのお勉強

fastapi + SQLAlchemy で CRUDアプリケーションを作ってみる

投稿日:2020年11月15日 更新日:

概要

勉強用に、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

-スクリプトのお勉強
-,

執筆者:

関連記事

Svelte(Carbon Components Svelte) + Python(FastAPI)でWebアプリを作る

Svelte用のサンプルとして、Carbon Components SvelteのTreeViewを試用してファイルツリーを表示し、各データはAPIとして読み出し、編集するWebアプリケーションを実装 …

gradleのcommandLineでリダイレクト

gradleというビルドツールがあります。なぜかRPMを作成するのに使ってます。Ansibleも使ってるんですがね。。 それはともかく、ここの通りなのですが、例えばls -lRの出力を、プロジェクトデ …

整形/文法チェック ツール インストールまとめ

1.はじめに 最近、仕事で複数スクリプトを組み合わせてコーディングすることが多くなりました。 それだと、各スクリプトの癖を忘れたり、そもそもどう書くのか忘れたりと、不良を作りこむ可能性が多くなります。 …

Python3 – VCR.py でネットワーク系テストを簡単に作成する

1. 始めに python3で実装すると、モックテストをしたくなります。モックを使って、比較的簡単にテストできるからです。 問題はネットワーク系テスト モックテストで問題になるのは、外部に依存するテス …

PyWebIOでform 入力+ REST API呼び出しを作ってみる

仕事柄、簡単なWebアプリを作りたいと思うことはよくあり、その場合はその場で直せるスクリプトで書きたいとよく思うものです。 すごーく簡単なフォームを非常に簡単に使いたいので、まずは簡単に作れるフレーム …

google オプトアウト Click here to opt-out.