市場にはすでに多くのフォーラム製品がありますが、どれもあなたのユニークなニーズを満たせず、まだイライラしていませんか?もしそうなら、なぜ自分でフォーラムをゼロから構築しないのでしょうか?
Discourseのような巨大なフォーラムSaaSプラットフォームに臆することはありません。フォーラムの構築は、思っているほど難しくありません。
今後の記事シリーズでは、人気のあるPython WebフレームワークであるFastAPIを使用して、完全に機能するモダンなフォーラムWebサイトをゼロから段階的にガイドします。
このチュートリアルシリーズは初心者向けです。この記事の最後までに、以下に示すような、実行可能なミニフォーラムが完成するでしょう。
早速始めましょう:
ステップ1:環境セットアップ
まず、開発環境を準備しましょう。
プロジェクトディレクトリと仮想環境の作成
プロジェクト専用のフォルダを作成し、その中に仮想環境を作成します。
簡単のため、Pythonの組み込みvenvモジュールを使用します。poetryのような、他にも素晴らしい仮想環境ツールがたくさんあります。これらについてはご自身で調べてみてください。
# プロジェクトディレクトリを作成して移動
mkdir fastapi-forum
cd fastapi-forum
# 仮想環境を作成
python3 -m venv venv
# 仮想環境をアクティベート
# Windows:
# venv\Scripts\activate
# macOS / Linux:
source venv/bin/activate
アクティベーションが成功すると、コマンドラインプロンプトの先頭に(venv)が表示されます。
FastAPIとUvicornのインストール
次に、この記事で必要となるコアライブラリ、fastapiとuvicornをインストールします。
-
fastapi: フレームワーク自体。 -
uvicorn: FastAPIアプリケーションを実行するために使用されるASGIサーバー。
pip install fastapi "uvicorn[standard]"
"uvicorn[standard]"は、最適なパフォーマンスのために推奨される依存関係とともにuvicornをインストールします。
ステップ2:「こんにちは、フォーラム!」 FastAPIアプリを実行する
環境が整ったので、最初のFastAPIコードを記述しましょう。fastapi-forumディレクトリにmain.pyという名前のファイルを作成し、以下の内容を追加します:
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello, Forum!"}
このコードは何をするのでしょうか?
-
FastAPIのインスタンスを作成し、appと名付けます。 -
@app.get("/")はデコレーターです。これは、以下のread_root関数がパス/に来るGETリクエストを処理することを示しています。 - ルートパスにリクエストが到達すると、関数はPython辞書を返します。FastAPIはこれを自動的にJSONレスポンスに変換します。
次に、ターミナルからアプリケーションを実行します:
uvicorn main:app --reload
-
main:main.pyファイルを指します。 -
app:main.pyで作成したFastAPIインスタンスappを指します。 -
--reload: コード変更後にサーバーが自動的に再起動する、非常に便利なパラメータです。
これで、ブラウザを開いてhttp://127.0.0.1:8000にアクセスすると、以下のように表示されます:
{ "message": "Hello, Forum!" }
おめでとうございます!最初のFastAPIアプリケーションが正常に実行されました!
ステップ3:コアデータ構造の定義
私たちのフォーラムは投稿を公開するためのものなので、「投稿」がどのようなものかを定義する明確なデータ構造が必要です。FastAPIでは、データ定義と検証にPydanticを使用することを推奨しています。これはFastAPIに組み込まれており、非常に強力です。
main.pyにPostモデルを定義しましょう。
main.py(更新版)
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
# 1. データモデルの定義
class Post(BaseModel):
id: int
title: str
content: str
app = FastAPI()
# 2. インメモリデータベースとしてリストを使用
# 注:これはデモンストレーション目的のみです。サーバー再起動でデータは失われます!
db: List[Post] = [
Post(id=1, title="What is FastAPI?", content="A modern, high-performance Python web framework..."),
Post(id=2, title="Introduction to Pydantic", content="Pydantic is a library for data validation and settings management..."),
]
@app.get("/")
def read_root():
return {"message": "Welcome to my forum!"}
# 後続のAPIはここに追加されます...
pydantic.BaseModelを継承するPostクラスを作成しました。投稿には3つのフィールド、id(整数)、title(文字列)、content(文字列)が必要であると定義しました。
また、dbという名前のリストを作成し、データベースをシミュレートするために2つのPostオブジェクトを事前に入力しました。
ステップ4:コアAPIの実装
基本的なフォーラムには、投稿の表示と投稿の作成という2つの機能が必要です。対応するAPIエンドポイントを実装しましょう。
1. 全投稿の取得
dbリスト内のすべての投稿を返すエンドポイントが必要です。main.pyに以下のコードを追加します:
main.py(継続)
... # 前のコードは変更なし
# 3. 投稿リストを取得するAPI
@app.get("/api/posts", response_model=List[Post])
def get_posts():
return db
-
@app.get("/api/posts"):GETリクエストを処理する新しいパス/api/postsを定義します。 -
response_model=List[Post]: このエンドポイントのレスポンスボディはPostオブジェクトのリストになることをFastAPIに伝えます。FastAPIはこれをデータ検証、変換、およびAPIドキュメントでの明確なドキュメントに使用します。
2. 新規投稿の作成
次に、新しい投稿を作成するためのエンドポイントです。
まず、フォームデータの処理をサポートするためにpython-multipartをインストールします:
pip install python-multipart
main.py(継続)
# ... 前のコードは変更なし
# 4. 新規投稿を作成するAPI
@app.post("/api/posts", response_model=Post)
def create_post(title: str = Form(...), content: str = Form(...)):
new_id = len(db) + 1
new_post = Post(
id=new_id,
title=title,
content=content
)
db.append(new_post)
return new_post
title: str = Form(...)というパラメータ形式は、FastAPIにフォームフィールドからデータを抽出するように指示します。
入力/出力形式がフォームフィールドであるのはなぜですか?後でユーザーがフォームを通じて投稿コンテンツを送信できるHTMLページを作成するためです。
ステップ5:シンプルなインタラクティブページ
純粋なAPIはフォーラムとは呼べません。FastAPIのHTMLResponseを使用して、ユーザーがブラウザで直接投稿を作成および表示できる、実行可能なHTMLページをすばやく作成できます。
このページを表示するために新しいパスGET /postsを作成します。
main.py(最終完全版)
from fastapi import FastAPI, Form
from fastapi.responses import HTMLResponse, RedirectResponse
from pydantic import BaseModel
from typing import List
# --- データモデル ---
class Post(BaseModel):
id: int
title: str
content: str
# --- インメモリデータベース ---
db: List[Post] = [
Post(id=1, title="What is FastAPI?", content="A modern, high-performance Python web framework..."),
Post(id=2, title="Introduction to Pydantic", content="Pydantic is a library for data validation and settings management..."),
]
app = FastAPI()
# --- HTMLテンプレート ---
def generate_html_response():
posts_html = ""
for post in reversed(db): # 新しい投稿を上に表示
posts_html += f"""
<div style="border: 1px solid #ccc; padding: 10px; margin-bottom: 10px;">
<h3>{post.title} (ID: {post.id})</h3>
<p>{post.content}</p>
</div>
"""
html_content = f"""
<html>
<head>
<title>My FastAPI Forum</title>
<style>
body {{ font-family: sans-serif; margin: 2em; }}
input, textarea {{ width: 100%; padding: 8px; margin-bottom: 10px; box-sizing: border-box; }}
button {{ padding: 10px 15px; background-color: #007BFF; color: white; border: none; cursor: pointer; }}
button:hover {{ background-color: #0056b3; }}
</style>
</head>
<body>
<h1>Welcome to My Forum</h1>
<h2>Create a New Post</h2>
<form action="/api/posts" method="post">
<input type="text" name="title" placeholder="Post Title" required><br>
<textarea name="content" rows="4" placeholder="Post Content" required></textarea><br>
<button type="submit">Post</button>
</form>
<hr>
<h2>Post List</h2>
{posts_html}
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
# --- ルート ---
@app.get("/", response_class=RedirectResponse)
def read_root():
# ルートパスをビューページにリダイレクト
return "/posts"
# ページを表示するルート
@app.get("/posts", response_class=HTMLResponse)
async def view_posts():
return generate_html_response()
@app.post("/api/posts")
def create_post(title: str = Form(...), content: str = Form(...)):
new_id = len(db) + 1
new_post = Post(
id=new_id,
title=title,
content=content
)
db.append(new_post)
# 更新効果のために、投稿後にメインページにリダイレクト
return RedirectResponse(url="/posts", status_code=303)
generate_html_response関数を使用して、フォームと投稿リストを含む完全なHTMLページを動的に生成します。これは原始的ですが、この段階では完全に十分です。
GET /postsは生成されたHTMLページを直接返します。これにより、ユーザーが/postsにアクセスするとフォーラムインターフェースが表示されます。さらに、ルートパス/は/postsにリダイレクトされるため、ルートURLにアクセスしたユーザーは自動的にフォーラムページに移動します。
GET /api/postsが削除されていることに気づくかもしれません。これは、投稿リストを取得するために別のAPIを必要としなくなったためです。ページはインメモリdbから直接データを読み取ります。
また、POST /api/postsのロジックも変更しました。Postオブジェクトを返すのではなく、/postsページにリダイレクトするようになり、ユーザーは送信後に更新された投稿リストをすぐに確認できます。
フォーラムの実行
Uvicornサーバーがまだ実行中であることを確認してください。http://127.0.0.1:8000をリフレッシュまたは再訪問すると、既存の投稿と新しい投稿を作成するためのフォームが表示されたフォーラムページが表示されます。
フォームにコンテンツを入力して送信すると、新しい投稿が投稿リストに表示されます。
プロジェクトのオンラインデプロイ
フォーラムは皆に使ってもらうためのものなので、ローカルで実行するだけでは十分ではありません。次に、オンラインでデプロイしましょう。
簡単なデプロイオプションはLeapcellを使用することです。これは、FastAPIを含むさまざまな言語やフレームワークのプロジェクトをホストできるWebアプリケーションホスティングプラットフォームです。
以下の手順に従ってください:
- ウェブサイトでアカウントを登録します。
- プロジェクトをGitHubにコミットします。GitHubの公式ドキュメントを参照して手順を確認してください。Leapcellは後でGitHubリポジトリからコードを取得します。
- Leapcellページで「Create Service」をクリックします。
- FastAPIリポジトリを選択すると、Leapcellが必要な構成を自動入力したことが表示されます。
- 下部にある「Submit」をクリックしてデプロイします。デプロイはすぐに完了し、デプロイホームページに戻ります。ここで、Leapcellがドメインを提供していることがわかります。これがご自身のブログのオンラインアドレスです。
結論
わずかなステップで、FastAPIを使用して、最も基本的な機能を備えたフォーラムプロトタイプをゼロから構築しました。
このフォーラムはまだ非常に不完全です。例えば、サーバーが再起動すると、すべての新しい投稿が消えてしまいます。これは明らかに許容できません。
次の記事では、永続的なデータストレージを可能にするために、実際のデータベースをフォーラムに導入します。
Xでフォローする:@LeapcellJapan
関連記事:



