Django之Form表單驗證

經常使用的Field

使用Field能夠是對數據驗證的第一步.你期待對上傳上來的數據爲何類型就使用什麼類型的Fieldhtml

公共參數:前端

  lable: 設置前端label中的字符串正則表達式

  widget: 設置input中的屬性數據庫

  error_messages: 自定義錯誤字段的提示信息django

from django import forms from django.forms import widgets from app01 import models class MyForm(forms.Form): username = forms.CharField(max_length=8, min_length=3, label='用戶名', error_messages={ 'required': '用戶名不能爲空', 'max_length': '用戶名最大爲8位', 'min_length': '用戶名最小爲3位' }, widget=widgets.TextInput(attrs={'class': 'form-control'}))

TextInput爲input類型其餘有:  PasswordInput   EmailInput  CheckBoxInput 等等json

 

CharField後端

用來接收文本app

參數:函數

  max_length: 最大長度ui

  min_length: 最小長度

  require: 這個字段是不是必須的.默認是必須的

  error_messages: 在某個條件驗證失敗的時候,給出錯誤信息 

 

EmailField

用來接收郵件,會自動驗證郵件是否合法

錯誤信息的key: required   invalid

 

FloatField

用來接收浮點類型,而且若是驗證經過後,會將這個字段的值轉換成浮點類型

參數:
  max_value:  最大的值

  min_value: 最小的值

錯誤信息的key: required   invalid   max_value   min_value

 

IntegerField

用來接收整形,而且驗證經過以後,會將這個字段的值轉換成整形

參數:

  max_value: 最大的值

  min_value: 最小的值

錯誤信息的key: required   invalid   max_value   min_value

 

URLField

用來接收url格式的字符串

錯誤信息:  required  invalid 

 

經常使用驗證器:

在驗證某個字段的時候,能夠傳遞一個validators參數用來指定驗證器,進一步對數據進行過濾. 驗證器有不少,可是不少驗證器咱們其實已經經過這個Field或者一些參數就能夠指定了.好比,EmailValidator, 咱們能夠經過EmailField來指定,好比 MaxValueValidator, 咱們能夠經過max_value參數來指定,如下是一些經常使用的驗證器

1. MaxValueValidator:  驗證最大值

2. MinValueValidator: 驗證最小值

3. MaxLengthValidator: 驗證最大長度

4. MinLengthValidator: 驗證最小長度

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("手機號碼已經存在!") 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): pwd1 = self.cleaned_data.get('pwd1') pwd2 = self.cleaned_data.get('pwd2') if pwd1 != pwd2: self.add_error('pwd2','兩次密碼不正確')
     return self.cleaned_data;

 

提取錯誤信息:

若是驗證失敗了,那麼有一些錯誤信息是咱們須要傳給前端的。這時候咱們能夠經過如下屬性來獲取:

  1. form.errors:這個屬性獲取的錯誤信息是一個包含了html標籤的錯誤信息。
  2. form.errors.get_json_data():這個方法獲取到的是一個字典類型的錯誤信息。將某個字段的名字做爲key,錯誤信息做爲值的一個字典。
  3. form.as_json():這個方法是將form.get_json_data()返回的字典dumpjson格式的字符串,方便進行傳輸。
  4. 上述方法獲取的字段的錯誤值,都是一個比較複雜的數據。好比如下:
{'username': [{'message': 'Enter a valid URL.', 'code': 'invalid'}, {'message': 'Ensure this 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

這樣就能夠把某個字段全部的錯誤信息直接放在這個列表中。

提取成功字段

校驗成功可使用form_obj.is_vaild()驗證,所有驗證成功則爲True,不然爲False

校驗成功會將成功的字段添加進cleaned_data中

def edit_password(request): form_obj = EditPasswordForm() if request.method == 'POST': back_dic = {'code': 100, 'msg':''} old_password = request.POST.get('id_old_password') password = request.POST.get('id_password') confirm_password = request.POST.get('id_confirm_password') form_obj = EditPasswordForm({'old_password': old_password,'password':password, 'confirm_password':confirm_password}) if form_obj.is_valid(): print(form_obj.cleaned_data) 輸出爲: {'old_password': '456', 'password': 'a159357', 'confirm_password': 'a159357'}

 

ModelForm:

你們在寫表單的時候,會發現表單中的Field和模型中的Field基本上是如出一轍的,並且表單中須要驗證的數據,也就是咱們模型中須要保存的。那麼這時候咱們就能夠將模型中的字段和表單中的字段進行綁定。
好比如今有個Article的模型。示例代碼以下:

from django.db import models from django.core import validators class Article(models.Model): title = models.CharField(max_length=10,validators=[validators.MinLengthValidator(limit_value=3)]) content = models.TextField() author = models.CharField(max_length=100) category = models.CharField(max_length=100) create_time = models.DateTimeField(auto_now_add=True)

那麼在寫表單的時候,就不須要把Article模型中全部的字段都一個個重複寫一遍了。示例代碼以下:

from django import forms class MyForm(forms.ModelForm): class Meta: model = Article fields = "__all__"

MyForm是繼承自forms.ModelForm,而後在表單中定義了一個Meta類,在Meta類中指定了model=Article,以及fields="__all__",這樣就能夠將Article模型中全部的字段都複製過來,進行驗證。若是隻想針對其中幾個字段進行驗證,那麼能夠給fields指定一個列表,將須要的字段寫進去。好比只想驗證titlecontent,那麼可使用如下代碼實現:

from django import forms class MyForm(forms.ModelForm): class Meta: model = Article fields = ['title','content']

若是要驗證的字段比較多,只是除了少數幾個字段不須要驗證,那麼可使用exclude來代替fields。好比我不想驗證category,那麼示例代碼以下:

class MyForm(forms.ModelForm): class Meta: model = Article exclude = ['category']

自定義錯誤消息:

使用ModelForm,由於字段都不是在表單中定義的,而是在模型中定義的,所以一些錯誤消息沒法在字段中定義。那麼這時候能夠在Meta類中,定義error_messages,而後把相應的錯誤消息寫到裏面去。示例代碼以下:

class MyForm(forms.ModelForm): class Meta: model = Article exclude = ['category'] error_messages ={ 'title':{ 'max_length': '最多不能超過10個字符!', 'min_length': '最少不能少於3個字符!' }, 'content': { 'required': '必須輸入content!', } }

 

save方法:

ModelForm還有save方法,能夠在驗證完成後直接調用save方法,就能夠將這個數據保存到數據庫中了。示例代碼以下:

form = MyForm(request.POST) if form.is_valid(): form.save() return HttpResponse('succes') else: print(form.get_errors()) return HttpResponse('fail')

這個方法必需要在clean沒有問題後才能使用,若是在clean以前使用,會拋出異常。另外,咱們在調用save方法的時候,若是傳入一個commit=False,那麼只會生成這個模型的對象,而不會把這個對象真正的插入到數據庫中。好比表單上驗證的字段沒有包含模型中全部的字段,這時候就能夠先建立對象,再根據填充其餘字段,把全部字段的值都補充完成後,再保存到數據庫中。示例代碼以下:

form = MyForm(request.POST) if form.is_valid(): article = form.save(commit=False) article.category = 'Python' article.save() return HttpResponse('succes') else: print(form.get_errors()) return HttpResponse('fail')

 前端使用

1. 後端先實例化forms對象

form_obj = MyForm()

2. 前端的三種渲染方式

1. {{ form_obj.as_p }} 2. {{ form_obj.name.label }}{{ form_obj.name }} 3. {% for foo in form_obj %} <p>{{ foo.label }} {{ foo }} </p> {% endfor %}

3. form前端經常使用屬性

name: 將該字段對應的input框渲染到頁面 label: 渲染設置的字段名, 若是沒設置則該字段名首字母大寫 auto_id: 字段中對應的屬性id的值 與 label中的for一塊兒使用

示例

         {% for foo in form_obj %} <div class="form-group">
                        <label for="{{ foo.auto_id }}" >{{ foo.label }}</label> {{ foo }} <span class="error pull-right" style="color: red"></span>
                    </div> {% endfor %}

後端代碼示例

def edit_password(request): form_obj = EditPasswordForm() if request.method == 'POST': back_dic = {'code': 100, 'msg':''} old_password = request.POST.get('id_old_password') password = request.POST.get('id_password') confirm_password = request.POST.get('id_confirm_password') form_obj = EditPasswordForm({'old_password': old_password,'password':password, 'confirm_password':confirm_password}) if form_obj.is_valid(): if request.user.check_password(old_password) and password == confirm_password: request.user.set_password(confirm_password) request.user.save() back_dic['url'] = '/login/' auth.logout(request) else: back_dic['code'] = 101 back_dic['msg'] = {'old_password':['原密碼錯誤']} else: back_dic['code'] = 101 back_dic['msg'] = form_obj.errors return JsonResponse(back_dic) return render(request,'edit_password.html', locals())

 4. 設置標籤樣式

使用django.forms.widgets

from django import forms from django.forms import widgets password = forms.CharField(max_length=8,min_length=3,error_messages={  'max_length': '密碼最長8位', 'required': '密碼不能爲空', 'min_length':'密碼最少3位' },widget=widgets.PasswordInput(attrs={'class':'c1 form-control'})) hobby = forms.ChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),label="愛好", initial=3, widget=forms.widgets.Select() ) hobby1 = forms.MultipleChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),label="愛好", initial=[1, 3],widget=forms.widgets.SelectMultiple() ) keep = forms.ChoiceField( label="是否記住密碼",initial="checked", widget=forms.widgets.CheckboxInput()) 
相關文章
相關標籤/搜索