clean()方法主要用於驗證相互依賴的字段,例如注冊時,填寫的“密碼”和“確認密碼”要相等時才符合要求。
在調用表單clean() 方法的時候,所有字段的驗證方法已經執行完(表單字段的默認驗證(如CharField())和特定字段屬性的驗證(clean_<fieldname>)),所以self.cleaned_data 填充的是目前為止已經合法的數據。所以你需要記住這個事實,你需要驗證的字段可能沒有通過初試的字段檢查。(例如你要驗證“密碼”和“確認密碼”是否相等,但或許它們沒有通過初始字段檢查,例如格式錯誤等,但仍會執行這一步)
在這一步,有兩種方法報告錯誤。你可以在clean() 方法中拋出ValidationError 來創建錯誤。例如:
forms.py
1 from django import forms 2 class RegisterForms(BaseForm, forms.Form): 3 password = forms.CharField() 4 confirm_password = forms.CharField() 5 6 def clean(self): 7 cleaned_data = super(RegisterForms, self).clean() # 注意,super(RegisterForms, self).clean() 的調用時為了保證維持父類中的驗證邏輯。 8 v1 = cleaned_data.get('password') 9 v2 = cleaned_data.get('confirm_password') 10 if v1 == v2: 11 pass 12 else: 13 raise ValidationError(message='密碼輸入不一致', code='invalid') #錯誤信息保存在errors.__all__中
1 view.py 2 def register(request): 3 if request.method == 'GET': 4 return render(request, 'register.html') 5 6 elif request.method == 'POST': 7 obj = RegisterForms(request=request, data=request.POST) 8 if obj.is_valid(): 9 pass 10 else: 11 error = obj.errors 12 return render(request, 'register.html', {'errors': error, 'obj':obj}) #因為要在HTML中把errors.__all__顯示出來,所以要把實例化的obj傳過去
register.html
1 <form method='post' action='/register.html'> 2 <div class="form-group"> 3 <label for="password">密碼</label> 4 <input type="password" class="form-control" id="password" name="password" placeholder="請輸入密碼"> 5 <p> 6 {{ errors.password.0 }} 7 {{ obj.non_field_errors.0 }} #顯示共有的錯誤信息 8 </p> 9 </div> 10 11 </form>
第二種方法涉及將錯誤消息關聯到某個字段。在這種情況下,讓我們在表單的顯示中關聯一個錯誤信息到“password” 。例如:
1 from django import forms 2 3 class RegisterForms(BaseForm, forms.Form): 4 password = forms.CharField() 5 confirm_password = forms.CharField() 6 7 def clean(self): 8 cleaned_data = super(RegisterForms, self).clean() 9 v1 = cleaned_data.get('password') 10 v2 = cleaned_data.get('confirm_password') 11 if v1 == v2: 12 pass 13 else: 14 msg = '密碼輸入不一致' 15 self.add_error('password', msg)
此時錯誤信息是關聯到password上的,因為不用傳遞實例化的obj,在register.html上也只需寫上"{{ errors.password.0 }}"