form元件簡單使用
阿新 • • 發佈:2020-07-04
Forms元件
我們在很多場景下都需要對使用者的輸入做校驗,比如校驗使用者是否輸入,輸入的長度和格式等是否正確。如果使用者輸入的內容有錯誤就需要在頁面上相應的位置顯示對應的錯誤資訊.。
Django forms元件就實現了上面所述的功能。form元件的主要功能如下:
- 生成頁面可用的HTML標籤
- 對使用者提交的資料進行校驗
- 保留上次輸入內容
基本使用
forms元件在檢視層中使用,通常與模型層結合。最簡單的使用步驟如下
- 匯入forms模組
- 書寫forms類
- 像寫模型層一樣,書寫校驗欄位
- 建立forms物件,字典形式傳入要校驗的資料
- 執行.is_valid() 方法,對資料進行校驗
- 執行其他方法
必須先執行.is_valid(),才可以取cleaned_data和errors
from django import forms # 匯入forms class RegisterForm(forms.Form): # 書寫欄位,和寫models幾乎一樣 account = forms.CharField(min_length=3,max_length=10) # 最小長度3,最大長度10,當然不止這兩個屬性 pwd = forms.CharField(min_length=3,max_length=16) # 在檢視函式中使用forms元件 class Register(View): def get(self, request): return render(request, 'login_forms.html') def post(self, request): user_dic = json.loads(request.body) print(user_dic) # 1. 建立forms物件,傳入校驗資料的字典 form_obj = RegisterForm(user_dic) # 執行is_valid(),校驗資料 print(form_obj.is_valid()) # cleaned_data裡面是通過校驗的資料 print(form_obj.cleaned_data) # errors裡面是沒有通過校驗的資料 print(form_obj.errors) return JsonResponse(user_dic)
# 1 將帶校驗的資料組織成字典的形式傳入即可 form_obj = 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
鉤子函式
經過第一層校驗之後,如果還有別的需求,需要再進行校驗,如:欄位是否已經存在資料庫、兩次輸入密碼是否一致、是否包含敏感詞,可以把這些自定義的校驗寫在鉤子函式裡,再進行第二次校驗
鉤子函式分為區域性鉤子和全域性鉤子,區域性鉤子只校驗單一欄位的資料,全域性鉤子可以校驗所有欄位的資料。
像別的鉤子函式一樣,校驗完之後要return校驗的資料
基本寫法
在上面建立的forms類下寫函式,針對已經建立的欄位,forms會幫你生成方法,pycharm中可以看到程式碼提示
區域性鉤子
def clean_account(self):
# clean_要勾出來的欄位名,表示對這個欄位使用區域性鉤子
account = self.cleaned_data.get('account')
# 因為到達鉤子函式的資料,已經經過了第一層校驗,所以在clean_data裡面用get取值
if '自由' in account:
self.add_error('account','人民不需要自由')
# 自己寫一些邏輯
# add_errror('欄位名','錯誤資訊')
# 可以手動寫錯誤資訊
return account
# 最後要把資料return回去
全域性鉤子
# 固定寫法了
def clean(self):
# clean就是全域性鉤子
pwd = self.cleaned_data.get('pwd')
pwd_confirm = self.cleaned_data.get('pwd_confirm')
# 因為到達鉤子函式的資料,已經經過了第一層校驗,所以在clean_data裡面用get取值
if not pwd == pwd_confirm:
self.add_error('pwd_confirm','兩次輸入密碼不一致')
# 自己寫邏輯
return self.cleaned_data
# 把整個clean_data還回去
內建欄位
看看就好,用的上的複製走
Field
required=True, 是否允許為空,預設不允許為空
widget=None, HTML外掛
label=None, 用於生成Label標籤或顯示內容
initial=None, 初始值,相當於html的value
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
RegexField(CharField)
regex, 自定製正則表示式
max_length=None, 最大長度
min_length=None, 最小長度
error_message=None, 忽略,錯誤資訊使用 error_messages={'invalid': '...'}
渲染標籤
三種渲染方式,但是隻用在前後端不分離的專案上
方式一
from django import forms # 引入forms元件
class UserForm(forms.Form): # 必須繼承forms.Form
# forms.CharField和forms.EmailField會渲染為input標籤
name = forms.CharField(min_length=4) # 預設label是欄位名
pwd = forms.CharField(min_length=4, label="密碼") # 如果需要中文label可以手動設定
r_pwd = forms.CharField(min_length=4, label="確認密碼")
email = forms.EmailField(label="郵箱")
tel = forms.CharField(label="手機")
def reg(request):
form = UserForm()
return render(request, "reg.html", locals())
<h3>form元件渲染方式1</h3>
<form action="" method="post">
{% csrf_token %}
<p>{{ form.name.label }}
{{ form.name }}
</p>
<p>{{ form.pwd.label }}
{{ form.pwd }}
</p>
<p>{{ form.r_pwd.label }}
{{ form.r_pwd }}
</p>
<p>{{ form.email.label }}
{{ form.email }}
</p>
<p>{{ form.tel.label }}
{{ form.tel }}
</p>
<input type="submit">
</form>
方式二
同理方式一,只是用了for迴圈
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
<p>
<label for="">{{ field.label }}</label>
{{ field }}
</p>
{% endfor %}
<input type="submit">
</form>