#******************************************************************************#
# ファイル名:main.py
# バージョン:p0001 Ver1.0
# 機能:
# 作成日:2024/11/25
# 更新日:2024/12/31 W010
#*******************************************************************************#
import os
import json
from ulid import ULID #--- 追加11 # ULIDクラスをインポート
from flask import Flask, render_template, request, redirect, Response, url_for # --- 追加10 url_for
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required #--- 追加 9 事前に $ pip install flask-login でインストール # 仮想環境の場合はpipenv
from flask_sqlalchemy import SQLAlchemy #--- 追加 9 事前に $ pip install flask_sqlalchemy でインストール # 仮想環境の場合はpipenv
from werkzeug.security import generate_password_hash, check_password_hash #--- 追加 9 パスワードのハッシュ化
from KDpay import PayManager #--- 追加 7-1
file_path = 'KDjson.json'
app = Flask(__name__)
# ------------------------------------------------------------------------------ #
# ユーザーDBの作成 #--- 追加 9
# ------------------------------------------------------------------------------ #
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///user_flask.db'
app.config['SECRET_KEY'] = os.urandom(24) # パスワード設定 #--- 追加 9
db = SQLAlchemy(app) # DB設定 #--- 追加 9
login_manager = LoginManager()
login_manager.init_app(app)
# login_manager.login_view = "users.login" # login_viewのrouteを設定
# ユーザーDBの作成 #--- 追加 9
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(255), nullable=False, unique=True)
password = db.Column(db.String(255))
# 認証ユーザーの呼び出し方を定義する #--- 追加 9
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# ------------------------------------------------------------------------------ #
#
# ------------------------------------------------------------------------------ #
@app.route('/')
def hello_show():
return 'Hello World!'
# ------------------------------------------------------------------------------ #
#
# ------------------------------------------------------------------------------ #
@app.route('/index')
def index():
insert_dict = {
'insert_1': 'insert_1部分です。',
'insert_2': 'insert_2部分です。',
}
return render_template('index.html', title='Webアプリテスト', insert_dict=insert_dict)
# ------------------------------------------------------------------------------ #
# ユーザー管理 #--- 追加 9
# ------------------------------------------------------------------------------ #
'''''''''''''''''
signup
'''''''''''''''''
@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == "POST":
username = request.form.get('username')
password = request.form.get('password')
# Userのインスタンスを作成
user = User(username=username, password=password)
# hashを使用する場合(def login():も修正必要箇所あり)
# user = User(username=username, password=generate_password_hash(password, method='pbkdf2:sha256'))
db.session.add(user)
db.session.commit()
return redirect('login')
else:
return render_template('signup.html')
'''''''''''''''''
login
'''''''''''''''''
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == "POST":
username = request.form.get('username')
password = request.form.get('password')
# Userテーブルからusernameに一致するユーザを取得
user = User.query.filter_by(username=username).first()
if user.password == password:
# hashを使用する場合(def signup()も修正必要箇所あり)
# if check_password_hash(user.password, password):
login_user(user)
# return redirect('/kakeibo') # 家計簿へ'''修正前''''''
return redirect(url_for('kd', user_name = user.username)) # 家計簿へ #--- 修正10
else:
# 入力したユーザー名のパスワードが間違っている場合
# return "パスワードが間違っています。
"
return Response(status=404, response="ページが見つかりません。")
else:
return render_template('login.html')
'''''''''''''''''
logout
'''''''''''''''''
@app.route('/logout')
@login_required # ログインしているユーザーのみに制限 #--- 追加 9
def logout():
logout_user()
return redirect('login')
# ------------------------------------------------------------------------------ #
# 家計簿
# ------------------------------------------------------------------------------ #
# @app.route('/kakeibo', methods=['GET', 'POST']) #--- 修正6-1 '''修正前'''
@app.route('/kakeibo/', methods=['GET', 'POST']) #--- 修正10
@login_required # ログインしているユーザーのみに制限 #--- 追加 9 ★★テストのときはコメントアウト★★ #
# def kd(): # '''修正前'''
def kd( user_name ): #--- 修正10
# 既存ファイルを確認
if not os.path.exists(file_path):
# 無ければ作成
with open( file_path, mode='w', encoding="UTF-8" ) as open_json:
initial_list = [{
"month" : [] , # "月"
"day" : [] , # "日"
"content" : [] , # "内訳"
"amount" : [] , # "金額"
"id" : [] , # "ID" #--- 追加10-2
"user" : [] # "ユーザー" #--- 追加10
} ]
json.dump( initial_list, open_json, indent=4, ensure_ascii=False)
# ペイ(収支)データ管理用クラス(KDpay.py)オブジェクト作成 #--- 追加7
pay_manager = PayManager()
# 一意なIDオブジェクト作成
main_key = str(ULID()) #--- 追加10-3
# JSONファイルを読み込んで、辞書型リストを作成
with open( file_path, mode='r', encoding="UTF-8") as open_json:
json_load_list = json.load(open_json)
# 読み込んだファイルをペイ(収支)データ管理用クラスオブジェクトに追加 --- 修正7
for pay_data in json_load_list:
pay_manager.add_pay(pay_data)
# ログイン中のユーザーの家計簿リストを作成
search_list = [ item for item in json_load_list if item['user'] == user_name ] #--- 追加10
# ------------------------------------------------------------------------------ #
#### HTTPリクエスト
#### GETメソッド受信 # --- 修正6
if request.method == 'GET':
# 更新した辞書型リストを送信し、HTMLをレンダリング
# return render_template('kakeibo_test_json/kd.html', title='kakeibo', pay_list = pay_manager.pay_data_list) #--- 修正7-4 '''修正前''''''
return render_template('kakeibo_test_json/kd.html', title='kakeibo',user_name = user_name , pay_list = search_list ) #--- 修正10
# ------------------------------------------------------------------------------ #
#### HTTPリクエスト
#### POSTメソッド受信
#### 「削除」
#### ボタンが押されたときの処理 # --- 追加 7
if request.method == 'POST' and request.form.get('delete_number') != None :
# number = int( request.form.get('delete_number') ) - 1 #--- 修正前
delete_target_id_number = int( request.form.get('delete_number') ) - 1 # 入力された削除番号を整数型に変換、リストの要素番号が0から始まるため1マイナス #--- 修正10-2
#--- 以下4行、追加10-2
search_list_id_list = [d.get('id') for d in search_list] # 個別ユーザーのidリスト
delete_target_id = search_list_id_list[delete_target_id_number] # 個別ユーザーのidリスト中、削除するid
json_load_list_id_list = [d.get('id') for d in json_load_list] # 全ユーザーのidリスト
delete_id_number = json_load_list_id_list.index(delete_target_id) # 全ユーザーのidリスト中、削除するidが何番目に存在するか
# pay_manager.delete_pay(number) #--- 修正前
pay_manager.delete_pay(delete_id_number) #--- 修正10-2
# JSONファイルに書き込み --- 修正7
with open(file_path, mode='w',encoding="UTF-8") as open_json:
updated_data_list=[]
for pay in pay_manager.pay_data_list:
updated_data_list.append({
"month" : pay.month,
"day" : pay.day,
"content" : pay.content,
"amount" : pay.amount,
"id" : pay.id , # --- 追加10-2
"user" : pay.user # --- 追加10
})
json.dump(updated_data_list, open_json ,indent=4,ensure_ascii=False)
updated_search_list = [ item for item in updated_data_list if item['user'] == user_name ] #--- 追加10
# 更新した辞書型リストを送信し、HTMLをレンダリング
# return render_template('kakeibo_test_json/kd.html', title='kakeibo', pay_list=pay_manager.pay_data_list) #--- 修正7-4 '''修正前'''
return render_template('kakeibo_test_json/kd.html', title='kakeibo',user_name = user_name , pay_list = updated_search_list ) #--- 修正10
# ------------------------------------------------------------------------------ #
#### HTTPリクエスト
#### POSTメソッド受信
#### 「送信」 ボタンが押されたときの処理 # --- 追加6-2
if request.method == 'POST':
# 画面上で入力された情報を取得し、辞書データを作成
add_dict = {"month" : request.form.get('month'),
"day" : request.form.get('day'),
"content" : request.form.get('content'),
"amount" : request.form.get('amount'),
"id" : main_key , # --- 追加10-2
"user" : user_name # --- 追加10
}
# 辞書データを辞書型リスト(PayManagerオブジェクト)に追加
pay_manager.add_pay(add_dict) #--- 修正7-5 (前) json_load_list.append(add_dict)
# JSONファイルに書き込み # --- 修正7-6
with open(file_path, mode='w',encoding="UTF-8") as open_json:
updated_data_list=[]
for pay in pay_manager.pay_data_list:
updated_data_list.append({
"month" : pay.month,
"day" : pay.day,
"content" : pay.content,
"amount" : pay.amount,
"id" : pay.id, # --- 追加10-2
"user" : pay.user # --- 追加10
})
json.dump(updated_data_list, open_json ,indent=4,ensure_ascii=False)
updated_search_list = [ item for item in updated_data_list if item['user'] == user_name ] #--- 追加10
# 更新した辞書型リストを送信し、HTMLをレンダリング
# return render_template('kakeibo_test_json/kd.html', title='kakeibo', pay_list=pay_manager.pay_data_list)# 修正7-4 '''修正前''''''
return render_template('kakeibo_test_json/kd.html', title='kakeibo',user_name = user_name , pay_list = updated_search_list ) #--- 修正10
# ------------------------------------------------------------------------------ #
#
# ------------------------------------------------------------------------------ #
if __name__ == '__main__':
app.run()
■■
■■

0 件のコメント:
コメントを投稿