はじめに#
「OKAZAKI Shogo のひとりアドベントカレンダー2024」の6日目です。 今回は、 Flask アプリと DB を繋げて、基本的な CRUD 処理が行えるようにします。 とりあえず、 SELECT 分が発行できたら良しというところまで。
準備#
DB はとりあえずは SQLite を使う。ローカルで開発する分にはこれで十分。 (参考:SQLite の基礎 #Database - Qiita)
以下の 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