前回は家計簿アプリのデータ削除を作成しました。今回は、ここまでのアプリをデータベースを使って実装したいと思います。
アプリイメージ
基本的な操作やイメージは特に変わりません。内部の処理をDBを使った場合に書き換えているだけです。
今回はsqlite3を使います。
コード全体
%%writefile app.py
import streamlit as st
import sqlite3
import pandas as pd
# SQLite3データベースの初期化
conn = sqlite3.connect('家計簿データ.db')
cursor = conn.cursor()
# テーブルが存在しない場合は作成
cursor.execute('''
CREATE TABLE IF NOT EXISTS expenses (
id INTEGER PRIMARY KEY,
date DATE,
item TEXT,
amount INTEGER
)
''')
conn.commit()
# Streamlitアプリケーションのタイトル
st.title("家計簿アプリ")
# 収支データの入力フォーム
st.header("収支の記録")
date = st.date_input("日付", pd.to_datetime("today"))
item = st.text_input("項目")
amount = st.number_input("金額", value=0, step=1) # 金額を整数として入力
# データをデータベースに追加
if st.button("記録する"):
cursor.execute('INSERT INTO expenses (date, item, amount) VALUES (?, ?, ?)', (date, item, amount))
conn.commit()
# データフレームの表示
st.header("収支データ")
# 削除モードのトグルボタン
delete_mode = st.checkbox("削除モード")
if delete_mode:
selected_rows = [] # 選択された行のリストを初期化
st.write("収支データを選択してください:")
for row in cursor.execute('SELECT * FROM expenses'):
selected = st.checkbox(label="", value=False, key=row[0])
data_row = pd.DataFrame([list(row)], columns=["ID", "日付", "項目", "金額"])
st.write(data_row) # データをDataFrameで表示
if selected:
selected_rows.append(row[0]) # 選択された行のIDを記録
if st.button("選択した行を削除") and selected_rows:
for row_id in selected_rows:
cursor.execute('DELETE FROM expenses WHERE id = ?', (row_id,))
conn.commit()
st.success("選択した行を削除しました.")
st.experimental_rerun() # データを削除後に再表示
else:
# 通常モードの一覧表示
expenses_df = pd.read_sql('SELECT * FROM expenses', conn)
st.write(expenses_df)
# 統計情報の表示
st.header("統計情報")
total_expenses = cursor.execute('SELECT SUM(amount) FROM expenses WHERE amount < 0').fetchone()[0]
total_income = cursor.execute('SELECT SUM(amount) FROM expenses WHERE amount > 0').fetchone()[0]
st.write("合計支出:", total_expenses)
st.write("合計収入:", total_income)
# アプリのクリアボタン
if st.button("データをクリア"):
cursor.execute('DELETE FROM expenses')
conn.commit()
st.success("データがクリアされました.")
# SQLite3データベースをクローズ
conn.close()
コード解説
# SQLite3データベースの初期化
conn = sqlite3.connect('家計簿データ.db')
cursor = conn.cursor()
# テーブルが存在しない場合は作成
cursor.execute('''
CREATE TABLE IF NOT EXISTS expenses (
id INTEGER PRIMARY KEY,
date DATE,
item TEXT,
amount INTEGER
)
''')
conn.commit()
ここでは、SQLite3データベースを初期化しています。データベースファイル 家計簿データ.db
が存在しない場合、新しいデータベースを作成し、expenses
というテーブルを作成しています。このテーブルには日付、項目、金額の情報が格納されます。
# データをデータベースに追加
if st.button("記録する"):
cursor.execute('INSERT INTO expenses (date, item, amount) VALUES (?, ?, ?)', (date, item, amount))
conn.commit()
ここでは、ユーザーが入力したデータをデータベースに追加します。ユーザーが「記録する」ボタンをクリックすると、日付、項目、金額がデータベースの expenses
テーブルに追加されます。データベースへの変更は commit()
メソッドを呼び出すことで確定されます。
if delete_mode:
selected_rows = [] # 選択された行のリストを初期化
st.write("収支データを選択してください:")
for row in cursor.execute('SELECT * FROM expenses'):
selected = st.checkbox(label="", value=False, key=row[0])
data_row = pd.DataFrame([list(row)], columns=["ID", "日付", "項目", "金額"])
st.write(data_row) # データをDataFrameで表示
if selected:
selected_rows.append(row[0]) # 選択された行のIDを記録
ここでは、削除モードが有効の場合、収支データを1行ずつ表示します。各行にはチェックボックスが表示され、ユーザーは行を選択できます。選択された行はリストに追加されます。
データは execute
メソッドを使用してデータベースから取得され、DataFrameに変換して表示されます。
if st.button("選択した行を削除") and selected_rows:
for row_id in selected_rows:
cursor.execute('DELETE FROM expenses WHERE id = ?', (row_id,))
conn.commit()
st.success("選択した行を削除しました.")
st.experimental_rerun() # データを削除後に再表示
この部分では、ユーザーが選択した行を削除するためのボタンを作成しています。ユーザーが「選択した行を削除」ボタンをクリックすると、選択された行がデータベースから削除されます。また、削除後にデータを再表示するために st.experimental_rerun()
を使用しています。
else:
# 通常モードの一覧表示
expenses_df = pd.read_sql('SELECT * FROM expenses', conn)
st.write(expenses_df)
ここでは、削除モードが無効の場合、通常モードの一覧表示が行われます。データベースから収支データを取得し、PandasのDataFrameに変換して、その内容を表示します。
# 統計情報の表示
st.header("統計情報")
total_expenses = cursor.execute('SELECT SUM(amount) FROM expenses WHERE amount < 0').fetchone()[0]
total_income = cursor.execute('SELECT SUM(amount) FROM expenses WHERE amount > 0').fetchone()[0]
st.write("合計支出:", total_expenses)
st.write("合計収入:", total_income)
この部分では、収支データの統計情報を表示しています。具体的には、支出の合計金額と収入の合計金額を計算し、それらを表示しています。データベースから支出(amount < 0)と収入(amount > 0)をフィルタリングして合計を取得しています。
# アプリのクリアボタン
if st.button("データをクリア"):
cursor.execute('DELETE FROM expenses')
conn.commit()
st.success("データがクリアされました.")
最後に、データをクリアするためのボタンがあります。ユーザーが「データをクリア」ボタンをクリックすると、データベース内のすべてのデータが削除され、画面に成功メッセージが表示されます。
# SQLite3データベースをクローズ
conn.close()
最後に、データベース接続をクローズしています。