サンプルモデル
例えばこんなモデルがあったとする。
class Urls(models.Model):
instagram = models.URLField(verbose_name='instagram', blank=True, null=True)
バリデーション
forms.pyでclean_FIELDNAM
を使いバリデーションする。
class UrlForm(forms.ModelForm):
class Meta:
model = Urls
fields = ('instagram',)
def clean_instagram(self, *args, **kwargs):
if self.is_valid():
insta_url = self.cleaned_data['instagram']
# 空ならそのまま返す
if insta_url == None:
return insta_url
# インスタのURLと異なればエラー
elif not "https://www.instagram.com/" in str(insta_url):
raise forms.ValidationError('「https://www.instagram.com/」で始まる必要があります。')
# 正常の場合
return insta_url
そもそもURLField
ではなく、CharField
でinstagramのid
を設定するようにすれば良いが、それは置いておく笑
テンプレートに表示
その1
form.errors
には全てのエラーを含むことができます。
{{ form.errors }}
↓
<ul class="errorlist">
<li> instagram
<ul class="errorlist">
<li>「https://www.instagram.com/」で始まる必要があります。</li>
</ul>
</li>
</ul>
とても扱いづらそうなので却下!
その2
次はフィールド名を入れてみます。
{{ form.instagram.errors }}
↓
<ul class="errorlist">
<li>「https://www.instagram.com/」で始まる必要があります。</li>
</ul>
このパターンは、input
タグの近くに使えそうです。
その3
input
タグとは別の場所に表示したい場合は、全てのエラーを出力したいのでform.errors
を使う必要があります。
for文で処理してみます。
{% for error in form.errors %}
{{ error }}
{% endfor %}
↓
instagram
表示したいのはそっちじゃない(´・ω・`)
その4
エラーの文字列を表示したいのでitems
を使う。
{{ form.errors.items }}
↓
dict_items([
('url4', ['「https://www.instagram.com/」で始まる必要があります。'])
])
{% for key, errors in form.errors.items %}
{% for error in errors %}
{{ error }}
{% endfor %}
{% endfor %}
↓
「https://www.instagram.com/」で始まる必要があります。
多分この方法が正解?
フィールド名を使いたい場合は{{ key }}
を入れてあげると良いです。
errors
はfor文で回すと、<li>
ではなく文字列で返ってくるので、使い分けると良い。
ちなみに、form.errors
の中には、同メソッド内で出力するforms.ValidationError
の数しかエラーが入っていないっぽいので、一つしか定義していなければ複数出力されることはないと思います。
clean_FIELDNAME
は定義された順に実行され、一つずつ処理されるので、他のフィールドのエラーを同時に出力することも無いっぽい。
まとめ
input
タグの近くでエラー表示させたい場合
<!-- リストで返す -->
{{ form.instagram.errors }}
<!-- 文字列で返す -->
{% for error in form.instagram.errors %}
{{ error }}
{% endfor %}
input
タグとは別の場所で、全てのエラーに対応したい場合。
{% for key, errors in form.errors.items %}
{% for error in errors %}
{{ error }}
{% endfor %}
{% endfor %}
間違いがあったら教えて下さい(´・ω・`)