このハンズオンの目的
前回は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環境と干渉しないようにします。
仮想環境の作成
-
プロジェクトディレクトリの作成
まず、プロジェクト用のディレクトリを作成します。ターミナルまたはコマンドプロンプトで以下のコマンドを実行してください。
mkdir my_fastapi_project cd my_fastapi_project
-
仮想環境の作成
venv
を使用して、現在のディレクトリに仮想環境を作成します。python3 -m venv venv
このコマンドは
venv
という名前の仮想環境を現在のディレクトリ内に作成します。 -
仮想環境のアクティベーション
作成した仮想環境をアクティブにします。
- macOS/Linuxの場合
source venv/bin/activate
- Windowsの場合
.\venv\Scripts\activate
- macOS/Linuxの場合
FastAPIとSQLAlchemyのインストール
仮想環境がアクティブになったら、FastAPIとSQLAlchemyをインストールします。
pip install fastapi[all] sqlalchemy
# zsh
pip install "fastapi[all]" sqlalchemy
[all]
オプションは、FastAPIの追加機能(非同期サーバーなど)もインストールすることを意味します。
これで、FastAPIとSQLAlchemyを含む必要なパッケージが仮想環境にインストールされます。
プロジェクトのディレクトリ構造
-
ディレクトリ構造の作成 きれいで管理しやすいプロジェクトのために、次のようなディレクトリ構造を作成します。
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
テーブルにマッピングされ、id
、name
、email
の各フィールドが定義されています。
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のEngine
、Session
、およびベースモデルクラスを定義するファイルです。このファイルを通じて、アプリケーションの他の部分(モデル定義やエンドポイントなど)はデータベースとの接続を管理します。
以下は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/
であり、name
とemail
を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アプリケーションの実行中に問題が発生した場合、次の手順でトラブルシューティングを行います。
-
エラーメッセージを確認
多くの場合、エラーメッセージには問題解決の手がかりが含まれています。
-
リクエストとレスポンスを検証
FastAPIの自動ドキュメントツールを使用して、送受信されるデータの形式が正しいか確認します。
-
コードのステップスルー
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開発をできるようになったということです。
参考文献とリソース
- FastAPI公式ドキュメント: FastAPIの詳細なガイドとベストプラクティス。
- SQLAlchemy公式ドキュメント: SQLAlchemyの使用方法とリファレンス。
- Swagger UIドキュメント: APIドキュメントの生成とテストに役立つツールの詳細。
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.10.17
AWS Lambdaの基本 Lambda関数のバージョン管理を理解しよう
この記事では、Lambda関数の中でも「バージョン管理」について解説していきます。
- AWS
- ハンズオン
2024.07.31
Terraformハンズオン】EC2のスケールアウトをスケジュールしてみよう
こちらの記事では、IaCツールのTerraformを使用し、EC2インスタンスのスケールアウトをスケジュールして実行する方法を解説します。
- AWS
- ハンズオン
2024.05.25
Easy RSAを使用したFQDN証明書の生成とAWS ACMへの登録
この記事では、Easy RSAを使用してOpenVPN用の証明書を生成し、それをAWS ACMに登録する手順を説明します。証明書は、VPN接続のセキュリティを確保するために重要です。
- サイバーセキュリティ
- ハンズオン