Flask SQLAlchemyを使って、Sqliteへデータを書き込む方法【DB定義を別にすると落ち着く】

2021年11月30日

こんにちは、説也です。

この記事では、Flask SQLAlchemyを使って、Sqliteへデータを書き込む方法を紹介しています。

DBの定義の仕方は、いろいろあると思いますが
今回は、なるべくシンプルでわかりやすいものを紹介します。

少しでも、参考になれば幸いです。それではよろしくお願いします。

完成イメージ

「SQLAlchemy」を使用して、下記の通り処理を行っています。

① テキスト入力ボックスに入れた、テキストデータを「DB(Sqlite)」ファイルに書き込む

②「DB(Sqlite)」に格納されているテキストデータを取得し表示

ファイル構成

「createdb.py」の実行前

「createdb.py」の実行後

「createdb.py」を実行すると、「todo.db(sqliteファイル)」が作成されます。

事前準備

FlaskでSQLAlchemyを使用する場合は、下記のライブラリをインストールします。

公式ページ

pip install Flask-SQLAlchemy

DBにSqliteを使用する場合は、下記のライブラリをインストールします。

公式ページ

pip install pysqlite3

Python ソースコード 解説

Flask アプリケーションファイル

indexapp.py

#+----------------------------------------------------------------------------+
#+ (1) flask インポート
#+----------------------------------------------------------------------------+
from flask import Flask, render_template, request

#+----------------------------------------------------------------------------+
#+ (2) flask_sqlalchemy インポート
#+----------------------------------------------------------------------------+
# (pip3 install flask-sqlalchemy)
# (pip3 install pysqlite3)
from flask_sqlalchemy import SQLAlchemy

#+----------------------------------------------------------------------------+
#+ (3) Flaskクラスをappに定義
#+----------------------------------------------------------------------------+
app = Flask(__name__)

#+----------------------------------------------------------------------------+
#+ (4) appのconfig設定
#+----------------------------------------------------------------------------+
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
db = SQLAlchemy(app)

#+----------------------------------------------------------------------------+
#+ (5) ルートページの設定
#+----------------------------------------------------------------------------+
@app.route('/', methods=["GET","POST"])
def index():
	from models.todo_db import TodoTable

	if request.method == 'GET':
		Todolist = db.session.query(TodoTable).all()
		return render_template('index.html',Todolist=Todolist)
	else:
		title = request.form.get('TITLE')
		new_title = TodoTable(ToDoTitle=title)
		db.session.add(new_title)
		db.session.commit()

	Todolist = db.session.query(TodoTable).all()
	return render_template('index.html',Todolist=Todolist)

#+----------------------------------------------------------------------------+
#+ (6) app実行
#+----------------------------------------------------------------------------+
# app.pyが実行されたときにFlaskアプリケーション(app)を開始
if __name__ == '__main__':
	app.run(debug=True)

(1) flask インポート

flaskの機能で使用するモジュールをインポート

(2) flask_sqlalchemy インポート

flaskでsqlalchemyを使用するモジュールをインポート

(3) Flask クラスをインスタンス化

Flask(name) クラスをappとしてインスタンス化します。

(4) appのconfig設定

インスタンス化したappの設定をします。
① 使用するDBを定義
② DB定義を「db」という名前でインスタンス化します。

(5) ルートページの設定

① 必要なDBをインポート
② トップページがリクエストされたときの処理
 >DBに格納されている「TodoTable」の全てを変数に取得
 >index.htmlに渡して、ページを表示
③ トップページにデータがポストされたときの処理
 >入力フォームのデータを変数に取得
 >TodoTableに追加したいデータを編集
 >編集したデータをTodoTableに追加
 >追加したデータをDBにコミット

(6) app実行

app.pyが実行されたときにFlaskアプリケーション(app)を開始します。

DBのテーブル定義

todo_db.py

from indexapp import db

class TodoTable(db.Model):
	ToDoID = db.Column(db.Integer, nullable=False, primary_key=True)
	ToDoTitle = db.Column(db.String)

DBのテーブルと項目定義を行います。

class TodoTableテーブル名
ToDoID = db.Column項目名
db.Integer項目の型(数値)
db.String項目の型(文字)
nullable=False項目の属性(空白を許容しない)
primary_key=True項目の属性(主キー)

DBファイル作成プログラム

createdb.py

#+----------------------------------------------------------------------------+
#+ .db ファイル作成プログラム
#+----------------------------------------------------------------------------+
#==============================================================================
#= DB定義インポート
#==============================================================================
# modelsファイルのテーブル定義を全てインポート
import models.todo_db
# indexapp.py に定義されているdbをインポート
from indexapp import db

#+----------------------------------------------------------------------------+
#- DBファイルを作成
#+----------------------------------------------------------------------------+
db.create_all()

① 定義されているDBをすべてインポート
② DB(sqlite)ファイルを作成
※ DB定義を変更・削除した場合は、DBファイル削除してこのプログラムを手動で実行

html + jinja2 ソースコード 解説

トップページ

index.html

{% extends 'base.html'%}
{% block head %}
    <title>トップページ</title>
{% endblock %}

{% block body %} 
    <div class="w-80 p-4">
        <form action="/" method="POST">
            <input name="TITLE" class="form-control" type="text" required>
            <button class="btn btn-outline-secondary mt-3" type="submit">書き込み</button>
        </form>
        <ul class="list-group pt-4">
            {% for Todo in Todolist %}
                <li class="list-group-item">{{ Todo.ToDoTitle }}</li>
            {% endfor %}    
        </ul>
    </div>
{% endblock %}

① {% extends 'base.html’%} で基本テンプレートの「base.html」を継承
② フォームアクションで入力したデータをpythonファイルにポスト
③ pythonファイルから受け取ったデータを表示

テンプレート定義(ヘッダー部分)

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- stylesheet Bootstrap5 -->
      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
    <!-- stylesheet Bootstrap5 -->
    {% block head %}{% endblock %}
</head>
<body>
    <nav class="navbar navbar-light bg-light p-3">
        <div class="container-fluid">
          <a class="navbar-brand" href="/">SQLAlchemyを使って、Sqliteへデータを書き込む方法</a>
        </div>
      </nav>
    {% block body %}{% endblock %}
</body>
</html>

① スタイルシートを設定
② ヘッダーの設定

コード解説は、これで以上となります。

テーブル定義を別ファイルにすることで「indexapp.py」のコードが多少は整理されたのではないでしょうか。

長くなりましたが、ここまで見ていただき、ありがとうございました。
また、遊びに来ていただけるとうれしいです。ではまた。😀