咱們在HTML頁面中利用form表單向後端提交數據時,都會寫一些獲取用戶輸入的標籤而且用form標籤把它們包起來。html
與此同時咱們在好多場景下都須要對用戶的輸入作校驗,好比校驗用戶是否輸入,輸入的長度和格式等正確與否。若是用戶輸入的內容有錯誤就須要在頁面上相應的位置顯示對應的錯誤信息.。前端
Django form組件就實現了上面所述的功能。git
總結一下,其實form組件的主要功能以下:正則表達式
思路:數據庫
1.手寫獲取用戶輸入的前端頁面代碼 渲染頁面
2.後端獲取用戶數據並作合法性校驗 校驗數據
3.將校驗以後的結果渲染到前端頁面 展現信息django
def register(request): error_dict = {'username':'','password':''} if request.method =='POST': username = request.POST.get("username") password = request.POST.get('password') if "Jin瓶梅" in username: #提示報錯信息 error_dict['username'] = '不符合核心價值觀' if not password: #提示報錯信息 error_dict['password'] = '密碼不能爲空' return render(request,'register.html',locals())
<body> <form action="" method="post"> <p>用戶名: <input type="text" name="username"> <span style="color:red">{{ error_dict.username }}</span> </p> <p>密碼: <input type="text" name="password"> <span style="color:red">{{ error_dict.password }}</span> </p> <input type="submit"> </form> </body>
views.py後端
#須要先寫一個類 class MyRegForm(forms.Form): #用戶名最少3位最多8位 username = forms.CharField(max_length=8,min_length=3) password = forms.CharField(max_length=8,min_length=3) #email字段必須填寫符合郵箱格式的數據 email = forms.EmailField()
# 1.傳入待校驗的數據 用本身寫的類 傳入字典格式的待校驗的數據 form_obj = views.MyRegForm({'username': 'hank', 'password': 123, 'email': '123456'}) # 2.判斷數據是否符合校驗規則 form_obj.is_valid() #False 該方法只有在全部的數據所有符合校驗規則纔會返回True # 3.如何獲取校驗以後經過的數據 form_obj.cleaned_data #{'username': 'hank', 'password': '123'} # 4.如何獲取校驗失敗及失敗的緣由 form_obj.errors #{'email': ['Enter a valid email address.']}
注意:forms組件默認全部的字段都必須傳值。瀏覽器
傳少了確定不行,而傳多了則沒有任何關係,只校驗類裏面寫的字段 多傳的直接忽略了。以下圖所示ide
forms組件只幫你渲染獲取用戶輸入(輸入 選擇 下拉 文件)的標籤 不渲染按鈕和form表單標籤
渲染出來的每個input提示信息都是類中字段首字母大寫函數
def reg(request): # 1.先生成一個空的類對象 form_obj = MyRegForm() # 2 獲取用戶數據並交給forms組件校驗 if request.method == 'POST': form_obj = MyRegForm(request.POST) # 3 獲取校驗結果 if form_obj.is_valid(): return HttpResponse('數據沒問題') # return render(request, 'reg.html', locals()) else: # 4 獲取校驗失敗的字段和提示信息 print(form_obj.errors) # 5.直接將該對象傳給前端頁面 return render(request,'reg.html',locals())
<body> <p>第一種渲染方式: 多個p標籤 本地測試方便 封裝程度過高 不便於擴展</p> {{ form_obj.as_p }} {#{{ form_obj.as_ul }}#} {#{{ form_obj.as_table }}#} <p>第二種渲染方式: 擴展性較高 書寫較爲繁瑣</p> <lable for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</lable> {{ form_obj.username }} {{ form_obj.password.label }}{{ form_obj.password }} {{ form_obj.email.label }}{{ form_obj.email }} <p>第三種渲染方式 (推薦使用)</p> {% for form in form_obj %} {{ form.label }}{{ form }} {% endfor %} </body>
效果展現:
def reg(request): # 1.先生成一個空的類對象 form_obj = MyRegForm() # 2 獲取用戶數據並交給forms組件校驗 if request.method == 'POST': form_obj = MyRegForm(request.POST) # 3 獲取校驗結果 if form_obj.is_valid(): return HttpResponse('數據沒問題') # return render(request, 'reg.html', locals()) else: # 4 獲取校驗失敗的字段和提示信息 print(form_obj.errors) # 5.直接將該對象傳給前端頁面 return render(request,'reg.html',locals())
<p>第三種渲染方式 (推薦使用)</p> <form action="" method="post" novalidate> {% for form in form_obj %} <p> {{ form.label }}{{ form }} <span>{{ form_obj.errors.0 }}</span> </p> {% endfor %} <input type="submit"> </form>
注意:
1.數據校驗一個先後端都得有,可是前端的校驗弱不由風 無關緊要;然後端的校驗則必須很是全面
2.form表單取消前端瀏覽器自動校驗功能 :
<form action="" method="post" novalidate>
label #input框的提示信息 error_messages #自定義報錯的提示信息 required #設置字段是否容許爲空 initial #設置默認值 widget #控制type類型及屬性 widget=forms.widgets.TextInput(attrs={'class':'form-control c1'}) widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
正則校驗:
from django.core.validators import RegexValidator class MyForm(forms.Form): user = forms.CharField( validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')], )
單選Select:
class LoginForm(forms.Form): ... hobby = forms.ChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ), label="愛好", initial=3, widget=forms.widgets.Select() )
多選Select:
class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ), label="愛好", initial=[1, 3], widget=forms.widgets.SelectMultiple() )
單選Checkbox
class LoginForm(forms.Form): ... keep = forms.ChoiceField( label="是否記住密碼", initial="checked", widget=forms.widgets.CheckboxInput() )
多選Checkbox
class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),), label="愛好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() )
補充:
Field required=True, 是否容許爲空 widget=None, HTML插件 label=None, 用於生成Label標籤或顯示內容 initial=None, 初始值 help_text='', 幫助信息(在標籤旁邊顯示) error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} validators=[], 自定義驗證規則 localize=False, 是否支持本地化 disabled=False, 是否能夠編輯 label_suffix=None Label內容後綴 CharField(Field) max_length=None, 最大長度 min_length=None, 最小長度 strip=True 是否移除用戶輸入空白 IntegerField(Field) max_value=None, 最大值 min_value=None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value=None, 最大值 min_value=None, 最小值 max_digits=None, 總長度 decimal_places=None, 小數位長度 BaseTemporalField(Field) input_formats=None 時間格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 時間間隔:%d %H:%M:%S.%f ... RegexField(CharField) regex, 自定製正則表達式 max_length=None, 最大長度 min_length=None, 最小長度 error_message=None, 忽略,錯誤信息使用 error_messages={'invalid': '...'} EmailField(CharField) ... FileField(Field) allow_empty_file=False 是否容許空文件 ImageField(FileField) ... 注:須要PIL模塊,pip3 install Pillow 以上兩個字典使用時,須要注意兩點: - form表單中 enctype="multipart/form-data" - view函數中 obj = MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices=(), 選項,如:choices = ((0,'上海'),(1,'北京'),) required=True, 是否必填 widget=None, 插件,默認select插件 label=None, Label內容 initial=None, 初始值 help_text='', 幫助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, # 查詢數據庫中的數據 empty_label="---------", # 默認空顯示內容 to_field_name=None, # HTML中value的值對應的字段 limit_choices_to=None # ModelForm中對queryset二次篩選 ModelMultipleChoiceField(ModelChoiceField) ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce = lambda val: val 對選中的值進行一次轉換 empty_value= '' 空值的默認值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 對選中的每個值進行一次轉換 empty_value= '' 空值的默認值 ComboField(Field) fields=() 使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件選項,目錄下文件顯示在頁面中 path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 required=True, widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用 SlugField(CharField) 數字,字母,下劃線,減號(連字符) ... UUIDField(CharField) uuid類型 Django Form內置字段
class MyRegForm(forms.Form): #用戶名最少3位最多8位 username = forms.CharField(max_length=8,min_length=3,label='用戶名', error_messages={ 'max_length':'用戶名最長8位', 'min_length':'用戶名最短3位', 'required':'用戶名不能位爲空' }, initial='hank') password = forms.CharField(max_length=8,min_length=3,label='密碼') confirm_password = forms.CharField(max_length=8,min_length=3,label='確認密碼') #email字段必須填寫符合郵箱格式的數據 email = forms.EmailField(label='郵箱',error_messages={ 'required':'郵箱必填', 'invalid':'郵箱格式不正確' }) # 全局鉤子 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 clean_username(self): #校驗用戶名中不能包含666 username =self.cleaned_data.get('username') if '666' in username: self.add_error('username','有666是就行的') return self.cleaned_data
若是想同時操做多個字段的數據,就用全局鉤子若是想操做單個字段的數據,就用局部鉤子