見出し画像

【78日目】Django_FormViewとは?_プログラミング学び日記

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

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

最近イスと湾曲モニターが欲しくてたまらないです。
イスは結構深刻な話で、昨年ぎっくり腰をやってから足の神経痛(腰から来る)が全く取れず、そろそろ腰の負担が減らせるものを買おうか悩んでいます。

湾曲モニターは憧れもありつつ、ドッキングステーション代わりになるものもあるようで、だったら余計ありだなーと。これは資格に合格するとか、自分へのご褒美系で買おうと思ってます。


さて本日はYouTubeのチュートリアルを進めて、FormViewについて学びました。いつもの動画シリーズから学ばせていただいています。


↓こんな感じの、自動でテキストの任意の文字を変換してくれるアプリが完成します


FormViewとは?

その名の通り、フォームを表示するためのViewです。基本要素は
①表示&入力する
②バリデーションする
③内容を処理する
の3つです。

FormViewのクラス図
https://www.membersedge.co.jp/blog/completely-guide-for-django-class-based-views/


まずは「forms.py」という専用のファイルを作って、そこにフォームを定義します。バリデーションを検知するためのclean()関数も書いておきます。ちなみにwidgetはformの見せ方をhtmlに渡したいときに使うもので、入力するデータは変わらないけど見た目だけが変わる、という性質のものです。

forms.py  # 簡略化のため見た目を整える系のコードは省略しています
 
from django import forms
from django.core.exceptions import ValidationError

# テキストを3つ受け取るフォームを作る
class TextForm(forms.Form):
    text = forms.CharField(label="", widget=forms.Textarea)
    search = forms.CharField(label="検索")
    replace = forms.CharField(label="置換")

    # バリデーションエラーを検知するための関数(ユーザーから送信があった後に自動で動く)
    def clean(self):
        data = super().clean()
        text = data["text"]
        if len(text) <= 5:
            raise ValidationError("テキストが短すぎます。6文字以上入力してください。")  
        return data

このフォームをviews.pyで受け取って、必要な処理を実行してテンプレートに渡します。data = form.cleaned_dataがFormの内容を受け取っている箇所です(forms.pyのclean()関数でバリデーションOKだったものを受け取っている)。

views.py

from django.views.generic.edit import FormView
from . import forms

class Index(FormView):
    form_class = forms.TextForm
    template_name = "index.html"

    # ユーザーの入力がバリデーションOKならこの関数が自動的に呼ばれる
    def form_valid(self, form):
        data = form.cleaned_data
        text = data["text"] 
        search = data["search"]
        replace = data["replace"]

        # 「textの中のsearchの文字をreplaceに変換する」というメソッド
        new_text = text.replace(search, replace)
        ctxt = self.get_context_data(new_text=new_text, form=form)
        
        # 生成したコンテキストをrender_to_responseでhtmlに渡す
        return self.render_to_response(ctxt)

コンテキスト変数としてformnew_textが渡されてきているので、それを使ってテンプレートを書きます。FormViewではデフォルトでformというコンテキスト変数にデータが格納されてきますが、ここでは新たにnew_textを追加するため、get_context_dataで改めて指定しています。

また、今回のformにはフォームラベルエラー内容の3つが格納されてきていて、フォームとラベルは{% for field in form %}で、エラーは{% for error in form.non_field_errors %}でそれぞれアクセスできます。clean()で検知したエラーはこのnon_field_errorsでないとアクセスできない(表示できない)ので注意です。

index.html
#ブートストラップのCSSひな型セットを利用してextendsしている

{% extends "base.html" %}
{% block main %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
    {{ error }}
</div>
{% endfor %}
<div class="row">
    <div class="col-sm">
        <h2>変換前</h2>
        <form method="post">
            {% csrf_token %}
            {% for field in form %}
            <p>
                <label>{{ field.label }}</label>
                {{ field }}
            </p>
            {% endfor %}
            <input type="submit" value="変換" class="btn btn-info" />
        </form>
    </div>
    <div class="col-sm">
        <h2>変換後</h2>
        <p>{{ new_text }}</p>
    </div>
</div>
{% endblock %}

ちなみに{{ form.as_p }}と一括で記載してもformの中身を表示できますが、上述の通りラベルとフォームとエラー内容の3つがformには入っているので、エラーの内容がフォームの途中に表示されて見栄えが微妙になります。そのため今回はそれぞれにアクセスして表示するように記載した感じです。

どういう流れで動作している?

FormViewで面白いと思ったのは、データベースが絡まないためか、FormとViewの間でデータの行き来があることです。以下の流れで動いています。

  1. Viewを経由してFormの「text,search,replace」がユーザーに表示される

  2. ユーザーが各Formに入力して送信

  3. forms.pyのclean()関数が自動で呼ばれ入力のバリデーションチェック

  4. バリデーションOKならviews.pyのform_valid()関数が自動で呼ばれて処理を実行

  5. バリデーションNGならclean()関数内のraise VaridationErrorで任意のエラー表示をユーザーに返す


CreateViewとの違いは?

ユーザーがデータを入力できるという点で、FormViewはCreateViewとよく似ています。ただし大きな違いがあります。CreateViewはmodelを通してデータベースに自動で保存するのに対し、FormViewはデータベースには保存されないため、そのフォームをどう処理するかは開発者が決めることができます。

つまりは自動でDBに保存しない用途の場合はFormViewを活用することになります。


FormViewについては以上です!
似た機能でModelFormというのもありますが、それはそんなに難しくないので一旦割愛します。



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

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

【Paiza】
Aランクレベルアップメニュー 24/49問
データセット選択メニュー 4/17問
配列メニュー      59/64問
ループメニュー1              20/20問
ループメニュー2              12/20問
条件分岐メニュー    25/25問
二重ループメニュー   19/19問
配列活用メニュー    26/26問
文字列処理メニュー   30/30問
Bランクレベルアップメニュー 62/62問
Cランクレベルアップメニュー 30/30問
ランクB合格
ランクC合格

【書籍/ブログ】
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の環境構築

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