LoginSignup
1
1

More than 1 year has passed since last update.

【Django】バリデーションエラーのテンプレートへの表示パターン

Last updated at Posted at 2022-10-29

サンプルモデル

例えばこんなモデルがあったとする。

models.py
class Urls(models.Model):
    instagram = models.URLField(verbose_name='instagram', blank=True, null=True)

バリデーション

forms.pyでclean_FIELDNAMを使いバリデーションする。

forms.py

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には全てのエラーを含むことができます。

html
{{ form.errors }}
    ↓
<ul class="errorlist">
    <li> instagram
        <ul class="errorlist">
            <li>「https://www.instagram.com/」で始まる必要があります。</li>
        </ul>
    </li>
</ul>

とても扱いづらそうなので却下!

その2

次はフィールド名を入れてみます。

html
{{ form.instagram.errors }}
    ↓
<ul class="errorlist">
    <li>「https://www.instagram.com/」で始まる必要があります。</li>
</ul>

このパターンは、inputタグの近くに使えそうです。

その3

inputタグとは別の場所に表示したい場合は、全てのエラーを出力したいのでform.errorsを使う必要があります。

for文で処理してみます。

html
{% for error in form.errors %}
    {{ error }}
{% endfor %}
    ↓
instagram

表示したいのはそっちじゃない(´・ω・`)

その4

エラーの文字列を表示したいのでitemsを使う。

html
{{ 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タグの近くでエラー表示させたい場合

html
<!-- リストで返す -->
{{ form.instagram.errors }}

<!-- 文字列で返す -->
{% for error in form.instagram.errors %}
    {{ error }}
{% endfor %}

inputタグとは別の場所で、全てのエラーに対応したい場合。

html
{% for key, errors in form.errors.items %}
    {% for error in errors %}
        {{ error }}
    {% endfor %}
{% endfor %}

間違いがあったら教えて下さい(´・ω・`)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1