#実現したいこと
自身の学習の一環で、目標の時間にかける時間を可視化するWebアプリを作成しています。
利用者の大まかな流れとしては、
①目標の個数を記入
②目標の内容と重みを記入
③目標にかけられる時間を算出するため、その他の時間(仕事や睡眠、食事など)を入力
④平日22日、休日8日とした上で入力情報から可処分時間を計算
⑤可処分時間を重みに基づいて配分し、結果として表示
になります。
#発生している不具合
現在質問させていただきたい内容として、「実行する状況によって発生するエラーやエラー発生有無が異なる」といったことになります。
具体的な状況として、
【状況1】 ローカルのMacOS上に構築した仮想環境(venv)
【状況2】 herokuを利用して公開したWebアプリを開発に使用しているPCで利用した場合
【状況3】 herokuを利用して公開したWebアプリをスマートフォンで利用した場合
の3つがあるのですが、
【状況1】のときはエラーは発生せずにうまく動作します。
【状況2】のときは主に
エラー2_1: NameError: name 'count_list' is not defined とcount_listが未定義の状態になってしまう
エラー2_2: 目標の個数を3つ以上にすると、目標の記入欄は4つ出現するが、結果は2つもしくは3つしか表示されない
エラー2_3: 目標の個数を3つにすると再度目標の個数入力画面へ遷移する(これは個数が入力されていなかった場合に想定している処理です)
といったエラーが発生します。
エラー2_1に関してはリロードしたり、一度TOP画面へ戻り、再度入力を行うと解消されます。
またこれは時間をあけた場合にのみ観測され、一度再入力し、エラーが発生しなくなるとその直後は何度試してもエラーが発生しません。
エラー2_2、2_3に関しては目標の内容記入欄の個数は入力値と一致しているものの、結果の表示では値が一致しない、といった状況です。
なおこれらの発生頻度は
エラー2_1: テストの初回のみ(時間をあけると再度発生)
エラー2_2: 100%エラーが発生
エラー2_3: 50%程度エラーが発生
【状況3】のときは
エラー3_1: 目標の個数を2つにしたが、結果では3つ表示される。
エラー3_2: 目標の個数を3つにしたが、結果は2つで表示される。
エラー3_3: 目標値記入後に。
2021-02-02T22:25:30.899761+00:00 app[web.1]: File "/app/app.py", line 60, in f_work 2021-02-02T22:25:30.899761+00:00 app[web.1]: impsum += float(importances[i - 1]) 2021-02-02T22:25:30.899769+00:00 app[web.1]: IndexError: list index out of range
といったエラーが発生します。
発生頻度は
エラー3_1: スマホアクセス時初回のみ(ただしエラー3_2と類似している)
エラー3_2: 50%程度エラーが発生
エラー3_3: 50%程度エラーが発生
になります。
#試したこと
herokuへのアップロードはvenvをactivateした状態で、pip freeze > requirements.txtを作成し、
.gitignoreを下記内容で作成。
# Virtualenv # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ .Python [Bb]in [Ii]nclude [Ll]ib [Ll]ib64 [Ll]ocal [Ss]cripts pyvenv.cfg .venv pip-selfcheck.json
herokuへコミットする際はgit add .で下記のディレクトリをコミットしています。
- Procfile - __pycache__ - app.py - myfunc.py - requirement.py - static └styles.css └img └imgファイル - templates └htmlファイル - venv
#ソースコード
[app.py]
python
1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4#モジュールのインポート 5from flask import Flask, render_template, request 6from myfunc import my_remove 7 8#クラスの定義 9class Conditions: 10 def __init__(self, work = 0, sleep = 0, breakfast = 0, lanch = 0, dinner = 0,\ 11 bath = 0, housework = 0, others = 0): 12 self.work = float(work) 13 self.sleep = float(sleep) 14 self.breakfast = float(breakfast) 15 self.lanch = float(lanch) 16 self.dinner = float(dinner) 17 self.bath = float(bath) 18 self.housework = float(housework) 19 self.others = float(others) 20 21 def sum_condition(self): 22 sum_wd = self.work + self.sleep + self.breakfast + self.lanch + self.dinner + self.bath + self.housework + self.others 23 sum_hd = self.sleep + self.breakfast + self.lanch + self.dinner + self.bath + self.housework + self.others 24 return sum_wd, sum_hd 25 26#インスタンス化 27app = Flask(__name__) 28cond = Conditions() 29 30#ルーティング 31@app.route('/') 32def f_top(): 33 return render_template("index.html") 34 35@app.route('/count') 36def f_count(): 37 return render_template('count.html') 38 39@app.route('/goal', methods = ['POST']) 40def f_goal(): 41 if request.form['count']: 42 global count 43 global count_list 44 count = int(request.form['count']) 45 count_list = range(1, count + 1, 1) 46 return render_template("input_goal.html", count = count_list) 47 else: 48 return render_template("count.html") 49 50@app.route('/work', methods = ['POST']) 51def f_work(): 52 if request.form.getlist('goal') and request.form.getlist('importance'): 53 global goals 54 global importances 55 global impsum 56 goals = my_remove(request.form.getlist('goal'), "") 57 importances = my_remove(request.form.getlist('importance'), "") 58 impsum = 0 59 for i in count_list: 60 impsum += float(importances[i - 1]) 61 if len(goals) == count and len(importances) == count: 62 return render_template("input_work.html") 63 else: 64 return render_template('count.html') 65 66@app.route('/sleep', methods = ['POST']) 67def f_sleep(): 68 if request.form['work-hours'] and request.form['work-minutes']: 69 cond.work = int(request.form['work-hours']) * 60 + int(request.form['work-minutes']) 70 return render_template("input_sleep.html") 71 72@app.route('/breakfast', methods = ['POST']) 73def f_breakfast(): 74 if request.form['sleep-hours'] and request.form['sleep-minutes']: 75 cond.sleep = int(request.form['sleep-hours']) * 60 + int(request.form['sleep-minutes']) 76 return render_template("input_breakfast.html") 77 78@app.route('/lanch', methods = ['POST']) 79def f_lanch(): 80 if request.form['breakfast-hours'] and request.form['breakfast-minutes']: 81 cond.breakfast = int(request.form['breakfast-hours']) * 60 + int(request.form['breakfast-minutes']) 82 return render_template("input_lanch.html") 83 84@app.route('/dinner', methods = ['POST']) 85def f_dinner(): 86 if request.form['lanch-hours'] and request.form['lanch-minutes']: 87 cond.lanch = int(request.form['lanch-hours']) * 60 + int(request.form['lanch-minutes']) 88 return render_template("input_dinner.html") 89 90@app.route('/bath', methods = ['POST']) 91def f_bath(): 92 if request.form['dinner-hours'] and request.form['dinner-minutes']: 93 cond.dinner = int(request.form['dinner-hours']) * 60 + int(request.form['dinner-minutes']) 94 return render_template("input_bath.html") 95 96@app.route('/housework', methods = ['POST']) 97def f_housework(): 98 if request.form['bath-hours'] and request.form['bath-minutes']: 99 cond.bath = int(request.form['bath-hours']) * 60 + int(request.form['bath-minutes']) 100 return render_template("input_housework.html") 101 102@app.route('/others', methods = ['POST']) 103def f_others(): 104 if request.form['housework-hours'] and request.form['housework-minutes']: 105 cond.housework = int(request.form['housework-hours']) * 60 + int(request.form['housework-minutes']) 106 return render_template("input_others.html") 107 108@app.route('/time_allocate', methods = ['POST']) 109def f_time_allocate(): 110 if request.form['others-hours'] and request.form['others-minutes']: 111 cond.others = int(request.form['others-hours']) * 60 + int(request.form['others-minutes']) 112 113 #可処分時間の計算 114 freetime_wd = 24 * 60 - cond.sum_condition()[0] 115 freetime_hd = 24 * 60 - cond.sum_condition()[1] 116 117 #時間配分 118 global allocated_times 119 allocated_times = [] 120 time_goal = [] 121 for i in count_list: 122 all_minutes = freetime_wd * (float(importances[i - 1]) / impsum) * 22 + freetime_hd * (float(importances[i - 1]) / impsum) * 8 123 minutes = all_minutes % 60 124 hours = all_minutes // 60 125 time_goal = [hours, minutes, goals[i - 1]] 126 allocated_times.append(time_goal) 127 return render_template("result.html", count = count_list, goals = goals,allocated_times = allocated_times)
htmlファイルは数が多くなっているので、不具合が発生しているcount.htmlとresult.htmlのみ載せます
[count.html]
html
1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <meta charset="utf-8"> 5 <link rel="stylesheet" href="../static/styles.css"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 7 <title>Time Allocator</title> 8 </head> 9 <body> 10 <main id="count-main"> 11 <h1>目標の数</h1> 12 <div id="count-lead"> 13 <p>あなたがこの1ヶ月で取り組もうと<br> 14 している目標の数を教えてください</p> 15 </div> 16 <div> 17 <form method="POST" action="/goal"> 18 <p>タスクの個数を記入してください</p> 19 <div class="div-input"> 20 <input id="input-count" name="count" type="number" step="1" required> 21 <p>個の目標達成を目指す</p> 22 </div> 23 <div class="div-img"> 24 <img src="../static/img/busy.png" id="img-count"> 25 </div> 26 <div class="div-button"> 27 <button type="submit">つぎへ</button> 28 </div> 29 </form> 30 </div> 31 </main> 32 <footer> 33 </footer> 34 </body> 35</html>
[result.html]
html
1<!DOCTYPE html> 2<html lang="ja"> 3 <head> 4 <meta charset="utf-8"> 5 <link rel="stylesheet" href="../static/styles.css"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 7 <title>Time Allocator</title> 8 </head> 9 <body> 10 <main id="result-main"> 11 <h1>計算結果</h1> 12 <div id="result-div"> 13 <p>計算結果が出ました<br> 14 それでは結果を見てみましょう</p> 15 </div> 16 <div id="result"> 17 <p class="title-sentence"><b>あなたは1ヶ月の中で</b></p> 18 {% for lists in allocated_times %} 19 <div class="result-detail"> 20 <p>「{{lists[0]}}時間 {{lists[1]}}分」かけて<br>「{{lists[2]}}」</p> 21 </div> 22 {% endfor %} 23 <p>という目標を達成しようとしてます</p> 24 <div class="div-img"> 25 <img src="../static/img/result.png" id="img-others"> 26 </div> 27 </div> 28 <button onclick="location.href='/'">Topへもどる</button> 29 </main> 30 </body> 31</html> 32
#環境
マシン: MacBook Pro(M1)
Python: 3.8.2
Flask: 1.1.2
Jinja2: 2.11.3
Werkzeug: 1.0.1
長くなってしまい恐縮ですが、お知恵お借りできますと幸いです。
何卒よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/02/03 08:51