Open5

Python FastAPIでMySQLデータベースに接続する

Teru roomTeru room
  • 環境:
    • 開発用PC :
      • note PC : Apple / macBook Pro2017年モデル
        • OS : macOS Ventura13.2.1
          • 最新のmac mini proが欲しい・・・・。でもお金がない(涙)
      • mini PC : MINIS FORLUM / Elitemini X400
        • OS : Windows 11 Pro
  • 参考資料:FastAPI

Python FastAPIは、高速で現代的なWebアプリケーションを開発するための人気のあるWebフレームワークです。FastAPIを使用してMySQLデータベースに接続する方法を以下に示します。

  • (base) macpro:~ sharland$ brew services start mysql
  • (base) macpro:~ sharland$ cd dev
  • (base) macpro:dev sharland$ mkdir fastapi;cd fastapi;mkdir MySQL;cd MySQL
  • (base) macpro:MySQL sharland$ python -m venv /Users/sharland/dev/fastapi/MySQL/venv
  • (base) macpro:MySQL sharland$ source ./venv/bin/activate
  • (venv) (base) macpro:MySQL sharland$ pip install --upgrade pip
実行結果
Collecting pip
  Using cached https://files.pythonhosted.org/packages/ae/db/a8821cdac455a1740580c92de3ed7b7f257cfdbad8b1ba8864e6abe58a08/pip-23.1-py3-none-any.whl
Installing collected packages: pip
  Found existing installation: pip 19.0.3
    Uninstalling pip-19.0.3:
      Successfully uninstalled pip-19.0.3
Successfully installed pip-23.1

MySQLのPythonライブラリをインストールする: FastAPIでは、MySQLデータベースに接続するために、PythonのMySQLクライアントライブラリを使用する必要があります。例えば、mysql-connector-pythonやpymysqlなどがあります。これらのライブラリをインストールします。

  • (venv) (base) macpro:MySQL sharland$ pip install mysql-connector-python
実行結果
Collecting mysql-connector-python
  Using cached mysql_connector_python-8.0.32-py2.py3-none-any.whl (381 kB)
Collecting protobuf<=3.20.3,>=3.11.0 (from mysql-connector-python)
  Using cached protobuf-3.20.3-cp37-cp37m-macosx_10_9_x86_64.whl (981 kB)
Installing collected packages: protobuf, mysql-connector-python
Successfully installed mysql-connector-python-8.0.32 protobuf-3.20.3
  • (venv) (base) macpro:MySQL sharland$ pip install fastapi
実行結果
Collecting fastapi
  Downloading fastapi-0.95.1-py3-none-any.whl (56 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 57.0/57.0 kB 5.8 MB/s eta 0:00:00
Collecting pydantic!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0,>=1.6.2 (from fastapi)
  Downloading pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl (2.8 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.8/2.8 MB 13.2 MB/s eta 0:00:00
Collecting starlette<0.27.0,>=0.26.1 (from fastapi)
  Downloading starlette-0.26.1-py3-none-any.whl (66 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 66.9/66.9 kB 7.4 MB/s eta 0:00:00
Collecting typing-extensions>=4.2.0 (from pydantic!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0,>=1.6.2->fastapi)
  Using cached typing_extensions-4.5.0-py3-none-any.whl (27 kB)
Collecting anyio<5,>=3.4.0 (from starlette<0.27.0,>=0.26.1->fastapi)
  Downloading anyio-3.6.2-py3-none-any.whl (80 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 80.6/80.6 kB 8.5 MB/s eta 0:00:00
Collecting idna>=2.8 (from anyio<5,>=3.4.0->starlette<0.27.0,>=0.26.1->fastapi)
  Using cached idna-3.4-py3-none-any.whl (61 kB)
Collecting sniffio>=1.1 (from anyio<5,>=3.4.0->starlette<0.27.0,>=0.26.1->fastapi)
  Downloading sniffio-1.3.0-py3-none-any.whl (10 kB)
Installing collected packages: typing-extensions, sniffio, idna, pydantic, anyio, starlette, fastapi
Successfully installed anyio-3.6.2 fastapi-0.95.1 idna-3.4 pydantic-1.10.7 sniffio-1.3.0 starlette-0.26.1 typing-extensions-4.5.0

本番環境では、Uvicorn または、 Hypercornのような、 ASGI サーバーが必要になります。

  • (venv) (base) macpro:MySQL sharland$ pip install "uvicorn[standard]"
実行結果
Collecting uvicorn[standard]
  Downloading uvicorn-0.21.1-py3-none-any.whl (57 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 57.8/57.8 kB 5.4 MB/s eta 0:00:00
Collecting click>=7.0 (from uvicorn[standard])
  Downloading click-8.1.3-py3-none-any.whl (96 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 96.6/96.6 kB 10.0 MB/s eta 0:00:00
Collecting h11>=0.8 (from uvicorn[standard])
  Downloading h11-0.14.0-py3-none-any.whl (58 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 58.3/58.3 kB 6.1 MB/s eta 0:00:00
Requirement already satisfied: typing-extensions in ./venv/lib/python3.7/site-packages (from uvicorn[standard]) (4.5.0)
Collecting httptools>=0.5.0 (from uvicorn[standard])
  Downloading httptools-0.5.0-cp37-cp37m-macosx_10_9_x86_64.whl (159 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 159.4/159.4 kB 11.4 MB/s eta 0:00:00
Collecting python-dotenv>=0.13 (from uvicorn[standard])
  Downloading python_dotenv-0.21.1-py3-none-any.whl (19 kB)
Collecting pyyaml>=5.1 (from uvicorn[standard])
  Downloading PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl (189 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 189.3/189.3 kB 9.7 MB/s eta 0:00:00
Collecting uvloop!=0.15.0,!=0.15.1,>=0.14.0 (from uvicorn[standard])
  Downloading uvloop-0.17.0-cp37-cp37m-macosx_10_9_x86_64.whl (1.5 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.5/1.5 MB 9.1 MB/s eta 0:00:00
Collecting watchfiles>=0.13 (from uvicorn[standard])
  Downloading watchfiles-0.19.0-cp37-abi3-macosx_10_7_x86_64.whl (405 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 406.0/406.0 kB 14.1 MB/s eta 0:00:00
Collecting websockets>=10.4 (from uvicorn[standard])
  Downloading websockets-11.0.1-cp37-cp37m-macosx_10_9_x86_64.whl (120 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 120.7/120.7 kB 12.0 MB/s eta 0:00:00
Collecting importlib-metadata (from click>=7.0->uvicorn[standard])
  Using cached importlib_metadata-6.4.1-py3-none-any.whl (22 kB)
Requirement already satisfied: anyio>=3.0.0 in ./venv/lib/python3.7/site-packages (from watchfiles>=0.13->uvicorn[standard]) (3.6.2)
Requirement already satisfied: idna>=2.8 in ./venv/lib/python3.7/site-packages (from anyio>=3.0.0->watchfiles>=0.13->uvicorn[standard]) (3.4)
Requirement already satisfied: sniffio>=1.1 in ./venv/lib/python3.7/site-packages (from anyio>=3.0.0->watchfiles>=0.13->uvicorn[standard]) (1.3.0)
Collecting zipp>=0.5 (from importlib-metadata->click>=7.0->uvicorn[standard])
  Using cached zipp-3.15.0-py3-none-any.whl (6.8 kB)
Installing collected packages: zipp, websockets, uvloop, pyyaml, python-dotenv, httptools, h11, watchfiles, importlib-metadata, click, uvicorn
Successfully installed click-8.1.3 h11-0.14.0 httptools-0.5.0 importlib-metadata-6.4.1 python-dotenv-0.21.1 pyyaml-6.0 uvicorn-0.21.1 uvloop-0.17.0 watchfiles-0.19.0 websockets-11.0.1 zipp-3.15.0
Teru roomTeru room

FastAPIの依存関係を定義するためのPythonファイル名は特定の命名規則がありません。一般的には、FastAPIの依存関係を定義する関数を含むPythonファイルを、アプリケーションの機能や役割に合った名前で命名すると良いでしょう。

例えば、上記の例で示したMySQLデータベースへの接続を定義する依存関係の関数を含むPythonファイルを、db.pyやdatabase.pyのように、データベース関連の機能を持つことを示す名前にすることが一般的です。

また、FastAPIの依存関係を定義する関数を複数持つ場合や、異なる機能の依存関係を定義する場合には、それぞれの機能を明確に示す名前を付けると、コードの可読性を向上させることができます。

例えば、以下のようなファイル名を考えることができます。

  • db.py: MySQLデータベースへの接続を定義する依存関係を含むファイル。
  • auth.py: 認証関連の依存関係を定義するファイル。
  • validation.py: 入力データのバリデーションを行う依存関係を定義するファイル。
    また、プロジェクトの規模や構造に応じて、ディレクトリやモジュールの階層を設計することもできます。依存関係を定義する関数を含むPythonファイルを適切なディレクトリに配置し、モジュールとして組織化することで、コードの管理や保守性を向上させることができます。

FastAPIのデペンデンシーにMySQLクライアントライブラリを追加する: FastAPIのdependenciesを使用して、MySQLクライアントライブラリをアプリケーションに追加します。例えば、mysql-connector-pythonを使用する場合、以下のようにデペンデンシーを追加します。

  • (venv) (base) macpro:MySQL sharland$ touch routers/db.py
routers/db.py
from fastapi import Depends
import mysql.connector

def get_db_connection():
    connection = mysql.connector.connect(
        host="localhost",
        user="root",
        password="",
        database="example_db"
    )
    return connection

def get_db():
    connection = get_db_connection()
    db = connection.cursor()
    try:
        yield db
    finally:
        db.close()
        connection.close()
Teru roomTeru room

ルーターでMySQLデータベースを使用する: FastAPIのルーターでMySQLデータベースを使用するには、上記で定義したget_db関数を依存関係として使用します。以下は、FastAPIのルーターでMySQLデータベースを使用する例です。

FastAPIのルーターでMySQLデータベースを使用する例のPythonファイル名は、一般的にアプリケーションの機能や役割に合った名前を付けると良いでしょう。以下のようなファイル名を考えることができます。

  • main.py: アプリケーションのメインエントリポイントであり、FastAPIのルーターを定義し、MySQLデータベースを使用する例のコードを含むファイル。
  • router.py: FastAPIのルーターを定義するファイルであり、MySQLデータベースを使用する例のコードを含むファイル。
  • db.py: MySQLデータベースへの接続やクエリを行う関数を含むファイル。
    また、プロジェクトの規模や構造に応じて、ディレクトリやモジュールの階層を設計することもできます。例えば、routersというディレクトリを作成し、その中にFastAPIのルーターを定義するモジュールを作成し、その中にMySQLデータベースを使用する例のコードを含めると、コードの組織化や可読性を向上させることができます。

例えば、以下のようなファイル名やディレクトリ構造を考えることができます。

  • main.py: アプリケーションのメインエントリポイントであり、routersディレクトリ内のルーターモジュールをインポートして使用するファイル。

  • routers/db_router.py: MySQLデータベースを使用する例のルーターを定義するモジュール。

  • routers/db.py: MySQLデータベースへの接続やクエリを行う関数を定義するモジュール。

  • (venv) (base) macpro:MySQL sharland$ mkdir routers;touch routers/db_router.py;vim routers/db_router.py

routers/db_router.py
ffrom fastapi import FastAPI, Depends
from mysql.connector import cursor
from db import get_db  # db.pyのget_db()関数をインポート
import json

app = FastAPI()

# MySQLデータベースに接続する依存関係
def get_db(db: cursor.MySQLCursor = Depends(get_db)):
    return db

# ルーターでMySQLデータベースを使用する
@app.get("/users/")
async def get_user(db: cursor.MySQLCursor = Depends(get_db)):
    query = "SELECT * FROM users"
    db.execute(query)
    result = db.fetchall()
    if result:
        return {"users":result}
    else:
        return {"error": "User not found"}

@app.get("/users/{user_id}")
async def get_user(user_id: int
                   , db: cursor.MySQLCursor = Depends(get_db)):
    query = "SELECT * FROM users WHERE id = %s"
    db.execute(query, (user_id,))
    result = db.fetchone()
    if result:
        return {"user_id": result[0], "username": result[1]}
    else:
        return {"error": "User not found"}

@app.get("/user_name/{user_name}")
async def insert_user(user_name:str
                      ,db: cursor.MySQLCursor = Depends(get_db)):
    query = "INSERT INTO users (name) VALUES (%s)"
    db.execute(query, (user_name,))
    result = db.fetchone()
    db.execute("COMMIT")
    return {"user_name":user_name}
Teru roomTeru room

以下のコマンドでサーバーを起動します:

  • (venv) (base) macpro:MySQL sharland$ cd routers/
  • (venv) (base) macpro:routers sharland$ uvicorn db_router:app --reload
実行結果
INFO:     Will watch for changes in these directories: ['/Users/sharland/dev/fastapi/MySQL/routers']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [60501] using WatchFiles
INFO:     Started server process [60503]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

ブラウザで http://127.0.0.1:8000/docs にアクセスするとGUIでFast APIサービスを操作できる画面が表示されます

  • 参照
    • ID指定
      • URL: http://127.0.0.1:8000/users/2
      • 返却JSON: {"user_id":2,"username":"鈴木 一郎"}
    • 全レコード
      • URL: http://127.0.0.1:8000/users/
      • 返却JSON: {"users":[[1,"山田 太朗"],[2,"鈴木 一郎"],[3,"森田 花子"],[4,"本堂 新一"],[5,"橋本 一郎"],[6,"橋口 洋子"],[7,"田辺 果林"],[8,"高橋 健二"]]}
  • 追加
    • URL: http://127.0.0.1:8000/user_name/高橋 健二
    • 返却JSON: {"user_name":"高橋 健二"}