メインコンテンツへスキップ

Flask から DB に接続する(とりあえず、SELECT まで)

·3 分
ひとりアドベントカレンダー2024 Python Flask Cgi
目次

はじめに
#

「OKAZAKI Shogo のひとりアドベントカレンダー2024」の6日目です。 今回は、 Flask アプリと DB を繋げて、基本的な CRUD 処理が行えるようにします。 とりあえず、 SELECT 分が発行できたら良しというところまで。

準備
#

DB はとりあえずは SQLite を使う。ローカルで開発する分にはこれで十分。 (参考:SQLite の基礎 #Database - Qiita

1$ mkdir db
2$ sqlite3 db/bshssa_member_sys.db

以下の SQL 分を発行してテーブルを作成。のちに使う SQLAlchemy の機能を使えばテーブル作成もできるらしいが、一旦自力で作成する。

 1CREATE TABLE ManagerUser (
 2	"user_id" INTEGER PARIMARY KEY AUTO_INCREMENT COMMENT '管理者ユーザーID',
 3	"user_name" TEXT COMMENT '管理者ユーザー名',
 4	"password" TEXT COMMENT 'パスワード',
 5	"servide" TEXT COMMENT '役務名',
 6	"logined_at" TEXT COMMENT 'ログイン日時'
 7);
 8
 9
10CREATE TABLE "File" (
11	"file_id"	INTEGER NOT NULL UNIQUE COMMENT 'ファイルID',
12	"file_name"	TEXT COMMENT 'ファイル名',
13	"display_name"	TEXT COMMENT 'ファイルの表示名',
14	"url"	TEXT COMMENT "ファイルの所在URL(Google Drive)",
15	"file_type"	TEXT COMMENT 'ファイル形式',
16	"size"	TEXT COMMENT 'ファイルサイズ',
17	"description"	TEXT COMMENT 'ファイルについての説明',
18	"tag"	TEXT COMMENT 'タグ',
19	"is_standard"	INTEGER COMMENT '定型文書か否か',
20	"created_at"	TEXT COMMENT '作成日時',
21	"created_by"	TEXT COMMENT '作成者の管理者ユーザーID',
22	"updated_at"	TEXT COMMENT '更新日時',
23	"updated_by"	TEXT COMMENT '更新者の管理者ユーザーID',
24	PRIMARY KEY("file_id" AUTOINCREMENT)
25)

あらかじめ、 File テーブルにレコードを登録しておく。

ORM である Flask-SQLAlchemy を入れる。

1poetry add Flask-SQLAlchemy

DB に接続するコードを書く
#

最終的には以下のようなディレクトリ構成になる。

 1.
 2|-- Makefile
 3|-- app
 4|   |-- __init__.py <-- 変更
 5|   |-- app.py
 6|   |-- index.cgi
 7|   |-- models
 8|   |   `-- file.py <-- 新規追加
 9|   |-- static
10|   |   `-- css
11|   |       `-- default.css
12|   |-- templates
13|   |   |-- files.html <-- 新規追加
14|   |   |-- index.html
15|   |   `-- layout.html
16|   `-- views
17|       |-- files.py <-- 新規追加
18|       `-- index.py
19|-- db
20|   `-- bshssa_member_sys.db <-- 新規追加
21|-- instance
22|   `-- config
23|       `-- dev.py  <-- 新規追加
24|-- poetry.lock
25`-- pyproject.toml

__init__,py
#

DB の設定を作成し、アプリに渡す処理を追加する。 DB 設定は config/dev.py に記述する。 File テーブルの一覧を表示するためのページへの Blueprint も登録しておく。

 1import os
 2from flask import Flask
 3from flask_sqlalchemy import SQLAlchemy
 4from instance.config.dev import BASE_DIR
 5
 6db = SQLAlchemy()
 7
 8
 9def create_app():
10    # appの設定
11    app = Flask(__name__, instance_relative_config=True)
12    # configファイルを読み込む
13    config_path = os.path.join("config", "dev.py")
14    app.config.from_pyfile(config_path)
15
16    # DB の設定
17    db.init_app(app)
18    from app import models
19
20    # Blueprint の登録
21    from app.views.index import index_bp
22    from app.views.files import files_bp
23
24    app.register_blueprint(index_bp)
25    app.register_blueprint(files_bp)
26
27    return app

instance/config/dev.py
#

DB のパスとか SQLAlchemy の設定を追加。

 1import os
 2
 3DEBUG = True
 4
 5# プロジェクトのルートディレクトリを基準にパスを解決
 6BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))
 7DATABASE_PATH = os.path.join(BASE_DIR, 'db', 'bshssa_member_sys.db')
 8
 9# SQLAlchemyの設定
10SQLALCHEMY_DATABASE_URI = f'sqlite:///{DATABASE_PATH}'
11SQLALCHEMY_TRACK_MODIFICATIONS = False

views/files.py
#

File テーブルにあるファイル一覧を出力する View を記述する。

 1from flask import Blueprint, render_template
 2from app.models.file import File
 3
 4files_bp = Blueprint("files", __name__, url_prefix="/files")
 5
 6
 7@files_bp.route("/", methods=["GET", "POST"])
 8def index():
 9    files = File.query.all()
10    return render_template("files.html", files=files)

models/file.py
#

File テーブルに対する Model を記述する。

 1from app import db
 2
 3
 4# File テーブル
 5class File(db.Model):
 6    __tablename__ = "File"
 7    file_id = db.Column(db.Integer, primary_key=True)
 8    file_name = db.Column(db.String(255))
 9    display_name = db.Column(db.String(255))
10    url = db.Column(db.String(255))
11    file_type = db.Column(db.String(255))
12    size = db.Column(db.String(255))
13    description = db.Column(db.String(255))
14    tag = db.Column(db.String(255))
15    is_standard = db.Column(db.Integer)
16    created_at = db.Column(db.String(255))
17    created_by = db.Column(db.String(255))
18    updated_at = db.Column(db.String(255))
19    updated_by = db.Column(db.String(255))

templates/files.html
#

最後に、 File 一覧を表示するページのテンプレートを用意する。

 1{% extends "layout.html" %}
 2
 3{% block content %}
 4<div>
 5    <h2>ファイル一覧</h2>
 6    <table>
 7        <thead>
 8            <tr>
 9            <th scope="col"><font>No</font></th>
10            <th scope="col"><font>登録日</font></th>
11            <th scope="col"><font>ファイル種類</font><br><font>サイズ</font></th>
12            <th scope="col"><font>タイトル</font><br><font size="2">説明</font></th>
13            </tr>
14        </thead>
15        <tbody>
16            {% for file in files %}
17            <tr>
18                <td>{{ file.file_id }}</td>
19                <td>{{ file.created_by }}</td>
20                <td>{{ file.file_type }}<br>{{ file.size }}</td>
21                <td><a href={{ file.url }}>{{ file.display_name }}</a><br>{{ file.description }}</td>
22            </tr>
23            {% endfor %}
24        </tbody>
25    </table>
26</div>
27{% endblock %}

簡単にだが、こんな感じのものが出てくれば OK

ページ表示

参考資料
#