Django中Form元件
阿新 • • 發佈:2022-03-14
目錄
Forms元件
1.基本使用
# 在views.py中 from django import forms class MyForm(forms.Form): # username字串型別最小3位最大8位 username = forms.CharField(min_length=3, max_length=8, label='使用者名稱') # password字串型別最小3位最大8位 password = forms.CharField(min_length=3, max_length=8, label='密碼') # email欄位必須符合郵箱格式 [email protected] email = forms.EmailField(label='郵箱') ''' label屬性預設展示的是類中定義欄位首字母大寫的形式 也可以自己修改 直接給欄位物件加label屬性即可 '''
2.校驗資料
在pycharm中的下方也可以測試資料
from app01 import views # 1 將帶校驗的資料組織成字典的形式傳入即可 form_obj = views.MyForm({'username':'jason','password':'123','email':'123'}) # 2 判斷資料是否合法 注意該方法只有在所有的資料全部合法的情況下才會返回True form_obj.is_valid() False # 3 檢視所有校驗通過的資料 form_obj.cleaned_data {'username': 'jason', 'password': '123'} # 4 檢視所有不符合校驗規則以及不符合的原因 form_obj.errors { 'email': ['Enter a valid email address.'] } # 5 校驗資料只校驗類中出現的欄位 多傳不影響 多傳的欄位直接忽略 form_obj = views.MyForm({'username':'jason','password':'123','email':'[email protected]','hobby':'study'}) form_obj.is_valid() True # 6 校驗資料 預設情況下 類裡面所有的欄位都必須傳值 form_obj = views.MyForm({'username':'jason','password':'123'}) form_obj.is_valid() False """ 也就意味著校驗資料的時候 預設情況下資料可以多傳但是絕不可能少傳 """
3.渲染標籤
form元件只會自動幫你渲染獲取使用者輸入的標籤(input select radio checkbox) 不能幫你渲染提交按鈕
後端
def index(request):
# 1 生成一個空物件
forms_obj = MyForm()
# 2 直接將該空物件傳遞給html頁面
return render(request, 'index.html', locals())
前端
<form action="" method="post"> <p>第三種渲染方式(推薦使用)</p> {% for form in forms_obj %} <p>{{ form.label }}:{{ form }}</p> {% endfor %}
"""
label屬性預設展示的是類中定義的欄位首字母大寫的形式
也可以自己修改 直接給欄位物件加label屬性即可
username = forms.CharField(min_length=3,max_length=8,label='使用者名稱')
"""
展示錯誤提示資訊
瀏覽器會自動幫你校驗資料 但是前端的校驗弱不禁風 所以這裡我們去掉瀏覽器的自動校驗
<form action="" method="post" novalidate> 加個novalidate就行了
後端
def index(request):
# 1 先產生一個空物件
form_obj = MyForm()
if request.method == 'POST':
# 獲取使用者資料並且校驗
"""
1.資料獲取繁瑣
2.校驗資料需要構造成字典的格式傳入才行
ps:但是request.POST可以看成就是一個字典
"""
# 3.校驗資料
form_obj = MyForm(request.POST) #
# 4.判斷資料是否合法
if form_obj.is_valid():
# 5.如果合法 操作資料庫儲存資料
return HttpResponse('OK')
# 5.不合法 有錯誤
# 2 直接將該空物件傳遞給html頁面
return render(request,'index.html',locals())
必備的條件
1.get請求和post請求傳給html頁面物件變數名必須一樣(上面的form_obj)
2.forms元件當你的資料不合法的情況下,會儲存你上次的資料,讓你基於之前的
結果進行修改,更加的人性化
前端
<form action="" method="post" novalidate>
<p>第三種渲染方式(推薦使用)</p>
{% for form in forms_obj %}
<p>{{ form.label }}:{{ form }}
<span style="color: red">{{ form.errors.0 }}</span> # 這裡的errors後必須加0,不然會換行
</p>
{% endfor %}
<input type="submit">
</form>
修改錯誤資訊
class MyForm(forms.Form):
# username字串型別最小3位最大8位
username = forms.CharField(min_length=3,max_length=8,label='使用者名稱',
error_messages={
'min_length':'使用者名稱最少3位',
'max_length':'使用者名稱最大8位',
'required':"使用者名稱不能為空"
}
)
# password字串型別最小3位最大8位
password = forms.CharField(min_length=3,max_length=8,label='密碼',
error_messages={
'min_length': '密碼最少3位',
'max_length': '密碼最大8位',
'required': "密碼不能為空"
}
)
# email欄位必須符合郵箱格式 [email protected]
email = forms.EmailField(label='郵箱',
error_messages={
'invalid':'郵箱格式不正確',
'required': "郵箱不能為空"
}
)
鉤子函式(HOOK)
鉤子函式再forms元件中就類似於第二道關卡,能夠讓我們自定義校驗規則(比如正則)
型別 | 使用規則 |
---|---|
區域性鉤子 | 當你需要給單個欄位增加校驗規則的時候可以使用 |
全域性鉤子 | 當你需要給多個欄位增加校驗規則的時候可以使用 |
鉤子函式是寫在類裡面的
# 區域性鉤子
def clean_username(self):
# 獲取到使用者名稱
username = self.cleaned_data.get('username')
# 判斷是否合法
if '666' in username:
# 前端展示錯誤資訊(比如這裡可以寫正則來校驗)
self.add_error('username', '不要給我加666!!!')
# 將鉤子函式勾取出來的資料再放回去
return username
# 全域性鉤子
def clean(self):
# 獲取資料
password = self.cleaned_data.get('password')
re_password = self.cleaned_data.get('re_password')
if password != re_password:
self.add_error('re_password', '兩次密碼不一致.')
# 將鉤子函式勾取出來的資料再放回去
return self.cleaned_data
forms元件其他引數及補充知識點
label 欄位名
error_messages 自定義報錯資訊
initial 預設值
required 控制欄位是否必填
給input框新增樣式和屬性值
"""
1.欄位沒有樣式
2.針對不同型別的input如何修改
text
password
date
radio
checkbox
...
"""
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2','username': 'jason'})
# 多個屬性值的話 直接空格隔開即可
部落格最後還有其他type型別渲染
第一道關卡正則校驗
# 先匯入模組
from django.core.validators import RegexValidator
phone = forms.CharField(
validators=[
RegexValidator(r'^[0-9]+$', '請輸入數字'),
RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')
],
)
其他型別渲染
# radio
gender = forms.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性別",
initial=3,
widget=forms.widgets.RadioSelect()
)
# select
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()
)
# 單選checkbox
keep = forms.ChoiceField(
label="是否記住密碼",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
# 多選checkbox
hobby2 = forms.MultipleChoiceField(
choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
label="愛好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
form元件原始碼
切入點:
form_obj.is_valid()
"""
切入點:
form_obj.is_valid()
"""
def is_valid(self):
"""
Returns True if the form has no errors. Otherwise, False. If errors are
being ignored, returns False.
"""
return self.is_bound and not self.errors
# 如果is_valid要返回True的話 那麼self.is_bound要為True self.errors要為Flase
self.is_bound = data is not None or files is not None # 只要你傳值了肯定為True
@property
def errors(self):
"Returns an ErrorDict for the data provided for the form"
if self._errors is None:
self.full_clean()
return self._errors
# forms元件所有的功能基本都出自於該方法
def full_clean(self):
self._clean_fields() # 校驗欄位 + 區域性鉤子
self._clean_form() # 全域性鉤子
self._post_clean()