
目標
- SQLiteについて概要が理解できる。
- Flaskでデータベース利用の為のセットアップ(Flask-SQLAlchemyの導入)が行える。
- Flaskを利用したデータベースの利用方法について理解できる。
Flaskでデータベースを利用する方法
SQLiteの概要(再掲載)
SQLiteは、非常に軽量で、サーバーを必要とせず、ファイルシステム上にデータベースを保存する組み込み型のデータベース管理システムです(サーバーとして動作せず、アプリケーションに直接組み込まれます。)。SQLiteには以下の特徴があります。
- ファイルベース:SQLiteのデータは、単一のファイル(例えば、database.db)として保存されます。これにより、データベースを管理するためのサーバーを立てる必要がありません。
- 軽量:小さなデータベースや開発段階でのテスト用のデータベースとして非常に適しています。サーバー型のデータベース(MySQLやPostgreSQL)に比べて、軽量で設定が簡単です。
- ACIDトランザクション:SQLiteは、データの整合性を保つためのACID(Atomicity, Consistency, Isolation, Durability)トランザクションをサポートしています。
SQLiteを、Flaskと組み合わせることで、手軽にデータベースを利用したWebアプリケーションを開発できます。そのため、プロトタイピングで非常に便利です。
FlaskとSQLiteの統合(再掲載)
FlaskアプリケーションとSQLiteの統合は、とても簡単で、Flask-SQLAlchemyというライブラリをインストールするだけでセットアップできます。
Flask-SQLAlchemyのインストール(再掲載)
Flask-SQLAlchemyをインストールします。
C:\Users\user\Desktop\FlaskProj>.venv\Scripts\activate
# 仮想環境が有効化されます。
(venv) C:\Users\user\Desktop\FlaskProj>pip install Flask-SQLAlchemy

FlaskアプリケーションでFlask-SQLAlchemyを使用するためにインポートします。
from flask_sqlalchemy import SQLAlchemy
Flask-SQLAlchemyライブラリの利用と解説
前回の記事では、models.pyというファイルをminiappディレクトリに作成して、商品モデルのクラスを準備し、app.pyからインポートしました。
FlaskでSQLAlchemyを使ってデータベースモデルを管理する際には、今回のような商品モデルをクラスの別ファイルにするのが一般的で、推奨されています。こうすることで、コードが整理され、アプリケーションが大きくなっても管理がしやすくなります。
Flaskアプリケーションを構築する際に、通常、モデル、ビュー、コントローラー(ルート)を分けて、よりモジュール化された構成にします。これにより、アプリケーションが拡張されても、コードが整理されていることもあり、可読性やメンテナンス性が向上します。(再掲載)
models.pyファイルの作成
前回の記事でmodels.pyファイルをminiappディレクトリに作成しました。

作成した models.pyファイル に次のプログラムを入力しました。
from flask_sqlalchemy import SQLAlchemy
# SQLAlchemyインスタンスを共通で使えるように
db = SQLAlchemy()
# 商品モデル(テーブル)の定義
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
price = db.Column(db.Integer, nullable=False)
def __repr__(self):
return f"<Product {self.id} - {self.name} - {self.price}>"
商品モデルクラスの解説
Flask-SQLAlchemyのインポート
from flask_sqlalchemy import SQLAlchemy
この行は、Flask-SQLAlchemyライブラリからSQLAlchemyクラスをインポートしています。Flask-SQLAlchemyは、FlaskアプリケーションにSQLAlchemy ORM(オブジェクトリレーショナルマッピング)を統合するためのライブラリです。このクラスは、データベースとの接続や操作を管理するためのものです。
SQLAlchemyインスタンスの作成
db = SQLAlchemy()
ここでは、SQLAlchemyのインスタンスを作成して、dbという変数に格納しています。このdbインスタンスは、Flaskアプリケーションでデータベースとの接続やモデルの定義、クエリの実行など、SQLAlchemyの操作に使用されます。
通常、Flaskアプリケーションでは、アプリケーションの設定後にこのdbインスタンスをFlaskアプリケーションにバインドします。
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db' # SQLiteのデータベースのURI
db.init_app(app)
商品モデルの定義
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
price = db.Column(db.Integer, nullable=False)
def __repr__(self):
return f"<Product {self.id} - {self.name} - {self.price}>"
この部分は、データベースのテーブルを表すクラス(モデル)を定義しています。このクラスはSQLAlchemy ORMの特徴で、テーブルの各列をPythonのクラス属性として表現します。
db.Modelの継承
Productクラスは、db.Modelを継承しています。これにより、ProductクラスはSQLAlchemyのモデルとして機能し、データベースのテーブルと関連づけられます。
idカラム
id = db.Column(db.Integer, primary_key=True)
idはデータベースのINTEGER型のカラムで、商品ごとの一意な識別子(主キー)として機能します。primary_key=Trueによって、このカラムが主キーであることが示されます。主キーは各レコードを一意に識別するため、重複しない値である必要があります。
nameカラム
name = db.Column(db.String(100), nullable=False)
nameはデータベースのSTRING型のカラムで、商品の名前を格納します。
nullable=Falseは、このカラムにNULLが許可されないことを意味します。つまり、商品名は必須項目であり、空の値は保存できません。
priceカラム
name = db.Column(db.String(100), nullable=False)
price = db.Column(db.Integer, nullable=False)
priceは商品の価格を格納するINTEGER型のカラムです。
nullable=Falseは、価格も必須項目であることを意味します。
__repr__メソッド
def __repr__(self):
return f"<Product {self.id} - {self.name} - {self.price}>"
__repr__は、Pythonのオブジェクトの文字列表現を定義する特殊メソッドです。このメソッドは、Productオブジェクトが文字列として表示されるときのフォーマットを指定します。
この例では、Productオブジェクトが文字列に変換されるとき、<Product id – name – price>という形式で出力されます。これにより、オブジェクトの情報が見やすく表示されます。
このコードの全体的な目的
このプログラムは、商品情報(商品ID、名前、価格)を保存するためのデータベースモデルを定義しています。Product
クラスは、商品のデータをデータベースのテーブルとして管理し、SQLAlchemy ORMを使ってデータベース操作を行えるようにします。
商品の追加
new_product = Product(name="Apple", price=100)
db.session.add(new_product)
db.session.commit()
商品のクエリ(取得)
product = Product.query.get(1) # id=1の商品の取得
商品の更新
product.price = 200
db.session.commit()
app.pyの編集内容
次のプログラムは、前回の記事で行ったapp.pyの編集後の内容です。
from flask import Flask, redirect, render_template, url_for
from apps.miniapp.forms import AddProductForm
from apps.miniapp.models import Product, db # models.pyからインポート
# アプリケーションの初期化
app = Flask(__name__)
app.secret_key = "your_secret_key"
# SQLiteの設定
app.config["SQLALCHEMY_DATABASE_URI"] = (
"sqlite:///products.db" # SQLiteデータベースファイル
)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False # 不要な変更追跡を無効化
# SQLAlchemyのインスタンスを初期化
db.init_app(app)
# アプリケーションコンテキスト内でテーブル作成
with app.app_context():
db.create_all()
# ルート: トップページ
@app.route("/")
def index():
return "Top page"
# ルート: 商品一覧ページ
@app.route("/products")
def product_list():
products = Product.query.all() # SQLiteから商品データを取得
return render_template("products.html", products=products)
# ルート: 商品追加ページ
@app.route("/add_product", methods=["GET", "POST"])
def add_product():
form = AddProductForm()
if form.validate_on_submit():
# フォームが送信され、バリデーションが成功した場合
name = form.product_name.data
price = form.product_price.data
# 新しい商品をデータベースに追加
new_product = Product(name=name, price=price)
db.session.add(new_product) # セッションに追加
db.session.commit() # データベースにコミット
# 商品一覧ページにリダイレクト
return redirect(url_for("product_list"))
return render_template("add_product.html", form=form)
# ルート: 商品管理ページ
@app.route("/manage_products")
def manage_products():
return render_template("manage_products.html")
if __name__ == "__main__":
app.run(debug=True)
修正内容の解説
Productモデルの作成
from apps.miniapp.models import Product, db # models.pyからインポート
models.pyからProductクラスとdbインスタンスをインポートしています。
Productは、データベースのテーブル(商品データ)を表すORMクラスで、db.Modelを継承しており、id, name, priceのカラムを持っています。dbはSQLAlchemyのインスタンスで、データベースへの接続や操作を管理します。
SQLAlchemyの設定
# SQLiteの設定
app.config["SQLALCHEMY_DATABASE_URI"] = (
"sqlite:///products.db" # SQLiteデータベースファイル
)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False # 不要な変更追跡を無効化
- app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘sqlite:///products.db’: SQLiteデータベースをproducts.dbというファイルに保存します。
- app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False: 不要な変更追跡を無効にして、アプリケーションのパフォーマンスを向上させます。
SQLAlchemyのインスタンスを初期化
db.init_app(app)
db.init_app(app)で、FlaskアプリケーションにSQLAlchemyを初期化しています。
アプリケーションコンテキスト内でデータベーステーブルの作成
with app.app_context():
db.create_all()
このコードは、Flaskアプリケーションのコンテキスト内でデータベースのテーブルを作成します。db.create_all()は、アプリケーション内で定義されたすべてのモデルに基づいてテーブルを自動的に作成します。これにより、最初に実行した際にデータベースに必要なテーブル(例えば、Productテーブル)が作成されます。
データベースの操作(商品一覧の取得)
# ルート: 商品一覧ページ
@app.route("/products")
def product_list():
products = Product.query.all() # SQLiteから商品データを取得
return render_template("products.html", products=products)
Product.query.all()は、Productテーブルからすべてのレコード(商品)を取得するクエリです。これにより、データベースに保存されている商品データが全て取得され、productsとしてテンプレートに渡されます。
render_template(“products.html”, products=products)で、商品データをproducts.htmlテンプレートに渡して表示します。
データベースの操作(商品の追加)
# ルート: 商品追加ページ
@app.route("/add_product", methods=["GET", "POST"])
def add_product():
form = AddProductForm()
if form.validate_on_submit():
# フォームが送信され、バリデーションが成功した場合
name = form.product_name.data
price = form.product_price.data
# 新しい商品をデータベースに追加
new_product = Product(name=name, price=price)
db.session.add(new_product) # セッションに追加
db.session.commit() # データベースにコミット
# 商品一覧ページにリダイレクト
return redirect(url_for("product_list"))
return render_template("add_product.html", form=form)
この部分は商品をデータベースに追加するための機能です。AddProductFormは、商品名と価格を入力するフォームです。フォームが送信されてバリデーションが成功すると、フォームからデータ(商品名と価格)を取得し、それを使って新しいProductインスタンスを作成します。
テンプレートの修正はなし
products.html と add_product.html のテンプレートをそのまま利用することができます。products.htmlでは、productsというリストをループして商品の一覧を表示する形にします。
add_product.htmlの商品追加フォームの内容。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品追加</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<h1>商品追加ページ</h1>
<ul>
<li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧に戻る</a></li>
<li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
</ul>
<h1>商品追加フォーム</h1>
<form method="POST" action="{{ url_for('add_product') }}">
{{ form.hidden_tag() }} <!-- CSRFトークンを含めるため -->
<label for="product_name">商品名</label>
{{ form.product_name() }} <!-- 商品名入力フィールド -->
{% if form.product_name.errors %}
<ul>
{% for error in form.product_name.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="product_price">価格</label>
{{ form.product_price() }} <!-- 価格入力フィールド -->
{% if form.product_price.errors %}
<ul>
{% for error in form.product_price.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<input type="submit" value="商品を追加する">
</form>
</body>
</html>
ブラウザで http://127.0.0.1:5000/manage_productsにアクセスします。
商品管理ページが表示されます。

商品一覧ボタンを押下すると、商品一覧ページが表示されます。始めて開いた状態では商品一覧には何もありません。

商品を追加するボタンを押下すると、商品追加ページが表示されます。

商品名と価格を入力して「商品を追加する」ボタンを押下します。

http://127.0.0.1:5000/products にリダイレクトされます。

商品が追加されています。このデータベースはVisual Studio Codeのエクスプローラーで確認ができます。今回の場合は、 instanceディレクトリの中に、products.db というファイルで生成されているのが確認できます。

続けて、商品追加ページで商品名を空で送信ボタンを押下します。

商品の追加はされず、商品追加ページが再表示されます。
今回は以上になります。

ブックマークのすすめ
「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

