使用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;
若是驗證失敗了,那麼有一些錯誤信息是咱們須要傳給前端的。這時候咱們能夠經過如下屬性來獲取:
form.errors
:這個屬性獲取的錯誤信息是一個包含了html
標籤的錯誤信息。form.errors.get_json_data()
:這個方法獲取到的是一個字典類型的錯誤信息。將某個字段的名字做爲key
,錯誤信息做爲值的一個字典。form.as_json()
:這個方法是將form.get_json_data()
返回的字典dump
成json
格式的字符串,方便進行傳輸。{'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'}
你們在寫表單的時候,會發現表單中的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
指定一個列表,將須要的字段寫進去。好比只想驗證title
和content
,那麼可使用如下代碼實現:
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!', } }
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())