Django def clean()函式對錶單中的資料進行驗證操作
最近寫的資源策略管理,在ceilometer 中建立alarm時,name要求是不能重複的,所以在建立policy的時候,要對policy的name欄位進行驗證,而django中正好擁有強大的表單資料驗證的功能。
#這是policy中的name欄位,在表單的資料進行提交的時候,所有的資料流會經過clean()這個函式
name = forms.CharField(max_length=255,label=_("Name"))
#在clean函式中先取出表單中的name欄位,在從資料庫裡面拿到所有的資料進行檢查 def clean(self): cleaned_data = super(CreatePolicyForm,self).clean() name = cleaned_data.get('name') try: policys = api.nova.policy_list(self.request) except: exceptions.handle(request,_('Unable to retrieve policys list.')) if policys is not None and name is not None: for policy in policys: if policy.name.lower() == name.lower(): raise forms.ValidationError( _('The name "%s" is already used by another policy.') % name ) return cleaned_data
補充知識:django中關於表單自定義驗證器和常用驗證器
常用驗證器:
在驗證某個欄位的時候,可以傳遞一個 validators 引數用來指定驗證器,進一步對資料進行過濾。驗證器有很多,但是很多驗證器我們其實已經通過這個 Field 或者一些引數就可以指定了。比如 EmailValidator ,我們可以通過 EmailField 來指定,比如 MaxValueValidator ,我們可以通過 max_value 引數來指定。
以下是一些常用的驗證器:
1. MaxValueValidator :驗證最大值。
2. MinValueValidator :驗證最小值。
3. MinLengthValidator :驗證最小長度。
4. MaxLengthValidator :驗證最大長度。
5. EmailValidator :驗證是否是郵箱格式。
6. URLValidator :驗證是否是 URL 格式。
7. RegexValidator :如果還需要更加複雜的驗證,那麼我們可以通過正則表示式的驗證
器: RegexValidator 。比如現在要驗證手機號碼是否合格,那麼我們可以通過以下程式碼實
現:
class MyForm(forms.Form):
telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message='請輸入正確格式的手機號碼!')])
自定義驗證:
有時候對一個欄位驗證,不是一個長度,一個正則表示式能夠寫清楚的,還需要一些其他複雜的邏輯,那麼我們可以對某個欄位,進行自定義的驗證。比如在註冊的表單驗證中,我們想要驗證手機號碼是否已經被註冊過了,那麼這時候就需要在資料庫中進行判斷才知道。對某個欄位進行自定義的驗證方式是,定義一個方法,這個方法的名字定義規則是: clean_fieldname 。如果驗證失敗,那麼就丟擲一個驗證錯誤。比如要驗證使用者表中手機號碼之前是否在資料庫中存在,那麼可以通過以下程式碼實現:
class MyForm(forms.Form): telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message='請輸入正確格式的手機號碼!')]) def clean_telephone(self): telephone = self.cleaned_data.get('telephone') exists = User.objects.filter(telephone=telephone).exists() if exists: raise forms.ValidationError("手機號碼已經存在!") else: return telephone
以上是對某個欄位進行驗證,如果驗證資料的時候,需要針對多個欄位進行驗證,那麼可以重寫 clean 方法。比如要在註冊的時候,要判斷提交的兩個密碼是否相等。那麼可以使用以下程式碼來完成:
class MyForm(forms.Form): telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message='請輸入正確格式的手機號碼!')]) pwd1 = forms.CharField(max_length=12) pwd2 = forms.CharField(max_length=12) def clean(self): cleaned_data = super().clean() pwd1 = cleaned_data.get('pwd1') pwd2 = cleaned_data.get('pwd2') if pwd1 != pwd2: raise forms.ValidationError('兩個密碼不一致!')
提取錯誤資訊:
如果驗證失敗了,那麼有一些錯誤資訊是我們需要傳給前端的。這時候我們可以通過以下屬性來獲取:
1. form.errors :這個屬性獲取的錯誤資訊是一個包含了 html 標籤的錯誤資訊。
2. form.errors.get_json_data() :這個方法獲取到的是一個字典型別的錯誤資訊。將某個欄位的名字作為 key ,錯誤資訊作為值的一個字典。
3. form.as_json() :這個方法是將 form.get_json_data() 返回的字典 dump 成 json 格式的字串,方便進行傳輸。
4. 上述方法獲取的欄位的錯誤值,都是一個比較複雜的資料。比如以下:
{'username': [{'message': 'Enter a valid URL.','code': 'invalid'},{'message': 'Ensurethis value has at most 4 characters (it has 22).','code': 'max_length'}]}
那麼如果我只想把錯誤資訊放在一個列表中,而不要再放在一個字典中。這時候我們可以定義一個方法,把這個資料重新整理一份。例項程式碼如下:
class MyForm(forms.Form): username = forms.URLField(max_length=4) def get_errors(self): errors = self.errors.get_json_data() new_errors = {} for key,message_dicts in errors.items(): messages = [] for message in message_dicts: messages.append(message['message']) new_errors[key] = messages return new_errors
這樣就可以把某個欄位所有的錯誤資訊直接放在這個列表中。
以上這篇Django def clean()函式對錶單中的資料進行驗證操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。