見出し画像

【97日目】Django_フォームから値を受け取ってグラフを作成

 このnoteは、31歳未経験からエンジニアを目指して勉強していく記録を綴っているものです。現在はAdTechでカスタマーサクセスを担当しつつ、色んなチャンスに恵まれ、CS業務や子育てと並行しながらチャレンジしています。

 これからプログラミングを始める方にとってのTipsやモチベアップに繋げられるように頑張りたいと思っています。
--------------------------------------------

Djangoでのグラフ表示の続きです。
本日の作業で実装したかった機能は無事実装することができました。
あとは見た目を整えるところですが、その前に何をどうやったかまとめたいと思います。

↓前回までの作業はこちら


本日の作業で以下の機能を実装できました。
・任意の対象期間を選択してグラフに表示
・ステータスが「完了済」のタスクのみを数える

↓こんなイメージになってます

バリデーションチェックも入れているので、例えば開始日と終了日が前後していたら以下のようになります。

グラフの見た目はまだ良くないですが、とりあえずやりたかったことは実装できました。


では、それぞれどうやったか見ていきたいと思います。


任意の対象期間を選択してグラフに表示

構成としてはformに入力した値をviewで受け取って、前回記事で紹介したグラフ作成のコードを走らせている感じになります。

まずforms.pyに開始日と終了日を入力するためのformを作成します。ここでは単純にformを定義するだけでなく、cleanメソッドを使ってバリデーションチェックをするようにしています。super().clean()でformに入力された値を変数に代入することができます。

[forms.py]
 
class AnalysisPeriodForm(forms.Form):
    start_day = forms.DateField(label="開始日", widget=DateInput())
    end_day = forms.DateField(label="終了日", widget=DateInput())

    def clean(self):
        period = super().clean()
        start_day = period["start_day"]
        end_day = period["end_day"]
        if start_day > end_day:
            raise ValidationError("開始日と終了日が前後しています。")
        return period


次にviews.pyを編集します。前回グラフ作成用のクラスはTemplateViewを継承していましたが、formを使うことになったのでFormViewに変更してます。form.cleaned_dataでバリデーションチェック済みの値を受け取れるので、そこから処理をスタートさせています。

get_context_dataメソッドでformの値に「form」という名前を、作成したグラフが入っているchartに「chart」という名前を付けています。これをrender_to_responseでテンプレートに渡すことで、テンプレート上で上記名前を変数として扱うことができます。

[views.py]
 
class TodoAnalysis(FormView):
    form_class = AnalysisPeriodForm
    template_name = "todo/todo_analysis.html"
    
    def form_valid(self, form):
        # formのclean関数を経てから日付を受取る
        period = form.cleaned_data
        start_day = period["start_day"]
        end_day   = period["end_day"]
        # グラフに表示する日数を指定する=for文で何回ループ処理するか
        N = (end_day - start_day).days + 1
        # 指定期間の辞書を作る
        tasks = {}
        for i in range(N):
            date = start_day + timedelta(i)
            tasks[date] = 0
        # Todoモデルのクエリセットからupdated_at(=最終更新日)を取得してdate型にする
        qs = Todo.objects.all()
        update_list = [ele.updated_at for ele in qs if str(ele.status) == "完了済"]
        dataf = pd.DataFrame({'time': update_list})
        dataf['time'] = pd.to_datetime(dataf['time']).dt.date

        for ele in dataf['time']:
            if ele in tasks:
                tasks[ele] += 1

        # グラフのx軸とy軸用のデータを格納する
        x = [x for x in tasks.keys()]
        y = [y for y in tasks.values()]
        chart = graph.Plot_Graph(x, y)

        # ここで引数に渡せば、上記のどの変数もテンプレートに渡せる(以下ではchart(右辺)をchart(左辺)の名前で渡しているし、form(右辺)もform(左辺)で渡している)
        ctxt = self.get_context_data(chart=chart, form=form)

        return self.render_to_response(ctxt)



ステータスが「完了済」のタスクのみを数える

これは一瞬で実装できます。上記views.pyにおける以下のコードが該当部分です。qsにデータベースから取得したタスクのデータが入っており、ステータスが「完了済」となっているタスクの「updated_at」のみをリスト化しています。

update_list = [ele.updated_at for ele in qs if str(ele.status) == "完了済"]

リスト内包表記については以下の記事で紹介しているので興味がある方はチェックしてみてください。


あとはmatplotlibのグラフ描画を勉強して、もうちょっといい感じの見た目にしたら完成です。

今回の取り組みでmatplotlibやpandasに興味が出てきたので、一度ちゃんと学んでみようとも思っています。

最後までお読みいただきありがとうございました!


これまで修了したコース等

【YouTube_Django関係】
Pythonでウェブサービスを作ろう! #1
テンプレートをマスターしよう! #2
静的ファイルを配信しよう !#3
本番公開しよう! #4
データベースと接続しよう! #5
ブログを作って学ぶモデル入門! #6
これが汎用ビューの力! #7
Djangoフォームを自由自在に操ろう! #8
djagoを最大限使って効率よくログインを作ろう! #9
ログイン完成!サインアップ & メール認証 #10
データベースマイグレーション前編 #15
データベースマイグレーション後編 #16

【Paiza】
Aランクレベルアップメニュー 24/49問
データセット選択メニュー   12/17問
配列メニュー         64/64問
ループメニュー1      20/20問
ループメニュー2      12/20問
条件分岐メニュー       25/25問
二重ループメニュー      19/19問
配列活用メニュー       26/26問
文字列処理メニュー      30/30問
Bランクレベルアップメニュー 62/62問
Cランクレベルアップメニュー 30/30問
ランクB合格
ランクC合格
JavaScript体験篇       15/15講座
辞書(ディクショナリ)の基礎 8/8講座

【書籍/ブログ】
Django入門 | 初心者でも1時間でWebアプリ(Todoアプリ)を作成するコース
基礎からのMySQL     514/514頁
Web技術の基本      189/189頁 ※2周目中
京大のPython教科書    116/201頁
Pythonデータベースプログラミング 194/194頁
Pythonエンジニアファーストブック読了

【Progate】
Python Ⅰ~Ⅴ
Python アプリ版 コースⅠ~Ⅴ
SQL Ⅰ~ Ⅳ
SQL アプリ版 コースⅢ
HTML&CSS 初級編

【その他】
Pythonの環境構築
VSCodeの環境構築
MySQLの環境構築(MAMP)
Git / GitHubの環境構築
HEROKUの環境構築

この記事が気に入ったらサポートをしてみませんか?