這裏拋出一個問題css
校驗:html
1.註冊功能
用戶輸入的用戶名中 不能包含‘xxx’
若是包含了 就提示用戶 輸入的內容不符合社會主義核心價值觀
用戶輸入的密碼 不能小於三位
若是密碼少於三位 提示用戶 密碼過短了
校驗數據一般是先後端都有校驗
可是前端校驗無關緊要 哪怕再牛逼
後端也必需要有校驗 反正一句話 前端可有不校驗 後端必須校驗!!前端
(深深的體現了開發鄙視鏈)jquery
這個時候用form組件就能夠自動幫咱們完成三個功能:django
1.搭建前端頁面(渲染頁面)
2.獲取前端用戶提交的數據校驗(校驗數據)
3.對數據的校驗的結果 展現到前端頁面給用戶查看 (展現錯誤信息)bootstrap
咱們首先須要本身寫一個繼承了Form的類。後端
from django import forms class MyRegForm(forms.Form): username = forms.CharField(min_length=3,max_length=8) password = forms.CharField(min_length=3,max_length=8) email = forms.EmailField()
如何校驗數據?瀏覽器
from app01 import views # 1.給自定義的類傳一個字典 obj = views.MyRegForm({'username':'jason','password':'12','email':'123'}) # 2.判斷數據是否所有合法 obj.is_valid() # 只有數據所有符合要求才會是True Out[4]: False # 3.查看符合校驗規則的數據 obj.cleaned_data Out[5]: {'username': 'jason'} # 4.查看不符合條件的數據以及不符合的緣由是什麼 obj.errors Out[6]: { 'password': ['Ensure this value has at least 3 characters (it has 2).'], 'email': ['Enter a valid email address.'] } # 5.校驗數據的時候 默認狀況下類裏面全部的字段都必須傳值 obj = views.MyRegForm({'username':'jason','password':'123'}) obj.is_valid() Out[12]: False obj.errors Out[13]: {'email': ['This field is required.']} # 6.默認狀況下能夠多傳 可是絕對不能少傳 obj = views.MyRegForm({'username':'jason','password':'1233','email':'123@qq.com','xxx':'ooo'}) obj.is_valid() Out[15]: True
這裏要介紹一下在pycharm裏的一個功能,下面的Python Console,他會自動幫咱們搭配好django環境,在這裏對咱們的輸入返回結果,上面代碼中的 Out就是返回結果。app
上述代碼中,咱們給本身寫的form類裏面傳了一個字典,能看到的是隻有 username 是符合要求的,其中各類 form 自帶的方法都已經作出瞭解釋,就不一一贅述了。函數
既然咱們已經得到告終果,那麼要怎麼樣才能在前端頁面上展現出來呢?
首先要注意一點 :forms組件只會幫你渲染獲取用戶輸入(輸入,選擇,下拉框...)的標籤 提交按鈕須要你本身手動寫
第一種:
{{ form_obj.as_p }} //as_p 是會把你的結果以p標籤的形式展現 {{ form_obj.as_ul}}//as_p 是會把你的結果以ul標籤的形式展現
這種方式的封裝程度擡高了,標籤的樣式以及參數不方便調整,可擴展性差,不推薦使用
第二種:
<p> {{ form_obj.username.label }}{{ form_obj.username }} </p> <p> {{ form_obj.password.label }}{{ form_obj.password }} </p> <p> {{ form_obj.email.label }}{{ form_obj.email }} </p>
這種方式擴展性高,可是須要手寫大量代碼,因此也不推薦。
第三種:(推薦)
{% for foo in form_obj %} <p>{{ foo.label }}{{ foo }}</p> {% endfor %}
代碼量和擴展性都很高(推薦使用)
首先咱們要把前端對咱們作的校驗取消掉,也就是瀏覽器,他會自動幫你作校驗,怎麼說呢,就是,若是你設置了最長的用戶名爲8位,這時候你是不能輸入超越8位的字符的,會直接卡在那裏,因此咱們要取消前端幫咱們作的校驗,只須要在form表單中添加一個參數novalida 就能夠了。
<form action="" method="post" novalidate> 展現錯誤信息 用對象點errors.0 <form action="" method="post" novalidate> {% for foo in form_obj %} <p> {{ foo.label }}:{{ foo }} <span style="color: red">{{ foo.errors.0 }}</span> </p> {% endfor %} <input type="submit"> </form>
這個時候把咱們的代碼寫上去,來解上面的題:
後端代碼:
from django import forms from django.forms import widgets class MyRegForm(forms.Form): username = forms.CharField(min_length=3,max_length=8,label='用戶名', #error_messages的做用是不符合條件的時候對應的錯誤信息 error_messages={ 'min_length':'用戶名最短爲三位', 'max_length':'用戶名最短爲三位', 'required':'用戶名不能爲空', },initial='我是初始值',required=False, #widget的做用是能夠給標籤加上樣式 widget=widgets.TextInput(attrs={'class':'form-control others'}) ) password = forms.CharField(min_length=3,max_length=8,label='密碼', error_messages={ 'min_length': '密碼最短爲三位', 'max_length': '密碼最短爲三位', 'required': '密碼不能爲空', },widget=widgets.PasswordInput()) confirm_password = forms.CharField(min_length=3, max_length=8, label='確認密碼', error_messages={ 'min_length': '確認密碼最短三位', 'max_length': '確認密碼最長八位', 'required': '確認密碼不能爲空' }) email = forms.EmailField(label='郵箱',error_messages={ 'required':'郵箱不能爲空', 'invalid':'郵箱格式不正確' },required=False,widget=widgets.EmailInput(attrs={'class':'form-control'})) def clean_username(self): username = self.cleaned_data.get('username') if 'xxx' in username: self.add_error('username','不能') return username def clean(self): password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password','兩次密碼不一致') return self.cleaned_data def formmm(request): form_obj = MyRegForm() if request.method == 'POST': #這個對象只能穿字典過去,而咱們的request.POST正好是一個字典,因此直接傳進 去就行了。 form_obj = MyRegForm(request.POST) if form_obj.is_valid(): return HttpResponse('數據沒問題') return render(request,'formmm.html',locals())
前端代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script> </head> <body> <form action="" method="post" novalidate> {% for foo in form_obj %} <p> {{ foo.label }}:{{ foo }} <span style="color: red">{{ foo.errors.0 }}</span> </p> {% endfor %} <input type="submit"> </form> </body> </html>
鉤子函數就是 針對字段 你還能夠作額外的校驗。
鉤子有分紅局部鉤子和全局鉤子
咱們以前的用戶名中不能有 ‘xxx’ 就是用鉤子函數實現的,把它拉過來看一下。
# 當你須要對某一個字段數據進行額外的一些列校驗 你能夠考慮使用鉤子函數 # 針對單個字段的 使用局部鉤子 def clean_username(self): #對象裏有cleaned_data這個屬性,拿到了裏面的username來看一下 username = self.cleaned_data.get('username') if 'xxx' in username: #不符合的話就丟進 error 裏面去 self.add_error('username','不能') return username #鉤子勾過來了,固然要還回去了 # 針對多個字段的校驗 使用全局鉤子 eg:校驗兩次密碼是否一致 def clean(self): password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if not password == confirm_password: self.add_error('confirm_password','兩次密碼不一致') return self.cleaned_data #這裏索性就把所有都還回去了。
如何改變input框的type屬性值 widget= widgets.TextInput() widget=widgets.PasswordInput() 如何讓forms組件渲染出來的input框有form-control類屬性 widget= widgets.TextInput(attrs={'class':'form-control others'}) # 若是有多個類屬性 空格隔開 widget=widgets.PasswordInput(attrs={'class':'form-control others'})
每一個字段 還支持正則校驗
from django import forms
from django.forms import Form
from django.core.validators import RegexValidator
class MyForm(Form):
user = forms.CharField(
validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')],
)
gender = forms.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性別", initial=3, widget=widgets.RadioSelect() ) hobby = forms.ChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),), label="愛好", initial=3, widget=widgets.Select() ) hobby1 = forms.MultipleChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),), label="愛好", initial=[1, 3], widget=widgets.SelectMultiple() ) keep = forms.ChoiceField( label="是否記住密碼", initial="checked", widget=forms.widgets.CheckboxInput() ) hobby2 = forms.MultipleChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),), label="愛好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() )