0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FastAPIで独自のフォーラムを構築:ステップ1 - ミニマルフォーラム

Posted at

Cover

市場にはすでに多くのフォーラム製品がありますが、どれもあなたのユニークなニーズを満たせず、まだイライラしていませんか?もしそうなら、なぜ自分でフォーラムをゼロから構築しないのでしょうか?

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のインストール

次に、この記事で必要となるコアライブラリ、fastapiuvicornをインストールします。

  • 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!"}

このコードは何をするのでしょうか?

  1. FastAPIのインスタンスを作成し、appと名付けます。
  2. @app.get("/")はデコレーターです。これは、以下のread_root関数がパス/に来るGETリクエストを処理することを示しています。
  3. ルートパスにリクエストが到達すると、関数は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.pyPostモデルを定義しましょう。

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をリフレッシュまたは再訪問すると、既存の投稿と新しい投稿を作成するためのフォームが表示されたフォーラムページが表示されます。

ImageP1

フォームにコンテンツを入力して送信すると、新しい投稿が投稿リストに表示されます。

ImageP2

プロジェクトのオンラインデプロイ

フォーラムは皆に使ってもらうためのものなので、ローカルで実行するだけでは十分ではありません。次に、オンラインでデプロイしましょう。

簡単なデプロイオプションはLeapcellを使用することです。これは、FastAPIを含むさまざまな言語やフレームワークのプロジェクトをホストできるWebアプリケーションホスティングプラットフォームです。

Leapcell

以下の手順に従ってください:

  1. ウェブサイトでアカウントを登録します。
  2. プロジェクトをGitHubにコミットします。GitHubの公式ドキュメントを参照して手順を確認してください。Leapcellは後でGitHubリポジトリからコードを取得します。
  3. Leapcellページで「Create Service」をクリックします。
    LeapcellImageP1
  4. FastAPIリポジトリを選択すると、Leapcellが必要な構成を自動入力したことが表示されます。
    LeapcellImageP2
  5. 下部にある「Submit」をクリックしてデプロイします。デプロイはすぐに完了し、デプロイホームページに戻ります。ここで、Leapcellがドメインを提供していることがわかります。これがご自身のブログのオンラインアドレスです。
    LeapcellImageP3

結論

わずかなステップで、FastAPIを使用して、最も基本的な機能を備えたフォーラムプロトタイプをゼロから構築しました。

このフォーラムはまだ非常に不完全です。例えば、サーバーが再起動すると、すべての新しい投稿が消えてしまいます。これは明らかに許容できません。

次の記事では、永続的なデータストレージを可能にするために、実際のデータベースをフォーラムに導入します。


Xでフォローする:@LeapcellJapan


ブログでこの記事を読む

関連記事:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?