Python | Django | フォームにおけるバリデーションの使い方

公開日:2021/7/8
Pythonには,DjangoというWebアプリケーションフレームワークがある.フレームワークのため,Djangoを利用するとWebアプリを通常よりも短時間で開発することが可能になる.
前記事にて,「フォームにおけるフィールドの使い方」を記した.前記事での設定をそのまま引き継いだ上で,本記事では,「フォームにおけるバリデーションの使い方」を以下3つの構成にて記す.
◆実施環境
Python 3.8.8
Django 3.2.3
■フォームにおけるフィールドの使い方
前記事で作成した以下ページ(“http://127.0.0.1:8000/form_application/form_page/")において,本項では,"チョコレート名"に入力制限をかける.

“form_app/forms.py"に追記し,以下のように編集する."チョコレート名"に入力する際,"F"から始めないとエラーが出るようなコードを追記した.
from django import forms
class ChocolateInfo(forms.Form):
chocolate_name = forms.CharField(label='チョコレート名', max_length=50)
chocolate_maker = forms.CharField(label='チョコレートメーカー', max_length=50)
mail = forms.EmailField(label='メールアドレス')
is_available_for_sale = forms.BooleanField(label='販売中')
birthday = forms.DateField(required=False, label='開発日')
price = forms.DecimalField(initial=300, max_value=1000, label='価格')
flavor = forms.ChoiceField(choices=(
(1,'Original Chocolat'),
(2,'Double Chocolat'),
(3,'Original White'),
(4,'Rich Matcha'),
), widget=forms.RadioSelect, label='味')
maker_factory = forms.MultipleChoiceField(choices=(
(1,'Ibaraki Moriya-city'),
(2,'Saitama Sakado-city'),
(3,'Aichi Inazawa-city'),
(4,'Osaka Takatsuki-city'),
), widget=forms.CheckboxSelectMultiple, label='メーカー工場')
homepage = forms.URLField(
label='ホームページ',
widget=forms.TextInput(attrs={'class':'url_class','placeholder':'https://www.shelokuma.com'})
)
def __init__(self,*args,**kwargs):
super(ChocolateInfo, self).__init__(*args,**kwargs)
self.fields['flavor'].widget.attrs['id']='id_flavor'
self.fields['maker_factory'].widget.attrs['class']='maker_factory_class'
def clean_chocolatename(self): # 以下追記箇所
chocolate_name = self.cleaned_data['chocolate_name']
if not chocolate_name.startswith('F'):
raise forms.ValidationError('名前は「F」から始めてください')
ターミナルを開き,”conda activate 仮想環境名”を実行し,仮想環境に移行する(移行方法の詳細はこちら).”form_project”のディレクトリで”python manage.py runserver”を実行する.私の場合,以下のように実行する.
(djangoenv) C:\Users\shiro\Desktop\210517_python development\myformtest\form_project
>python manage.py runserver
実行すると,ターミナルに以下が出力される.
System check identified no issues (0 silenced).
July 08, 2021 - 13:25:33
Django version 3.2.3, using settings 'form_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
“http://127.0.0.1:8000/”をクリックし,ブラウザを開くと以下のように表示される.

“http://127.0.0.1:8000/form_application”をクリックし,ブラウザを開くと以下のように表示される.

上記の"Go to Form"をクリックすると以下ページ(“http://127.0.0.1:8000/form_application/form_page/")に遷移する.

以下にて,チョコレート名を"F"から始まらない"aaaaa"にし,"submit"をクリックすると,赤枠にエラーが出現する.

以下のように,チョコレート名を"F"から始まるように修正し,"submit"をクリックするとエラーは出現しない.

ターミナルには,以下のように上記で入力した内容が出力された.
submission is successful
{'chocolate_name': 'Faaa', 'chocolate_maker': 'Meiji',
'mail': 'Faaa@gmail.com', 'is_available_for_sale': True,
'birthday': datetime.date(1999, 1, 1), 'price': Decimal('300'),
'flavor': '3', 'maker_factory': ['1', '2'],
'homepage': 'https://www.google.com'}
以下ページ(“http://127.0.0.1:8000/form_application/form_page/")で"価格"に入力制限をかける.

“form_app/forms.py"の2行目と10行目に追記し,以下のように編集する.価格を入力する際,1未満だとエラーが出るようなコードを追記した.
from django import forms
from django.core import validators # 追記箇所
class ChocolateInfo(forms.Form):
chocolate_name = forms.CharField(label='チョコレート名', max_length=50)
chocolate_maker = forms.CharField(label='チョコレートメーカー', max_length=50)
mail = forms.EmailField(label='メールアドレス')
is_available_for_sale = forms.BooleanField(label='販売中')
birthday = forms.DateField(required=False, label='開発日')
price = forms.DecimalField(initial=300, max_value=1000, label='価格',validators=[validators.MinValueValidator(1, message='1以上にしてください')]) # 追記箇所
flavor = forms.ChoiceField(choices=(
(1, 'Original Chocolat'),
(2, 'Double Chocolat'),
(3, 'Original White'),
(4, 'Rich Matcha'),
), widget=forms.RadioSelect, label='味')
maker_factory = forms.MultipleChoiceField(choices=(
(1, 'Ibaraki Moriya-city'),
(2, 'Saitama Sakado-city'),
(3, 'Aichi Inazawa-city'),
(4, 'Osaka Takatsuki-city'),
), widget=forms.CheckboxSelectMultiple, label='メーカー工場')
homepage = forms.URLField(
label='ホームページ',
widget=forms.TextInput(attrs={'class':'url_class','placeholder':'https://www.shelokuma.com'})
)
def __init__(self,*args,**kwargs):
super(ChocolateInfo, self).__init__(*args, **kwargs)
self.fields['flavor'].widget.attrs['id'] = 'id_flavor'
self.fields['maker_factory'].widget.attrs['class'] = 'maker_factory_class'
def clean_chocolatename(self):
chocolate_name = self.cleaned_data['chocolate_name']
if not chocolate_name.startswith('F'):
raise forms.ValidationError('名前は「F」から始めてください')
ターミナルを開き,仮想環境に移行し,”form_project”のディレクトリで”python manage.py runserver”を実行すると以下が出力される.
System check identified no issues (0 silenced).
July 08, 2021 - 13:25:33
Django version 3.2.3, using settings 'form_project.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
“http://127.0.0.1:8000/”をクリックし,ブラウザを開くと以下のように表示される.

その後,以下ページ(“http://127.0.0.1:8000/form_application/form_page/")に遷移し,各項目を入力をし,"submit"をクリックする.価格が1未満である"0″だったため,エラーが出現した.

以下のように,価格を1以上に修正し,"submit"をクリックするとエラーは出現しない.

ターミナルには,以下のように上記で入力した内容が出力された.
submission is successful
{'chocolate_name': 'Fran10', 'chocolate_maker': 'Meiji',
'mail': 'Fran10@gmail.com', 'is_available_for_sale': True,
'birthday': datetime.date(1999, 1, 1), 'price': Decimal('1'),
'flavor': '1', 'maker_factory': ['2'],
'homepage': 'https://www.google.com'}
以下ページ(“http://127.0.0.1:8000/form_application/form_page/")の"メールアドレス"の下に"メールアドレス再入力"を作成し,メールアドレスの一致確認をする.

“form_app/forms.py"の8行目と41行目に追記し,以下のように編集する."メールアドレス"の下に"メールアドレス再入力"を作成し,メールアドレスが同じでないとエラーを出現させるようなコードを追記した.
from django import forms
from django.core import validators
class ChocolateInfo(forms.Form):
chocolate_name = forms.CharField(label='チョコレート名', max_length=50)
chocolate_maker = forms.CharField(label='チョコレートメーカー', max_length=50)
mail = forms.EmailField(label='メールアドレス')
confirmed_mail = forms.EmailField(label='メールアドレス再入力') # 追記箇所
is_available_for_sale = forms.BooleanField(label='販売中')
birthday = forms.DateField(required=False, label='開発日')
price = forms.DecimalField(initial=300, max_value=1000, label='価格',validators=[validators.MinValueValidator(1, message='1以上にしてください')])
flavor = forms.ChoiceField(choices=(
(1, 'Original Chocolat'),
(2, 'Double Chocolat'),
(3, 'Original White'),
(4, 'Rich Matcha'),
), widget=forms.RadioSelect, label='味')
maker_factory = forms.MultipleChoiceField(choices=(
(1, 'Ibaraki Moriya-city'),
(2, 'Saitama Sakado-city'),
(3, 'Aichi Inazawa-city'),
(4, 'Osaka Takatsuki-city'),
), widget=forms.CheckboxSelectMultiple, label='メーカー工場')
homepage = forms.URLField(
label='ホームページ',
widget=forms.TextInput(attrs={'class':'url_class','placeholder':'https://www.shelokuma.com'})
)
def __init__(self,*args,**kwargs):
super(ChocolateInfo, self).__init__(*args, **kwargs)
self.fields['flavor'].widget.attrs['id'] = 'id_flavor'
self.fields['maker_factory'].widget.attrs['class'] = 'maker_factory_class'
def clean_chocolatename(self):
chocolate_name = self.cleaned_data['chocolate_name']
if not chocolate_name.startswith('F'):
raise forms.ValidationError('名前は「F」から始めてください')
def clean(self): # 以下追記箇所
cleaned_data = super().clean()
mail = cleaned_data['mail']
confirmed_mail = cleaned_data['confirmed_mail']
if mail != confirmed_mail:
raise forms.ValidationError('メールアドレスが一致しません')
以下ページ(“http://127.0.0.1:8000/form_application/form_page/")に遷移し,各項目を入力をし,"submit"をクリックする."メールアドレス"と"メールアドレス再入力"が異なる内容だったため,エラーが出現した.

以下のように,"メールアドレス"と"メールアドレス再入力"を同じにし,"submit"をクリックするとエラーは出現しない.

ターミナルには,以下のように上記で入力した内容が出力された.
submission is successful
{'chocolate_name': 'Fran100', 'chocolate_maker': 'Meiji',
'mail': 'Fran100@gmail.com', 'confirmed_mail': 'Fran100@gmail.com',
'is_available_for_sale': True, 'birthday': datetime.date(2000, 1, 1),
'price': Decimal('400'), 'flavor': '1', 'maker_factory': ['1', '2'],
'homepage': 'https://www.yahoo.co.jp'}
■参照
以上