サンプルモデル
例えばこんなモデルがあったとする。
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 %}
間違いがあったら教えて下さい(´・ω・`)