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

2024.04.06

初心者向け 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の仮想環境をvenvを使って管理し、プロジェクトの依存関係を効果的に扱えるようになりました。

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

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

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

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

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

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

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

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

参考文献とリソース

【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

IT未経験者必見 USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。

「フリーランスエンジニア」

近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。

「成功する人とそうでない人の違いは何か?」

私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。

比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。

多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、

note記事3000いいね超えの殿堂記事 今すぐ読む

エンベーダー編集部

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

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

関連記事