【初心者向け】PythonでWebアプリを作ろう|Flask+SQLite+SQLAlchemy完全入門

Python

FlaskはPythonで手軽にWebアプリケーションを開発できる軽量フレームワークです。SQLiteはインストール不要で使える軽量なデータベースです。これらを組み合わせれば、簡単なデータベースを使ったアプリを素早く構築できます。

本記事では、Python初心者の方に向けて、

  • Flaskとは何か
  • SQLiteを使った基本的なデータ保存方法
  • SQLAlchemy(ORM)を使った実践的なDB連携

1本の記事で段階的に解説します。

この記事でできるようになること

  • FlaskでWebアプリを動かせる
  • SQLiteの基本的な役割が分かる
  • sqlite3でDB操作の仕組みを理解できる
  • SQLAlchemy(ORM)を使った安全なDB操作ができる
  • Webアプリ開発の全体像を掴める
スポンサーリンク
スポンサーリンク

Webアプリの全体像を理解しよう

まずは処理の流れをイメージします。

ブラウザ
   ↓
Flask(Python)
   ↓
データベース(SQLite)
   ↑
Flask
   ↑
ブラウザ
  • ブラウザ:ユーザーが操作
  • Flask:処理を担当
  • DB:データを保存

この構造を理解できれば、Webアプリは一気に分かりやすくなります。

SQLiteの概要

SQLiteはファイルベースの軽量なDBMS(データベース管理システム)で、設定不要ですぐに使えます。サーバーを必要としないため、アプリケーションと一緒にそのまま配布できます。小規模なアプリケーションや学習用途、プロトタイピングに最適です。

Flaskとの接続は、SQLAlchemyというORM(Object Relational Mapper)を使うことで、より簡単になります。

SQLiteとは?
  • ファイル1つで使える
  • サーバー不要
  • Python標準で扱える

SQLiteは上記の特徴を持つ超軽量データベースです。

SQLiteが向いている用途
  • 学習用アプリ
  • 小規模Webアプリ
  • Raspberry Pi などの組み込み用途

sqlite3でDB操作を理解する

sqlite3を用いたアプリ例になります。タスクアプリになります。

開発環境の準備

pip install flask

プロジェクト構成(sqlite3版)

flask_sqlite_app/
├── app.py
├── sample.db
└── templates/
    └── index.html

SQLite(sqlite3)を使ったFlaskアプリ

データベース作成(初回のみ)

import sqlite3

conn = sqlite3.connect("sample.db")
cur = conn.cursor()

cur.execute("""
CREATE TABLE IF NOT EXISTS memo (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    text TEXT
)
""")

conn.commit()
conn.close()

DB生成のためのスクリプト。一回だけ実行。

Flaskアプリ本体(sqlite3版 app.py)

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

app = Flask(__name__)

def get_db():
    return sqlite3.connect("sample.db")

@app.route("/", methods=["GET", "POST"])
def index():
    conn = get_db()
    cur = conn.cursor()

    if request.method == "POST":
        text = request.form["text"]
        cur.execute("INSERT INTO memo (text) VALUES (?)", (text,))
        conn.commit()

    cur.execute("SELECT * FROM memo")
    rows = cur.fetchall()
    conn.close()

    return render_template("index.html", rows=rows)

if __name__ == "__main__":
    app.run(debug=True)
ポイント解説
  • @app.route("/")
    → URLと処理を結びつける
  • request.form
    → HTMLフォームからの入力取得
  • INSERT / SELECT
    → DBへの保存・取得
  • render_template()
    → HTMLにデータを渡す

HTMLテンプレート(index.html)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Flask DB サンプル</title>
</head>
<body>
    <h1>メモアプリ</h1>

    <form method="post">
        <input type="text" name="text">
        <button type="submit">追加</button>
    </form>

    <ul>
        {% for row in rows %}
            <li>{{ row[1] }}</li>
        {% endfor %}
    </ul>
</body>
</html>
  • {% for %}:Pythonのfor文
  • {{ }}:Python変数の表示

結果

sqlite3版のポイント
  • SQL文を直接書く
  • DBの構造が見えて理解しやすい
  • 仕組みの学習に最適
sqlite3の注意点
  • SQL文が増えると読みにくくなる
  • SQLインジェクションのリスク
  • DBを変更すると修正量が多い

👉 次のステップとしてORMを使う理由がここにあります。

SQLAlchemy(ORM)を使った実践構成

SQLAlchemyとは?

SQLAlchemy は PythonでDBを扱うためのライブラリで、ORM(Object Relational Mapper) と呼ばれる仕組みです。

SQL文を直接書かずに、安全で読みやすいコードが書けるのが特徴です。

主な機能:

  • テーブル構造の定義
  • データの追加・取得・更新・削除(CRUD)
  • クエリのフィルタや並び替え
  • リレーション(外部キー)によるテーブル結合も可能

ORMとは?

  • Pythonのクラス = データベースのテーブル
  • Pythonのオブジェクト操作 = DB操作

SQLを書かずにDBを扱えるのが最大の特徴です。

SQLAlchemyを使うメリット

項目sqlite3SQLAlchemy
SQL記述必要不要
可読性低下しやすい高い
安全性自己管理高い
拡張性低い非常に高い

SQLAlchemyのインストール

Flask-SQLAlchemyという拡張ライブラリを使います。インストールは以下のコマンドで可能です:

pip install flask_sqlalchemy

プロジェクト構成(SQLAlchemy版)

flask_sqlalchemy_app/
├── app.py
├── app.db
└── templates/
    └── index.html

Flask+SQLAlchemy アプリ(完成版)

from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db = SQLAlchemy(app)

class Memo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.String(200), nullable=False)

@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        memo = Memo(text=request.form["text"])
        db.session.add(memo)
        db.session.commit()
        return redirect(url_for("index"))

    memos = Memo.query.all()
    return render_template("index.html", memos=memos)

if __name__ == "__main__":
    with app.app_context():
        db.create_all()
    app.run(debug=True)

簡単な解説になります。

以下のようにFlaskアプリの設定ファイルにデータベースの場所(URI)を指定し、SQLAlchemyを初期化することで接続が完了します。

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db = SQLAlchemy(app)

この設定により、同じディレクトリに「sample.db」という名前のSQLiteデータベースファイルが作成されます。

HTMLテンプレート

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Flask DB 入門</title>
</head>
<body>
    <h1>メモアプリ</h1>

    <form method="post">
        <input type="text" name="text" required>
        <button type="submit">追加</button>
    </form>

    <ul>
        {% for memo in memos %}
            <li>{{ memo.text }}</li>
        {% endfor %}
    </ul>
</body>
</html>

Flask × SQLAlchemyでCRUD操作を完全実装しよう

ここからは、これまで作成した メモアプリを拡張し、
CRUD(Create / Read / Update / Delete)操作をすべて実装します。

CRUDを理解すると、

  • Webアプリの基本構造が分かる
  • 実務レベルのアプリに一気に近づく
  • 他のフレームワークにも応用できる

という大きなメリットがあります。

CRUDとは?(初心者向け)

CRUDとは、データベース操作の基本4つをまとめた言葉です。

操作内容SQLAlchemyでの例
Create作成db.session.add()
Read読み取りquery.all()
Update更新値を書き換えて commit()
Delete削除db.session.delete()

ほぼすべてのWebアプリは、このCRUDの組み合わせでできています。

完成後のアプリ動作

  • メモを追加できる(Create)
  • メモ一覧を表示できる(Read)
  • メモを編集できる(Update)
  • メモを削除できる(Delete)

プロジェクト構成(CRUD対応)

flask_sqlalchemy_crud/
├── app.py
├── app.db
└── templates/
    ├── index.html
    └── edit.html

Flaskアプリ本体(CRUD完全版)

app.py(完成コード)

from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

# DB設定
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

db = SQLAlchemy(app)

# ===== モデル =====
class Memo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.String(200), nullable=False)

    def __repr__(self):
        return f"<Memo id={self.id}>"

# ===== 一覧 & 追加(Read / Create)=====
@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        text = request.form["text"]
        memo = Memo(text=text)
        db.session.add(memo)
        db.session.commit()
        return redirect(url_for("index"))

    memos = Memo.query.order_by(Memo.id.desc()).all()
    return render_template("index.html", memos=memos)

# ===== 編集(Update)=====
@app.route("/edit/<int:memo_id>", methods=["GET", "POST"])
def edit(memo_id):
    memo = Memo.query.get_or_404(memo_id)

    if request.method == "POST":
        memo.text = request.form["text"]
        db.session.commit()
        return redirect(url_for("index"))

    return render_template("edit.html", memo=memo)

# ===== 削除(Delete)=====
@app.route("/delete/<int:memo_id>", methods=["POST"])
def delete(memo_id):
    memo = Memo.query.get_or_404(memo_id)
    db.session.delete(memo)
    db.session.commit()
    return redirect(url_for("index"))

if __name__ == "__main__":
    with app.app_context():
        db.create_all()
    app.run(debug=True)

コード解説(初心者向け)

Create(追加)
memo = Memo(text=text)
db.session.add(memo)
db.session.commit()
  • Pythonオブジェクトを作成
  • DBに登録
  • commit() で確定
Read(一覧取得)
memos = Memo.query.order_by(Memo.id.desc()).all()
  • SELECT * FROM memo
  • 新しいデータを上に表示
Update(更新)
memo.text = request.form["text"]
db.session.commit()
  • データを取得
  • 値を書き換え
  • commit() で反映
Delete(削除)
db.session.delete(memo)
db.session.commit()
  • 削除対象を指定
  • DBから完全に削除

HTMLテンプレート①(一覧画面)

templates/index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Flask CRUD メモアプリ</title>
</head>
<body>
    <h1>メモアプリ(CRUD対応)</h1>

    <form method="post">
        <input type="text" name="text" required>
        <button type="submit">追加</button>
    </form>

    <ul>
        {% for memo in memos %}
            <li>
                {{ memo.text }}
                <a href="{{ url_for('edit', memo_id=memo.id) }}">編集</a>
                <form action="{{ url_for('delete', memo_id=memo.id) }}"
                      method="post"
                      style="display:inline;">
                    <button type="submit">削除</button>
                </form>
            </li>
        {% endfor %}
    </ul>
</body>
</html>

HTMLテンプレート②(編集画面)

templates/edit.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>メモ編集</title>
</head>
<body>
    <h1>メモ編集</h1>

    <form method="post">
        <input type="text" name="text" value="{{ memo.text }}" required>
        <button type="submit">更新</button>
    </form>

    <p><a href="{{ url_for('index') }}">一覧に戻る</a></p>
</body>
</html>

結果

よくあるエラーと対処法

エラー1: RuntimeError: Working outside of application context.

原因: db.create_all() などをアプリケーションコンテキスト外で実行した。

対処法:

with app.app_context():
    db.create_all()

エラー2: IntegrityError: UNIQUE constraint failed

原因: 一意性制約のあるカラム(例: email)に重複したデータを登録しようとした。

対処法: 登録前にデータの存在を確認するか、例外処理で対応する。

おわりに

SQLiteは小規模のアプリケーションに最適で、Flaskとの組み合わせは実用性が高いです。

次のステップでは、ユーザー登録やログイン機能の実装に進んでみましょう!

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