#form表單的校驗、局部鉤子及全局鉤子#
## views.py 視圖函數 ##css
from django import forms #調用forms模塊 from django.forms import widgets #調用widgets模塊,用來對form組件的參數配置。 from django.core.exceptions import ValidationError #調用 ValidationError 模塊。用來手動觸發raise錯誤。 from fileupdate.models import * #載入必要的數據庫列表。 class FormReg(forms.Form): name = forms.CharField(min_length=4, widget=widgets.TextInput(attrs={'class': 'form-control '}), label='姓名', error_messages={'required': '*不能爲空', }) pwd = forms.CharField(min_length=4, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), label='密碼') r_pwd = forms.CharField(min_length=4, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), label='確認密碼') email = forms.EmailField(widget=widgets.EmailInput(attrs={'class': 'form-control'}), label='郵箱') tel = forms.CharField(max_length=13, label='電話', widget=widgets.TextInput(attrs={'class': 'form-control'})) ##字段的校驗,經過對widget的屬性設置,可定義INPUT標籤的type類型,以及標籤的其餘屬性。經過對label設置,能夠自定義form渲染時的標籤名, ##另外,經過對error_messages屬性設置,可對驗證信息進行自定義。注意:字典中錯誤信息的key值是固定的 def clean_name(self): #局部鉤子 注意:名字必須爲clean_%s ,這是根據源碼來設置的。 #其原理是,當字段校驗完畢後,再進行查找是否有以clean_開頭的函數名,若是有,就調用該函數, #運行咱們自定義的函數,若是知足條件就返回當前被校驗字段的內容。不然手動觸發ValidationError錯誤,源碼中會捕獲並將值返回。 val = self.cleaned_data.get('name') #經過cleaned_data得到對應字段的'乾淨數據' user_obj = User.objects.filter(name=val).first() #與對應的數據庫中字段相比較,並得到一個字段對象 if not user_obj: #對字段進行判斷,若是爲空(數據庫中沒有對應的名字),那麼返回這個校驗值。 return val else: raise ValidationError('名字存在') #若是存在,那麼手動觸發異常(異常名爲ValidationError),並設置自定義內容。 def clean(self): #全局鉤子 注意:名字必須爲clean,這是根據源碼來設置的。 #其原理是對校驗完畢的字段,再進行字段間的校驗。當字段校驗完畢,查找是否有clean的函數,若是有就運行該 #函數,其功能是對全部校驗的字段進行校驗比對。若是知足條件,就將cleaned_data返回(這與源碼相匹配) #若是不知足就手動觸發ValidationError錯誤。 pwd = self.cleaned_data.get('pwd') r_pwd = self.cleaned_data.get('r_pwd') if pwd and r_pwd: #若是兩個字段中一個爲空值那麼就不用再進行校驗。直接返回cleaned_data,經過校驗功能返回錯誤信息。 if pwd == r_pwd: return self.cleaned_data else: raise ValidationError('兩次密碼不一致!') else: return self.cleaned_data def reg(request): if request.method == 'POST': #若是是一次POST提交,那麼進行校驗。 formreg = FormReg(request.POST) #對提交的信息實例化。 if formreg.is_valid(): #經過is_valid()方法進行判斷,(注意:當執行這個函數時,將對全部字段進行校驗,運行局部鉤子和全局鉤子) return HttpResponse('OK') else: print('cleaneddata', formreg.cleaned_data) print('errordata', formreg.errors) error = formreg.errors.get('__all__') #當設置了全局鉤子時,要設置一個變量來得到全局鉤子返回的錯誤信息。 #這是因爲,全局鉤子的錯誤在form對象的errors中,當clean()方法拋出異常時,源碼會自動捕獲,並將錯誤 #存儲在errors字典中,其中鍵名'__all__'就是全局鉤子的變量。 return render(request, 'reg.html', locals()) formreg = FormReg() #當爲get請求時,實例化一個空的對象,經過這個空的實例化對象能夠渲染前段,自動生成form表單。 return render(request,'reg.html', locals())
## reg.html 前端頁面 ##html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>reg</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form action="" method="post" novalidate> {% csrf_token %} {% for field in formreg %} <p> <label for="">{{ field.label }}</label> {{ field }} {% if field.name == 'r_pwd' %} <span style="color: crimson">{{ field.errors.0 }} {{ error.0 }}</span> {% else %} <span style="color: crimson">{{ field.errors.0 }}</span> {% endif %} </p> {% endfor %} <p><input type="submit"></p> </form> </div> </div> </div> </body> </html>