DjangoのFormsを使うことで、一般的なValidator処理を行うことができます。
例えば、アカウント名の入力項目は必須のはずが、入力されずに登録ボタンを押したケースがあります。
この場合のformsクラスは次のように示すことで実現できます。
# forms.py
class SampleForm(forms.Form):
# 中略
# 必須項目
username = forms.CharField(max_length = 30, widget=forms.TextInput(attrs={'size':50}))
# 任意項目の場合
# username = forms.CharField(max_length = 30, widget=forms.TextInput(attrs={'size':50}), required=False)
# 中略
これにより、入力されずに登録ボタンが押下された場合、
そのテキストフィールドの下に「フィールドを入力してください。」
というメッセージが吹き出しとして表示されます。
Validator処理としてはこれでもいいのですが、
やり方によっては、画面上部に表示させたいという場合があります。
残念ながら画面上部に表示させる方法が、Formsの機能には存在しません。
そこで、Validator処理をカスタマイズして、画面上部にエラーメッセージを表示させます。
まず、formクラス内にclean()メソッドがあります。
このメソッドにより、フィールド変数に対して独自のValidator処理を入れることができます。
アカウント名は必須であり、最大30文字までであり、かつ半角文字(記号は受け付けない)のみ入力できます。
しかし、すでに使用しているアカウント名を入力することはできません。
以上の制約を実装すると以下のような書き方になります。
# forms.py
from . import validatorUtil
from .models import MODEL_USER
class SampleForm(forms.Form):
# 中略
# 必須項目
username = forms.CharField(max_length = 30, widget=forms.TextInput(attrs={'size':50}))
# 中略
def clean(self):
msgs = []
data = super().clean()
v_username = data.get('username')
msgs.append(validatorUtil.requireInputCheck(v_username, u'アカウント名'))
msgs.append(validatorUtil.maxLengthCheck(v_username, 30, u'アカウント名'))
msgs.append(validatorUtil.alphabetNumberCheck(v_username, '', u'アカウント名'))
try:
user = MODEL_USER.objects.get(username=v_username)
msgs.append(forms.ValidationError(u'アカウント名は既に存在しています。', code='existedValue'))
except MODEL_USER.DoesNotExist:
pass
errorMsgs = []
for i, m in enumerate(msgs):
if m != None:
errorMsgs.append(m)
if len(errorMsgs) != 0:
raise forms.ValidationError(errorMsgs)
return data
# validatorUtil.py from django import forms def requireInputCheck(target, item): if target == None or len(target) == 0: return forms.ValidationError(u'%(item)sは必ず入力してください。', code='require', params={'item': item },) return None def maxLengthCheck(target, mlen, item): if target == None: return None if len(target) > mlen: return forms.ValidationError(u'%(item)sは%(maxLength)d文字以内で入力してください。', code='invalidLength', params={'item': item, 'maxLength': mlen},) return None def alphabetNumberCheck(target, ignoreCharacter, item): if target == None or len(target) == 0: return None if len(ignoreCharacter) != 0: for c in ignoreCharacter: target.replace(c, '') naLen = 0 for c in target: if unicodedata.east_asian_width(c) == 'Na': naLen = naLen + 1; if len(target) != naLen: return forms.ValidationError(u'%(item)sは半角文字で入力してください。', code='invalidCharacter', params={'item': item },) return None
from django.utils.translation import gettext as _
# 中略
return forms.ValidationError(_('This is Error!!'), code='invalid')
<!-- sample.html -->
{% if form.non_field_errors|length != 0 %}
<div id='errorMessage'>{{ form.non_field_errors }}</div>
{% endif %}
# views.py
# 中略
# Form初期処理
def initForm(data = None):
# いろいろな初期設定 中略
if data == None:
data = {}
data.update({'data1': data1, ・・・})
form = SampleForm(data)
return form
# 登録画面へ遷移
def goSample(request):
form = initForm()
return render(request, 'sample.html', { 'form': form })
# 登録処理
@transaction.atomic
def inSample(request):
# 不正アクセスのための制御
if not request.user.is_authenticated:
return HttpResponseRedirect('/app/logout')
if request.method == 'POST':
form = initForm(request.POST.copy())
if form.is_valid():
# 中略
else:
return render(request, 'sample.html', { 'form': form })
else:
# 中略
# forms.py
# 中略
class SampleForm(forms.Form):
# 中略
# clear()を初期処理のみ行わないようにするための制御を追加
initialized = False
def __init__(self, *args, **kwargs):
self.initialized = True
# 中略
def clean(self):
if self.initialized == True:
return
msgs = []
data = super().clean()
# 中略
# views.py # 中略 # 登録処理 @transaction.atomic def inSample(request): # 不正アクセスのための制御 if not request.user.is_authenticated: return HttpResponseRedirect('/app/logout') if request.method == 'POST': form = initUSDMC0310Form(request.POST.copy()) form.initialized = False #追加 if form.is_valid(): # 中略
ややごり押し感となりましたが、
もっとスマートな方法があれば、教えてください。
参考URL:
https://docs.djangoproject.com/ja/2.1/ref/forms/validation/
https://docs.djangoproject.com/en/2.1/ref/forms/fields/
https://stackoverflow.com/questions/2525905/how-do-i-display-the-django-all-form-errors-in-the-template
Comment
現在、コメントはありません。