【Webアプリ応用編 #2】FlaskとSQLiteを連携!Webフォームで掲示板に投稿しよう

ALL

こんにちは、Tech Samuraiです!
前回の記事「【Webアプリ応用編 #1】Python標準ライブラリだけでOK!SQLiteデータベース入門」では、PythonとSQLiteを使って、プログラムのデータをファイルに保存・読み込みする方法を学びましたね。

データベースという強力な「記憶装置」の使い方はマスターしました。今回の冒険の目的は、この記憶装置を、私たちが作った**FlaskのWebアプリケーションと接続する**ことです。

具体的には、ユーザーがWebページのフォームに入力した名前とメッセージを受け取り、それをSQLiteデータベースに永続的に保存する**「一言掲示板」**のバックエンドを構築します。この記事を終える頃には、あなたのWebアプリは、ユーザーとの対話を「記憶」し、積み重ねていくことができるようになります!


ステップ1:データベースの準備

まずは、前回の知識を元に、掲示板の投稿を保存するためのデータベースファイルとテーブルを準備します。`init_db.py`という名前で、以下のスクリプトをプロジェクトフォルダに作成し、一度だけ実行してください。

# init_db.py
import sqlite3

conn = sqlite3.connect('guestbook.db')
cursor = conn.cursor()

# postsテーブルが既に存在する場合は削除してから再作成する
# (開発中はリセットが簡単なこの方法が便利)
cursor.execute("DROP TABLE IF EXISTS posts")
cursor.execute("""
CREATE TABLE posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    message TEXT NOT NULL,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);
""")

conn.commit()
conn.close()

print("データベースを初期化しました。guestbook.db が作成されました。")

ターミナルでpython3 init_db.pyを実行し、`guestbook.db`ファイルが作成されれば準備完了です。


ステップ2:入力フォームの作成 (`templates/index.html`)

次に、ユーザーが名前とメッセージを入力するためのHTMLフォームを用意します。前回のWebアプリ入門で作った`templates/index.html`を、以下のように書き換えましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>一言掲示板</title>
    <style>
        /* ページ全体のスタイル */
        body { 
            font-family: "Helvetica Neue", Arial, "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif;
            line-height: 1.6;
            color: #333;
            background-color: #f4f4f4;
            margin: 0;
            padding: 20px;
        }
        /* コンテンツを中央に配置するラッパー */
        .container {
            max-width: 700px;
            margin: 0 auto;
            background-color: #fff;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        /* 見出しのスタイル */
        h1, h2 { 
            color: #333; 
            border-bottom: 2px solid #007BFF; 
            padding-bottom: 10px;
        }
        /* フォーム全体のスタイル */
        form { 
            background-color: #f8f9fa; 
            padding: 20px; 
            border-radius: 5px; 
            border: 1px solid #ddd;
            margin-bottom: 30px;
        }
        /* テキスト入力欄とテキストエリアのスタイル */
        input[type="text"], textarea { 
            width: 95%; 
            padding: 10px; 
            border: 1px solid #ccc;
            border-radius: 4px;
            margin-top: 5px;
        }
        /* 送信ボタンのスタイル */
        input[type="submit"] { 
            background-color: #007BFF; 
            color: white; 
            padding: 10px 20px; 
            border: none; 
            border-radius: 4px; 
            cursor: pointer;
            font-size: 16px;
        }
        /* 送信ボタンにマウスを乗せた時のスタイル */
        input[type="submit"]:hover { 
            background-color: #0056b3; 
        }
        /* 投稿一件ずつのスタイル */
        .post { 
            border: 1px solid #eee; 
            padding: 15px; 
            margin-bottom: 15px; 
            border-radius: 5px; 
            background-color: #fff;
        }
        /* 投稿情報のスタイル(名前や日時) */
        .post-info { 
            color: #777; 
            font-size: 0.9em; 
        }
        .post-message {
            margin-top: 10px;
        }
    </style>
</head>
<body>

    <div class="container">
        <h1>一言掲示板へようこそ!</h1>
        
        <form method="post" action="">
            <p>
                <label for="name">名前:</label><br>
                <input type="text" name="name" id="name" required>
            </p>
            <p>
                <label for="message">メッセージ:</label><br>
                <textarea name="message" id="message" rows="5" required></textarea>
            </p>
            <p>
                <input type="submit" value="投稿する">
            </p>
        </form>

        <hr>
        
        <h2>投稿一覧</h2>

        <div class="post">
            <p class="post-info"><strong>田中</strong> <span>投稿日時: 2025-09-06 14:30:15</span></p>
            <p class="post-message">こんにちは!初めての投稿です。</p>
        </div>

        <div class="post">
            <p class="post-info"><strong>鈴木</strong> <span>投稿日時: 2025-09-06 12:10:48</span></p>
            <p class="post-message">いい天気ですね。<br>掲示板のデザイン、見やすいです。</p>
        </div>
        
        <div class="post">
            <p class="post-info"><strong>佐藤</strong> <span>投稿日時: 2025-09-05 21:55:01</span></p>
            <p class="post-message">テスト投稿です。</p>
        </div>
        
        </div>

</body>
</html>

method="post"で、入力されたデータをサーバーに送信するように設定しています。


ステップ3:Flaskとデータベースの連携 (`app.py`)

いよいよ核心部分です。Flaskアプリケーション (`app.py`) を修正し、フォームから`POST`リクエストが来たときに、そのデータをSQLiteデータベースに保存するロジックを追加します。

import sqlite3
from flask import Flask, render_template, request, redirect, url_for

app = Flask(__name__)
DATABASE = 'guestbook.db'

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # --- フォームが送信されたときの処理 ---

        # 1. フォームからデータを取得
        name = request.form['name']
        message = request.form['message']

        # 2. 簡単なバリデーション
        if name and message:
            # 3. データベースに接続
            conn = sqlite3.connect(DATABASE)
            cursor = conn.cursor()

            # 4. データをINSERT
            sql = "INSERT INTO posts (name, message) VALUES (?, ?)"
            cursor.execute(sql, (name, message))

            conn.commit()
            conn.close()

        # 5. 投稿後は、トップページにリダイレクトする
        return redirect(url_for('index'))

    # --- 初めてページにアクセスしたときの処理 (GET) ---
    # (今回はまだ投稿を表示しないので、シンプルにテンプレートを返すだけ)
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True)

コードのポイント解説

  • if request.method == 'POST':
    Webページが初めて表示されるとき(`GET`)と、フォームの「投稿する」ボタンが押されたとき(`POST`)で処理を分けています。
  • request.form['name']
    `POST`リクエストで送られてきたフォームデータにアクセスする方法です。HTMLの`name`属性と対応しています。
  • redirect(url_for('index'))
    これはWebアプリ開発の重要なお作法です。フォームを送信した後、ユーザーをトップページに**リダイレクト(再案内)**しています。これにより、ユーザーがブラウザの更新ボタンを押しても、同じデータが二重に投稿されてしまうのを防ぎます。

動作確認

  1. ターミナルでpython3 app.pyを実行して、Flaskサーバーを起動します。
  2. ブラウザでhttp://127.0.0.1:5000にアクセスし、フォームに名前とメッセージを入力して「投稿する」ボタンを押します。
  3. ページがリロードされ、入力欄が空になれば成功です!(まだ投稿内容は表示されません)
  4. 本当に保存されたか確認するには、前回の記事で使った読み込み用のスクリプトを別のターミナルで実行するか、sqlite3 guestbook.dbコマンドでデータベースの中身を覗いてみましょう。

まとめと次回予告

今回は、Webアプリ応用編の第2回として、Webフォームとデータベースを接続し、ユーザーの入力を永続的に保存する仕組みを構築しました。

  • Webフォームからの**POSTリクエスト**をFlaskで処理する方法。
  • 受け取ったデータを**SQLiteデータベースに`INSERT`**する流れ。
  • 二重投稿を防ぐための**Post/Redirect/Get (PRG)** パターン。

私たちのアプリは、ついにユーザーとの対話を「記憶」し、積み重ねていく能力を手に入れました。あとは、その記憶をユーザーに見せてあげるだけです。

次回、いよいよシリーズ完結編では、データベースに保存された全ての投稿を**`SELECT`**文で読み出し、掲示板の投稿一覧として**Webページに動的に表示**します。本当の意味で「生きている」Webアプリケーションを完成させましょう!お楽しみに!

コメント

タイトルとURLをコピーしました