Django之form表單驗證順序

概述

django框架提供了一個forms類,來處理web開發中的表單相關事項。衆所周知,form最常作的是對用戶輸入的內容進行驗證,爲此django的forms類提供了全面的內容驗證支持。html

驗證過程

驗證順序

流程詳解

  1. 函數full_clean()依次調用每一個field的clean()函數,該函數針對field的max_length,unique等約束進行驗證,若是驗證成功則返回值,不然拋出ValidationError錯誤。若是有值返回,則放入form的cleaned_data字典中。
  2. 若是每一個field的內置clean()函數沒有拋出ValidationError錯誤,則調用以clean_開頭,以field名字結尾的自定義field驗證函數。驗證成功和失敗的處理方式同步驟1。
  3. 最後,調用form的clean()函數——注意,這裏是form的clean(),而不是field的clean()——若是clean沒有錯誤,那麼它將返回cleaned_data字典。
  4. 若是到這一步沒有ValidationError拋出,那麼cleaned_data字典就填滿了有效數據。不然cleaned_data不存在,form的另一個字典errors填上驗證錯誤。在template中,每一個field獲取本身錯誤的方式是:{{ form.username.errors }}。
  5. 最後,若是有錯誤is_valid()返回False,不然返回True。

注意一點:自定義驗證機制時:clean()和clean_ &()的最後必須返回驗證完畢或修改後的值. web

form驗證中自定義驗證機制

需求

  1. 用戶輸入的是否爲cc,若是是,提示用戶
  2. 驗證二次輸入的密碼是否匹配,若是不一致,提示用戶

看下views.py中的代碼:django

...

from django import forms
from django.core.exceptions import ValidationError
import re


def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手機號碼格式錯誤')


class LoginForm(forms.Form):
    user = forms.CharField(required=True, error_messages={'required': '用戶名不能爲空.'})
    pwd = forms.CharField(required=True,
                          min_length=6,
                          max_length=10,
                          error_messages={'required': '密碼不能爲空.', 'min_length': "至少6位"})

    pwd2 = forms.CharField(required=True,
                          min_length=6,
                          max_length=10,
                          error_messages={'required': '密碼不能爲空.', 'min_length': "至少6位"})


    num = forms.IntegerField(error_messages={'required': '數字不能空.', 'invalid': '必須輸入數字'})

    phone = forms.CharField(validators=[mobile_validate, ], )

    def clean_user(self):
        user = self.cleaned_data.get('user')
        if user == 'cc':
            raise forms.ValidationError('用戶名是個人!')

        return user

    def clean(self):
        cleaned_data = self.cleaned_data
        pwd = cleaned_data['pwd']

        pwd2 = cleaned_data['pwd2']
        print(pwd,pwd2)
        if pwd != pwd2:
            raise forms.ValidationError('二次輸入密碼不匹配')
        return cleaned_data #注意此處必定要return clean_data,不然會報錯
        
        


def login(request):
    if request.POST:
        objPost = LoginForm(request.POST)
        ret = objPost.is_valid()
        if ret:
            print(objPost.clean())
        else:
            from django.forms.utils import ErrorDict
            print(objPost.non_field_errors())

            pass
        return render(request, 'login.html', {'obj1': objPost})
    else:
        objGet = LoginForm()
        return render(request, 'login.html', {'obj1': objGet})
   
...

HTML 頁面中,若是想取clean()報錯的信息,因其自己是一個迭代器,因此咱們能夠循環返回數據的non_field_errors取值,好比:框架

<div>
            {%  if obj1.non_field_errors %}
                {% for item in obj1.non_field_errors %}
                    <span class="error_msg">{{ item }}</span>
                {% endfor %}
            {% endif %}

我來看下html中的設置:函數

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .error_msg{
            color: red;
        }
    </style>
</head>
<body>
    <form action="/login/" method="POST">
        <div>用戶名:
            {{ obj1.user }}
            {%  if obj1.errors.user %}
                <span class="error_msg">{{ obj1.errors.user.0 }}</span>
            {% endif %}
        </div>
        <div>密碼:
            {{ obj1.pwd }}
            {%  if obj1.errors.pwd %}
                <span class="error_msg">{{ obj1.errors.pwd.0 }}</span>
            {% endif %}
        </div>
        <div>確認密碼:
            {{ obj1.pwd2 }}
            {%  if obj1.errors.pwd2 %}
                <span class="error_msg">{{ obj1.errors.pwd2.0 }}</span>
            {% endif %}
        </div>
        <div>數字:
            {{ obj1.num }}
            {%  if obj1.errors.num %}
                <span class="error_msg">{{ obj1.errors.num.0 }}</span>
            {% endif %}
        </div>
        <div>電話:
            {{ obj1.phone }}
            {%  if obj1.errors.phone %}
                <span class="error_msg">{{ obj1.errors.phone.0 }}</span>
            {% endif %}
        </div>
        <div>
            {%  if obj1.non_field_errors %}
                {% for item in obj1.non_field_errors %}
                    <span class="error_msg">{{ item }}</span>
                {% endfor %}
            {% endif %}
        </div>
        <input type="submit" value="提交"/>

    </form>


</body>
</html>
相關文章
相關標籤/搜索