コンテンツにスキップ

FastAPIデスクトップツール-001

[質問]

FastAPIをバックエンドとして、ブラウザからアクセスするマイクロブログを作ってください。個人利用なのでユーザー登録は不要です。記事タイトルと本文が投稿できる形にしてください。

[回答] Gemini

FastAPIを使って、個人でサクッと使えるマイクロブログを作成しましょう。 シンプルさを重視し、FastAPI(バックエンド) + Jinja2(HTMLテンプレート) + SQLite(データベース) の構成で構築します。


1. 準備:ディレクトリ構造

まず、プロジェクトフォルダを作成し、以下の構成でファイルを配置します。

microblog/
├── main.py          # FastAPIのメインロジック
├── database.py      # DB設定
├── models.py        # DBテーブル定義
├── templates/       # HTMLファイル
│   └── index.html
└── blog.db          # 実行時に自動生成されるDB

2. 実装:コードの記述

database.py (データベース接続)

SQLiteを使用するための設定です。

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

SQLALCHEMY_DATABASE_URL = "sqlite:///./blog.db"

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

models.py (データ構造)

記事のタイトルと本文を保存するテーブルを定義します。

from sqlalchemy import Column, Integer, String, Text, DateTime
from datetime import datetime
from database import Base

class Post(Base):
    __tablename__ = "posts"
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(100))
    content = Column(Text)
    created_at = Column(DateTime, default=datetime.now)

main.py (メインロジック)

投稿の表示と保存を行うAPIを記述します。

from fastapi import FastAPI, Request, Form, Depends, responses
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
import models
from database import SessionLocal, engine

# DBテーブルの作成
models.Base.metadata.create_all(bind=engine)

app = FastAPI()
templates = Jinja2Templates(directory="templates")

# DBセッションの取得
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/")
def read_root(request: Request, db: Session = Depends(get_db)):
    posts = db.query(models.Post).order_by(models.Post.created_at.desc()).all()
    return templates.TemplateResponse("index.html", {"request": request, "posts": posts})

@app.post("/post")
def create_post(title: str = Form(...), content: str = Form(...), db: Session = Depends(get_db)):
    new_post = models.Post(title=title, content=content)
    db.add(new_post)
    db.commit()
    return responses.RedirectResponse(url="/", status_code=303)

3. UI:templates/index.html

見た目を整えるために、軽量なCSSフレームワーク「Pico.css」を利用します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>My Microblog</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css">
</head>
<body class="container">
    <nav>
        <ul><li><strong>My Microblog</strong></li></ul>
    </nav>

    <main>
        <section>
            <form action="/post" method="post">
                <input type="text" name="title" placeholder="タイトル" required>
                <textarea name="content" placeholder="いまなにしてる?" required></textarea>
                <button type="submit">投稿する</button>
            </form>
        </section>

        <hr>

        <section>
            {% for post in posts %}
            <article>
                <header>
                    <strong>{{ post.title }}</strong> 
                    <small style="float: right;">{{ post.created_at.strftime('%Y-%m-%d %H:%M') }}</small>
                </header>
                {{ post.content }}
            </article>
            {% endfor %}
        </section>
    </main>
</body>
</html>

4. 実行方法

  1. ライブラリのインストール

    pip install fastapi uvicorn sqlalchemy jinja2 python-multipart
    

  2. サーバーの起動

    uvicorn main:app --reload
    

  3. ブラウザでアクセス http://127.0.0.1:8000 を開くと、投稿フォームと記事一覧が表示されます。


次のステップへの提案

このままでも十分使えますが、さらに便利にするために以下の機能を追加することも可能です。

  • 削除機能: 投稿を消せるようにするボタンの追加。
  • Markdown対応: 本文を装飾できるようにする。
  • パスワード保護: 自分以外が投稿できないように簡易的な認証をつける。

まずはこのコードを動かしてみて、削除機能なども追加してみたいですか?