一、form介紹
我們之前在HTML頁面中利用form表單向后端提交數據時,都會寫一些獲取用戶輸入的標簽并且用form標簽把它們包起來。
與此同時我們在好多場景下都需要對用戶的輸入做校驗,比如校驗用戶是否輸入,輸入的長度和格式等正不正確。如果用戶輸入的內容有錯誤就需要在頁面上相應的位置顯示對應的錯誤信息.。
Django form組件就實現了上面所述的功能。
總結一下,其實form組件的主要功能如下:
- 生成頁面可用的HTML標簽
- 對用戶提交的數據進行校驗
- 保留上次輸入內容
二、普通方式手寫注冊功能
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
# 注冊 def register(request): error_msg = "" if request.method = = "POST" : username = request.POST.get( "name" ) pwd = request.POST.get( "pwd" ) # 對注冊信息做校驗 if len (username) < 6 : # 用戶長度小于6位 error_msg = "用戶名長度不能小于6位" else : # 將用戶名和密碼存到數據庫 return HttpResponse( "注冊成功" ) return render(request, "register.html" , { "error_msg" : error_msg}) |
register.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >注冊頁面</ title > </ head > < body > < form action = "/reg/" method = "post" > {% csrf_token %} < p > 用戶名: < input type = "text" name = "name" > </ p > < p > 密碼: < input type = "password" name = "pwd" > </ p > < p > < input type = "submit" value = "注冊" > < p style = "color: red" >{{ error_msg }}</ p > </ p > </ form > </ body > </ html > |
三、使用form組件實現注冊功能
views.py
先定義好一個RegForm類:
1
2
3
4
5
6
|
from django import forms # 按照Django form組件的要求自己寫一個類 class RegForm(forms.Form): name = forms.CharField(label = "用戶名" ) pwd = forms.CharField(label = "密碼" ) |
再寫一個視圖函數:
1
2
3
4
5
6
7
8
9
10
|
# 使用form組件實現注冊方式 def register2(request): form_obj = RegForm() if request.method = = "POST" : # 實例化form對象的時候,把post提交過來的數據直接傳進去 form_obj = RegForm(request.POST) # 調用form_obj校驗數據的方法 if form_obj.is_valid(): return HttpResponse( "注冊成功" ) return render(request, "register2.html" , { "form_obj" : form_obj}) |
register2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >注冊2</ title > </ head > < body > < form action = "/reg2/" method = "post" novalidate autocomplete = "off" > {% csrf_token %} < div > < label for = "{{ form_obj.name.id_for_label }}" >{{ form_obj.name.label }}</ label > {{ form_obj.name }} {{ form_obj.name.errors.0 }} </ div > < div > < label for = "{{ form_obj.pwd.id_for_label }}" >{{ form_obj.pwd.label }}</ label > {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }} </ div > < div > < input type = "submit" class = "btn btn-success" value = "注冊" > </ div > </ form > </ body > </ html > |
看網頁效果發現 也驗證了form的功能:
- 前端頁面是form類的對象生成的 -->生成HTML標簽功能
- 當用戶名和密碼輸入為空或輸錯之后 頁面都會提示 -->用戶提交校驗功能
- 當用戶輸錯之后 再次輸入 上次的內容還保留在input框 -->保留上次輸入內容
四、pycharm的專屬測試環境
1.使用方法
1.導入要測試的py文件
2.生成一個對象
2.本地校驗測試的一些參數
1
2
3
4
5
|
from_obj.is_valid() / / 判斷校驗是否通過 from_obj.cleaned_data / / 拿到當前符號校驗的數據{ 'username' : '111' , 'password' : '111' } form_obj.errors / / 拿到當前校驗不通過的數據 少傳參數Flalse,多傳Trun。因為少傳了拿不到校驗的數據,多傳了也不會使用。這是字典的形式 |
五、html自動生成input用戶輸入框的三種方式
forms組件只幫你渲染獲取用戶輸入(輸入 選擇 下拉 文件)的標簽 不渲染按鈕和form表單標簽
渲染出來的每一個input提示信息都是類中字段首字母大寫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class MyRegForm(forms.Form): username = forms.CharField(max_length = 8 , min_length = 3 ) # 最長8位,最短3位 password = forms.CharField(max_length = 8 , min_length = 3 ) # 最長8位,最短3位 email = forms.EmailField() # 郵箱驗證 def reg(request): # 1 先生成一個空的類對象 form_obj = MyRegForm() if request.method = = 'POST' : # 3 獲取用戶數據并交給forms組件校驗 request.POST form_obj = MyRegForm(request.POST) # 4 獲取校驗結果 if form_obj.is_valid(): return HttpResponse( '數據沒問題' ) else : # 5 獲取校驗失敗的字段和提示信息 print (form_obj.errors) # 2 直接將該對象傳給前端頁面 return render(request, 'reg.html' , locals ()) |
第一種方式 {{ form_obj.as_p }} (不推薦)
不推薦,封裝程度高,擴展性低。一般測試本地用
1
2
3
4
5
6
|
< body > < p >第一種渲染方式:多個p標簽 本地測試方便 封裝程度太高了 不便于擴展</ p > {{ form_obj.as_p }} {#{{ form_obj.as_ul }}#} {#{{ form_obj.as_table }}#} </ body > |
第二種方式 {{ form_obj.username }} (不推薦)
不推薦,擴展性較高 ,書寫較為繁瑣,每一個input框都需要自己手動寫
1
2
3
4
5
|
< p >第二種渲染方式: 擴展性較高 書寫較為繁瑣</ p > < label for = "{{ form_obj.username.id_for_label }}" >{{ form_obj.username.label }}</ label > {{ form_obj.username }} {{ form_obj.password.label }}{{ form_obj.password }} {{ form_obj.email.label }}{{ form_obj.email }} |
第三種方式 for循環 (推薦)
推薦使用,for循環方式
{{ form.errors.0 }} # 這個是模板語法
1
2
3
4
5
6
7
8
9
10
|
< p >第三種渲染方式 推薦使用</ p > < form action = "" method = "post" novalidate> {% for form in form_obj %} < p > {{ form.label }}{{ form }} < span >{{ form.errors.0 }}</ span > </ p > {% endfor %} < input type = "submit" > </ form > |
六、數據校驗
*******數據校驗一個前后端都得有 但是前端的校驗弱不禁風 可有可無
而后端的校驗則必須非常全面
如何取消瀏覽器自動幫我們校驗的功能?
在form后加參數 no validate,不驗證
1
2
|
form表單取消前端瀏覽器自動校驗功能 < form action = "" method = "post" novalidate> |
常用校驗參數
max_length //允許輸入的最大長度
min_length //最小長度
label input的提示信息,name、password等
error_messages 自定義報錯的提示信息
'max_length':"用戶名最長8位",
'min_length':"用戶名最短3位",
'required':"用戶名不能為空"
required 設置字段是否允許為空
initial 設置默認值
widget 控制type類型及屬性
使用方式
CharField用戶名類型校驗
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.forms import widgets / / 不導入也可以,沒提示 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' : "用戶名不能為空" },required = False ,initial = 'jeff' , / / 為空和默認值 widget = forms.widgets.TextInput(attrs = { 'class' : 'form-control c1 c2' }), / / 設置 input 的 type 屬性為text,及 class 屬性 ) |
password校驗
1
2
3
4
5
6
7
|
class LoginForm(forms.Form): ... pwd = forms.CharField( min_length = 6 , label = "密碼" , widget = forms.widgets.PasswordInput(attrs = { 'class' : 'c1' }, render_value = True ) ) |
郵箱類型校驗
1
2
3
4
5
6
|
class MyRegForm(forms.Form): # email字段必須填寫符合郵箱格式的數據 email = forms.EmailField(label = '郵箱' ,error_messages = { 'required' : '郵箱必填' , 'invalid' : '郵箱格式不正確' }) |
手機號類型校驗
正則匹配
1
2
3
4
5
6
7
8
9
|
from django.core.validators import RegexValidator class MyRegForm(forms.Form): # 手機號 phone = forms.CharField( validators = [ RegexValidator(r '^[0-9]+$' , '請輸入數字' ), RegexValidator(r '^159[0-9]+$' , '數字必須以159開頭' ) ] ) |
性別校驗
1
2
3
4
5
6
|
gender = forms.ChoiceField( choices = (( 1 , "男" ), ( 2 , "女" ), ( 3 , "保密" )), label = "性別" , initial = 3 , widget = forms.widgets.RadioSelect() ) |
愛好單選 select校驗
1
2
3
4
5
6
|
hobby = forms.ChoiceField( choices = (( 1 , "籃球" ), ( 2 , "足球" ), ( 3 , "雙色球" ),), label = "愛好" , initial = 3 , widget = forms.widgets.Select() # 單選 ) |
愛好多選select 校驗1
1
2
3
4
5
6
|
hobby1 = forms.MultipleChoiceField( choices = (( 1 , "籃球" ), ( 2 , "足球" ), ( 3 , "雙色球" ),), label = "愛好" , initial = [ 1 , 3 ], widget = forms.widgets.SelectMultiple() ) |
愛好多選chekbox校驗2
1
2
3
4
5
6
|
hobby2 = forms.MultipleChoiceField( choices = (( 1 , "籃球" ), ( 2 , "足球" ), ( 3 , "雙色球" ),), label = "愛好" , initial = [ 1 , 3 ], widget = forms.widgets.CheckboxSelectMultiple() ) |
是否記住密碼校驗
1
2
3
4
5
|
keep = forms.ChoiceField( label = "是否記住密碼" , initial = "checked" , widget = forms.widgets.CheckboxInput() ) |
七、鉤子函數
# 如果你想同時操作多個字段的數據你就用全局鉤子
# 如果你想操作單個字段的數據 你就用局部鉤子
鉤子勾回來處理完之后,還要還回去的
局部鉤子
校驗用戶名中不能包含666
1
2
3
4
5
6
7
|
# 局部鉤子 # 這里的self是自己類,MyRegForm def clean_username( self ): username = self .cleaned_data.get( 'username' ) if '666' in username: self .add_error( 'username' , '光喊666是不行的' ) return username |
全局鉤子
兩次密碼驗證
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class MyRegForm(forms.Form): # 密碼 password = forms.CharField(max_length = 8 ,min_length = 3 ,label = '密碼' , widget = forms.widgets.PasswordInput(attrs = { 'class' : 'form-control' }) ) # 密碼驗證 re_password = forms.CharField(max_length = 8 ,min_length = 3 ,label = '確認密碼' , widget = forms.widgets.PasswordInput(attrs = { 'class' : 'form-control' }) ) def clean( self ): # 這里的self是自己類,MyRegForm # 校驗密碼和確認密碼是否一致 password = self .cleaned_data.get( 'password' ) re_password = self .cleaned_data.get( 'confirm_password' ) if not password = = re_password: # 展示提示信息 self .add_error( 're_password' , '兩次密碼不一致' ) return self .cleaned_data |
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.cnblogs.com/guyouyin123/p/12189453