見出し画像

Webアプリ開発(Django+Vue.js+Docker)#13

こちらの記事の続きになります。

今回が最終回になります!!!
最後まで頑張りましょう!

今回はフォームバリデーションを行おうと思います。

フォームバリデーションとは??

フォームに入力された値が正しい値なのかをチェックする機能の事です。
ユーザがデータを登録するときに間違えて空白のまま登録してしまった、などのようなことが起こらないようにします。

今回は二種類のフォームバリデーションに挑戦してみます。
一つ目がバックエンドを使用する処理方法。
二つ目がVueを使用してフロントのみを使用する処理方法。
です。

バックエンド

チェックを行うライブラリを作成します。
「forms.py」というファイルを作成し、以下をコピペします。

import re
from django import forms
from django.core.exceptions import ValidationError

def check_name_length(value):
    name_length = len(value)
    if name_length < 4 or name_length >50:
        raise ValidationError('ユーザ名: 4~50文字で入力してください')

def check_email(value):
    email_length = len(value)
    if email_length < 4 or email_length > 50:
        raise ValidationError('正しいEmailを入力してください')

def check_password_length(value):
    pass_length = len(value)
    if pass_length < 8 or pass_length > 50:
        raise ValidationError('パスワード: 8~50文字で入力してください')
    
def check_password_re(value):
    if not re.compile(r'^[a-zA-Z0-9]+$').search(value):
        raise ValidationError('パスワード: 半角英数字で入力してください')

class UserForm(forms.Form):
    name = forms.CharField(
        label='name',
        required=True,
        max_length=100,
        validators=[check_name_length],
    )
    email = forms.CharField(
        label='email',
        required=True,
        max_length=100,
        validators=[check_email],
    )
    password = forms.CharField(
        label='password',
        required=True,
        max_length=100,
        validators=[check_password_length, check_password_re],
    )

まずコード上部では入力値チェックの関数を定義しています。
だいたい4~50文字で入力していないとエラーを返すようにします。

クラスの設定はコード下部のようにします。
validatorsの部分に必要な関数を格納します。

また、バリデーションしたいのは、新規登録の部分です。
そのため、views.pyファイルのcreate_user関数を以下のように変更します。

from .forms import UserForm


def create_user(request):
  if request.method == 'GET':
    return render(request, 'create_user.html')
  if request.method == 'POST':
    form = UserForm(request.POST)
    if form.is_valid():
      User.objects.create_user(username=request.POST.get('name'), password=request.POST.get('password'), email=request.POST.get('email'))
      return HttpResponseRedirect(reverse('test:login'))
    print(form.errors)
    return render(request, 'create_user.html', {'form': form})

これは、is_valid()が実行されたときに、先ほど設定したvalidatorに照らし合わせることが行われ、もし条件に当てはまらなかった場合、その時のエラーをform.errorsに格納します。
その後、create_user.htmlを表示すると同時に、エラーが出てしまった関数のraise ValidationErrorで設定した文字列を格納してフロントに送ります。

raise ValidationError('パスワード: 半角英数字で入力してください')

こちらも参考にしてみてください。

フロントエンド

バックエンドから送られてきたエラーをフロントエンドで表示する部分を作成しましょう。

create_user.htmlファイルに以下を追加しましょう。

<!-- フォームバリデーションエラーメッセージ -->
{% for field, errors in form.errors.items %}
  {% for error in errors %}
    <p class="alert alert-danger">{{ error }}</p>
  {% endfor %}
{% endfor %}

この部分にエラーが全て表示されるようになります。
では、実際に確認してみてください!
何か入力が不十分だとそれに対応したエラーが出力されます。

では次は、Vueのみで動的に行うフォームバリデーションを行います。

Vueによるバリデーション

create_test.htmlに作ってみましょう。

Vueを使うので、適用したいフォームタグ全体を<div id="msg">で囲いましょう。

<!-- 問題をdbに追加する -->
<div id="msg">
  <form method="post" action="{% url 'test:create_test' %}">
    {% csrf_token %}
    <!-- 科目のプルダウンメニュー -->
    ~~~~~~~~~~~~~  
  </form>
</div>

そして、監視したいテキストボックスを以下のように、タグ内にv-modelを設定し紐づけましょう。

<!-- 問題・解答 -->
<div class="mb-3">
  <label class="form-label">問題</label>
  <textarea  rows="5" cols="50" class="form-control" placeholder="問題文を入力してください" name="question" type="question" v-model="question"></textarea>
  <div v-if="check_que" style="color: red; text-align: right;">問題を入力してください</div>
</div>
<div class="mb-3">
  <label class="form-label">解答</label>
  <textarea  rows="5" cols="50" class="form-control" placeholder="解答を入力してください" name="answer" type="answer" v-model="answer"></textarea>
  <div v-if="check_ans" style="color: red; text-align: right;">解答を入力してください</div>
</div>

次は、Vue関数です。
ファイルの下部に以下をコピペしましょう。


{% endblock content %}

{% block cdn %}
  <!-- vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
{% endblock cdn %}

{% block script %}
  <script>
    new Vue({
      el: '#msg',
      delimiters: ['[[', ']]'],
      data: {
        question: '',
        answer: '',
      },
      computed: {
        /* フォームバリデーション */
        check_que: function () {
          return this.question.length < 1;
        },
        check_ans: function(){
          return this.answer.length < 1;
        },
      },
    })
  </script>
{% endblock script %}

v-modelとして紐づけた部分の文字数をカウントするような関数を作ります。
次に、エラーメッセージを表示する部分のタグ内にv-ifとして作った関数をせ呈することで、エラーメッセージを動的に表示/非表示を切り替えれるようになります。

ここで、いつものmethodsではなく、computedを使用しています。
理解が少し曖昧ですが、ボタンをクリックするなどのイベントによって処理が行われるものがmethodsで、今回のようなクリックなどせずデータを監視するときは、computedを使用しないと動かないようです。

また、エラーが生じている場合はテスト追加ボタンを押されてしまうと困るので、押せないようにしましょう。

ボタンタグを以下のように変更します。

<!-- 追加ボタン -->
<button type="submit" :disabled="!sendable" class="btn btn-primary" style="margin: 0.5rem; font-size: 25px;">テストを追加</button>

:disableに指定する値がもしtrueであればボタンが押せなくなるというものを使います。

Vueのconputedの処理には以下の関数を追加します。

 更新ボタン有効化 */
sendable: function() {
  return this.question.length > 0 && this.answer.length >0;
},

以上で完成です!
長い間お疲れさまでした。

後は、見た目を好みに整えて頂ければと思います。
整え方は、HTMLのタグ内に直接style=""と書いて整えるか、HTMLのタグ内にclass=""を指定して初めに作成したstyle.cssに記述していくかのどちらかで行っていただければと思います。

これで、あなたも一つポートフォリオができましたね!
今回でアプリ作り楽しいなって思っていただけたらとてもうれしいです!

また何か作った時は、コメントなどで知らせていただけると嬉しいです!

~追記(2022.12.27)~
ファイル構成ですが、treeコマンドなんて便利なものがあるんですね!
知りませんでした笑

コマンドプロンプトで指定のディレクトリに移動し、以下を打ち込むと表示できました。

tree /f
ディレクトリ構成

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