Django之form表單驗證順序


概述

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

驗證過程

驗證順序

流程詳解

  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_ &()的最后必須返回驗證完畢或修改后的值.

form驗證中自定義驗證機制

需求

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

看下views.py中的代碼:

...

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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM