1. ホーム
  2. 記事一覧
  3. 初心者向け FastAPIとSQLiteでユーザー管理アプリを作成するハンズオン

2024.03.29

初心者向け FastAPIとSQLiteでユーザー管理アプリを作成するハンズオン

  • バックエンド
  • エンジニア
  • ハンズオン

このハンズオンの目的

前回はFastAPIについて簡単なアプリを作成してみました。

https://envader.plus/article/333

バックエンドエンジニアを目指すなら、API開発ができることは必須要件といえます。今回のハンズオンでは、FastAPIとSQLiteデータベースを使って簡単なウェブアプリケーションを作成し、Pythonによる現代的なウェブ開発の基本を学びます。

使用するツール・ライブラリの紹介

FastAPI

FastAPIは、Pythonで高性能なAPIを構築するための現代的なフレームワークです。開発速度とコード品質を向上させ、少ないバグでプロダクション環境に移行できることが特徴です。

SQLAlchemy

SQLAlchemyは、Pythonでデータベースとやり取りするためのORMライブラリです。データベース操作を抽象化し、Pythonicなコードで記述できるため、開発効率を高めることができます。

SQLite

SQLiteは、軽量で設定不要のディスクベースデータベースです。小規模なアプリケーションや開発時のテストに最適です。

このハンズオンで学べること

  • FastAPIとSQLAlchemyのインストールと設定方法
  • SQLiteデータベースへの接続と操作方法
  • ユーザーモデルの作成とCRUD操作 (Create, Read, Update, Delete) の実装
  • FastAPIを使ったユーザー一覧の取得

前提条件

必要なもの

  • Python 3.7以降

環境設定

Pythonのバージョン確認

python --version

Python 3.7以上であることを確認してください。

環境準備とプロジェクトのセットアップ

Pythonの標準モジュールであるvenvを使用して、プロジェクト固有の仮想環境を作成し、そこに必要なパッケージをインストールします。これにより、プロジェクトの依存関係が他のプロジェクトやシステム全体のPython環境と干渉しないようにします。

仮想環境の作成

  1. プロジェクトディレクトリの作成

    まず、プロジェクト用のディレクトリを作成します。ターミナルまたはコマンドプロンプトで以下のコマンドを実行してください。

    mkdir my_fastapi_project
    cd my_fastapi_project
  2. 仮想環境の作成

    venvを使用して、現在のディレクトリに仮想環境を作成します。

    python3 -m venv venv

    このコマンドはvenvという名前の仮想環境を現在のディレクトリ内に作成します。

  3. 仮想環境のアクティベーション

    作成した仮想環境をアクティブにします。

    • macOS/Linuxの場合
      source venv/bin/activate
    • Windowsの場合
      .\venv\Scripts\activate

FastAPIとSQLAlchemyのインストール

仮想環境がアクティブになったら、FastAPIとSQLAlchemyをインストールします。

pip install fastapi[all] sqlalchemy
# zsh
pip install "fastapi[all]" sqlalchemy

[all]オプションは、FastAPIの追加機能(非同期サーバーなど)もインストールすることを意味します。

これで、FastAPIとSQLAlchemyを含む必要なパッケージが仮想環境にインストールされます。

プロジェクトのディレクトリ構造

  1. ディレクトリ構造の作成 きれいで管理しやすいプロジェクトのために、次のようなディレクトリ構造を作成します。

     myproject/
     ├── app/
     │   ├── __init__.py     # appディレクトリをPythonパッケージとして認識させる
     │   ├── main.py         # FastAPIアプリケーションとルートエンドポイントの定義
     │   ├── models.py       # SQLAlchemyを使用したデータベースモデルの定義
     │   ├── schemas.py      # Pydanticを使用したリクエストとレスポンスのスキーマ定義
     │   └── database.py     # データベース接続とセッション管理の設定
     └── .env                # 環境変数の定義(例: データベースの接続情報)
    • app/

    アプリケーションのコードを格納するディレクトリ。

    • __init__.py

    Pythonにこのディレクトリがパッケージであることを示すファイル。

    • main.py

    アプリケーションのエントリポイント。ルーティングとアプリケーションの設定を含みます。

    • models.py

    データモデル(SQLAlchemyモデル)を定義するファイル。

    • schemas.py

    Pydanticライブラリを使用して、入出力データのバリデーションに使うスキーマ(シリアライズ/デシリアライズ用のモデル)が定義されます。

    • database.py

    SQLAlchemyを用いたデータベース接続設定とセッション管理を行います。このファイルでengine、SessionLocal、そしてBase(モデルのベースクラス)が定義されます。

    • .env

    環境変数を格納するファイル。データベース接続などの設定をここに記述します。

以上で、FastAPIとSQLiteを使用したウェブアプリ開発のための基本的な環境設定とプロジェクト構造の準備が完了しました。

SQLiteデータベースの設定

SQLiteは、サーバーレスで設定不要の軽量データベースです。アプリケーションのデータを保存するために使用します。このセクションでは、SQLiteデータベースファイルの作成と、SQLAlchemyを通じたデータベースへの接続設定を行います。

SQLiteデータベースファイルの作成

SQLiteデータベースは、ファイルベースのデータベースであるため、特別な設定は必要ありません。データベースを操作するためには、単にデータベースファイルの場所を指定するだけです。ここでは、appディレクトリ内にdatabase.dbファイルを作成することを想定しますが、実際のファイル作成はアプリケーションがデータベースに最初にアクセスした時に自動的に行われます。

データモデルの定義

models.pyファイルに、アプリケーションで使用するデータモデルをSQLAlchemyを使って定義します。例えば、ユーザーモデルを以下のように定義することができます。

from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "sqlite:///./app/database.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    email = Column(String, unique=True, index=True)

このコードでは、Userクラスがデータベースのusersテーブルにマッピングされ、idnameemailの各フィールドが定義されています。

SQLAlchemyとは?

SQLAlchemyは、PythonプログラムからSQLデータベースを操作するためのライブラリです。ORM(Object-Relational Mapping)を提供することで、Pythonオブジェクトとデータベーステーブルの間で自動的にデータ変換を行います。

ORMとは、オブジェクトとデータベーステーブルを自動的に対応付けるテクニックです。これにより、開発者はオブジェクト指向のコードでデータベース操作が可能になります。SQLAlchemyはPythonにおけるORMライブラリの1つです。

schemas.pyの例

from pydantic import BaseModel

class UserCreate(BaseModel):
    name: str
    email: str

class User(BaseModel):
    id: int
    name: str
    email: str

    class Config:
        orm_mode = True

ここで、orm_mode = Trueを設定することで、ORMモデルからデータを読み取る際に、辞書への変換を容易にします。これにより、データベースモデルのインスタンスから直接レスポンスモデルを生成することができます。

ご指摘ありがとうございます。記事の内容と実際のコード例でdatabase.pyの作成について触れられていなかった点、混乱を招いてしまい申し訳ありません。FastAPIアプリケーションでデータベース接続設定を管理するdatabase.pyファイルは、アプリケーションの構造を整理し、データベース操作を効率化する重要な役割を担います。ここでは、database.pyファイルの基本的な内容とその作成方法について説明します。

database.pyファイルの作成

database.pyは、SQLAlchemyのEngineSession、およびベースモデルクラスを定義するファイルです。このファイルを通じて、アプリケーションの他の部分(モデル定義やエンドポイントなど)はデータベースとの接続を管理します。

以下はdatabase.pyの簡単な例です。

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "sqlite:///./database.db"

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

この例では、SQLiteデータベースを使用していますが、必要に応じてDATABASE_URLを変更することで、PostgreSQLやMySQLなど他のデータベースシステムを使用することも可能です。

CRUD操作(作成・読み取り・更新・削除)

FastAPIを使用して、ユーザーデータに対するCRUD操作を行うAPIエンドポイントを作成します。これらのエンドポイントを通じて、クライアントはデータベース内のユーザーデータを作成、取得、更新、削除することができます。

ユーザーの作成

main.pyにユーザーを作成するためのエンドポイントを追加します。この例では、ユーザー名とメールアドレスを受け取り、新しいユーザーをデータベースに追加します。

from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy.orm import Session
from typing import List
from app import models, schemas
from app.database import SessionLocal, engine

@app.post("/users/", response_model=User)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    db_user = db.query(UserModel).filter(UserModel.email == user.email).first()
    if db_user:
        raise HTTPException(status_code=400, detail="Email already registered")
    new_user = UserModel(name=user.name, email=user.email)
    db.add(new_user)
    db.commit()
    db.refresh(new_user)
    return new_user

ユーザーの読み取り

特定のユーザーを取得するためのエンドポイントと、すべてのユーザーを取得するためのエンドポイントを追加します。

@app.get("/users/{user_id}", response_model=User)
def read_user(user_id: int, db: Session = Depends(get_db)):
    db_user = db.query(UserModel).filter(UserModel.id == user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    return db_user

@app.get("/users/", response_model=List[User])
def read_users(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
    users = db.query(UserModel).offset(skip).limit(limit).all()
    return users

ユーザーの更新

ユーザー情報を更新するエンドポイントを追加します。

@app.put("/users/{user_id}", response_model=User)
def update_user(user_id: int, user: UserCreate, db: Session = Depends(get_db)):
    db_user = db.query(UserModel).filter(UserModel.id == user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    db_user.name = user.name
    db_user.email = user.email
    db.commit()
    db.refresh(db_user)
    return db_user

ユーザーの削除

ユーザーを削除するためのエンドポイントを実装します。

@app.delete("/users/{user_id}", status_code=204)
def delete_user(user_id: int, db: Session = Depends(get_db)):
    db_user = db.query(UserModel).filter(UserModel.id == user_id).first()
    if db_user is None:
        raise HTTPException(status_code=404, detail="User not found")
    db.delete(db_user)
    db.commit()
    return {"message": "User deleted successfully"}

これで、FastAPIを使用した基本的なCRUD操作の実装が完了しました。

動作確認

プロジェクトのルートディレクトリ(この例では myproject/)から以下のようにして FastAPI アプリケーションを実行してください。

uvicorn app.main:app --reload

作成したAPIエンドポイントに対して、curlコマンドを使用してユーザーを追加します。

以下の形式を使用します。この例では、エンドポイントがPOST /users/であり、nameemailをJSON形式でリクエストボディに含めて送信することを想定しています。

curl -X 'POST' \
  'http://127.0.0.1:8000/users/' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "新しいユーザーの名前",
  "email": "user@example.com"
}'

http://127.0.0.1:8000/users/に接続し、[{"id":1,"name":"新しいユーザーの名前","email":"user@example.com"}]のように表示されていれば完成です。

アプリのテストとデバッグ

アプリケーション開発において、テストとデバッグは非常に重要です。これにより、コードに潜むバグを早期に発見し、期待通りの動作をするかを確認できます。FastAPIには、テストを容易にするツールが備わっています。

FastAPIのテスト

FastAPIはpytestを使用したテストに対応しています。以下は、ユーザー作成エンドポイントのテストの基本的な例です。

from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from .main import app
from .database import Base
from .models import User

SQLALCHEMY_DATABASE_URL = "sqlite:///./database.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base.metadata.create_all(bind=engine)

client = TestClient(app)

def test_create_user():
    response = client.post(
        "/users/",
        json={"name": "testuser", "email": "test@example.com"},
    )
    assert response.status_code == 200
    data = response.json()
    assert data["email"] == "test@example.com"
    assert "id" in data

このテストコードでは、TestClientを使用してAPIエンドポイントにリクエストを送り、レスポンスを検証しています。

デバッグ

開発中に問題が発生した場合、FastAPIの自動ドキュメント(Swagger UIやReDoc)を利用して、リクエストとレスポンスの内容を確認することが役立ちます。また、printステートメントやPythonのデバッガを使用して、コードの実行フローを追跡し、変数の値を確認することも有効です。

FastAPIアプリケーションの実行中に問題が発生した場合、次の手順でトラブルシューティングを行います。

  1. エラーメッセージを確認

    多くの場合、エラーメッセージには問題解決の手がかりが含まれています。

  2. リクエストとレスポンスを検証

    FastAPIの自動ドキュメントツールを使用して、送受信されるデータの形式が正しいか確認します。

  3. コードのステップスルー

    Pythonのデバッガを使用して、コードの実行を一歩ずつ進め、問題の原因を突き止めます。

Swagger UIの基本的な使い方

FastAPIを使って構築されたアプリケーションでは、Swagger UIはデフォルトで有効になっています。アプリケーションを起動した後、Webブラウザを使用してSwagger UIにアクセスすることができます。

FastAPIアプリケーションがローカルで実行されている場合、通常は http://127.0.0.1:8000/docs にアクセスすることでSwagger UIを開くことができます。ポート番号は、アプリケーションの起動時に指定したものに依存します。

以上、FastAPIとSQLAlchemyを使用したアプリケーションの基本的なテストとデバッグ方法について説明しました。ここまでの内容を通して、アプリケーション開発からテストに至る一連の流れを理解できたと思います。

これからはより実践的なアプリケーションを構築していく上で、テストの自動化やデバッグの高度なテクニックが必要になってくるでしょう。しかし、ここで学んだ基本を土台にすれば、着実にスキルを伸ばすことができます。

## 身につけたこと

この記事を通じて、FastAPIとSQLAlchemyを使用して基本的なウェブアプリケーションを開発するスキルを身につけることができました。具体的には、Pythonの仮想環境の設定、FastAPIとSQLAlchemyの基本的な使い方、CRUD操作の実装、そしてAPIのドキュメント作成とテストに関する知識を獲得しました。これらのスキルは、現代のウェブ開発において非常に重要であり、様々なプロジェクトや実務で直接活用することが可能です。

できるようになったこと

  • 仮想環境の管理

    Pythonの仮想環境をpipenvを使って管理し、プロジェクトの依存関係を効果的に扱えるようになりました。

  • FastAPIでのウェブアプリケーション開発

    FastAPIを使って、リクエストを処理し、レスポンスを返すエンドポイントを設計できるようになりました。

  • データモデルの定義とデータベース操作

    SQLAlchemyを使用してデータモデルを定義し、SQLiteデータベースとの間でCRUD操作を行えるようになりました。

  • APIのテストとドキュメントの自動生成

    Swagger UIを活用してAPIのテストを行い、APIの使用方法を文書化できるようになりました。

このハンズオンで習得したスキルと知識を実践に活かし、実際のプロジェクトでFastAPIとSQLAlchemyの強力な機能をフルに活用することで、効率的でスケーラブルなウェブアプリケーションの開発を実現できます。

つまり、バックエンドエンジニアとしてAPI開発をできるようになったということです。

参考文献とリソース

エンベーダー編集部

エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

RareTECH 無料体験授業開催中! オンラインにて実施中! Top10%のエンジニアになる秘訣を伝授します! RareTECH講師への質疑応答可

関連記事