Django 中的Form表單認證
?
1.1 Form的幾個功能驗證用戶數據(顯示錯誤信息)
初始化頁面顯示內容
HTML Form提交保留上次提交數據
生成HTML標簽
?
1.2 創建表單類Form1. 創建的類必須繼承類:forms.Form
2. 字段名必須與前端表單中的名稱一致(完全一樣)
3. Field類是所有其他類的基類
#!/usr/bin/env python # -*- coding:utf-8 -*- import re from django import forms from django.forms import fields from django.forms import widgets from django.forms import ValidationError def mobile_validate(value): pattern_mobile= '^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$' if not re.match(pattern_mobile, str(value)): raise ValidationError('手機號碼格式錯誤') class UserForm(forms.Form): user = fields.CharField( min_length=4, max_length=12, error_messages={ "required": "用戶名不能為空", "min_length": "長度必須大於4", "max_length": "長度必須小於12" } ) email = fields.EmailField( error_messages={ "required": "郵箱不能為空", "invalid": "格式不合法" } ) wechat = fields.CharField( error_messages={ "required": "微信號還是填上吧!" } ) phone_number = fields.IntegerField( # validators= ['^1[3-8]{2}\d{8}$',], validators= [mobile_validate,], error_messages= { "required": "手機號不能為空", "invalid": "手機號格式有誤" } ) group = fields.ChoiceField( choices=((1,"普通用戶"), (2, "員工用戶"), (3, "黑名單")), error_messages={ "required": "用戶類型必選", "invalid": "只能為選擇框中的內容" } ) partment = fields.ChoiceField( choices=( (0,"人力資源"), (1,"運營維護"), (2,"銷售部"), (3,"開發部"), (4,"項目部"), (5,"後勤管理"), ), error_messages = { "required": "所屬部門必選", "invalid": "必須為提供的選項中的值" } )
?
1.3 視圖函數處理
HTML Form提交保留上次提交數據 及“GET”方式提交生成form內的標簽
實現方式:在"GET"方法內生成一個Form對象 obj = my_form.UserForm() 並傳入前端驗證用戶數據
實現方式:在"POST"方法中創建一個Form對象並把POT提交的數據傳入
obj = my_form.UserForm(request.POST)
if obj.is_valid():
????data = obj.cleaned_data
????#在這兒去數據庫創建數據
????# models.User.objects.create(**data)
????errors = obj.errors.as_data()
def adduser(request): """使用Form表單驗證,新增用戶是否合法""" users = models.User.objects.all() if request.method == "GET": obj = my_form.UserForm() #這兒就能保證上次的錯誤信息還給保留 response = render(request, 'cmdb/usermanage.html',{ "obj": obj, "users": users, }) elif request.method == "POST": obj = my_form.UserForm(request.POST) if obj.is_valid(): data = obj.cleaned_data #在這兒去數據庫創建數據 # models.User.objects.create(**data) else: errors = obj.errors.as_data() response = render(request, 'cmdb/usermanage.html', { "users": users, "obj":obj, }) return response
?
1.4 Form驗證時幾個方法代表的含義
- obj = UserForm(request.POST) #生成一個將要驗證的對象
1. obj.is_valid() #開始驗證, 所有數據驗證過了返回True 有一個錯誤就返回False
2. obj.cleaned_data #所有正確的數據都在這裏面
obj.clearned_data.as_json() #json 格式展示數據
obj.cleaned_data.as_data
3. obj.errors #包含了所有驗證錯誤的方法
?
1.5 前端生成html標簽
obj = my_form.UserForm() #已將標簽打包
response = render(request, ‘url‘,{"obj": obj, "users": users,}) #將數據傳入前端
- obj.user 會自動生成 <input type="text" name="user"/>標簽,同理其他
在此我使用的表格形式
<form action="/cmdb/add-user/" method="POST">
{% csrf_token %}
<tr option="add">
<td>{{ obj.user }}<span class="error_msg">{{ obj.errors.user.0 }}</span></td>
<td>{{ obj.email }}<span class="error_msg">{{ obj.errors.email.0 }}</span></td>
<td>{{ obj.wechat }}<span class="error_msg">{{ obj.errors.wechat.0 }}</span></td>
<td>{{ obj.phone_number }}<span class="error_msg">{{ obj.errors.phone_number.0 }}</span></td>
<td>{{ obj.group }}<span class="error_msg">{{ obj.errors.group.0 }}</span></td>
<td>{{ obj.partment }}<span class="error_msg">{{ obj.errors.partment.0 }}</span></td>
<td>默認當前時間</td>
<td style="width: 80px">
<input type="submit" value="新增用戶"/>
</td
</tr>
實際效果
?
二、Form中的參數
創建Form類時,主要涉及到 【字段】 和 【插件】,字段用於對用戶請求數據的驗證,插件用於自動生成HTML;
- 內置字段如下:
Field
required=True, 是否允許為空
widget=None, HTML插件
label=None, 用於生成Label標簽或顯示內容
initial=None, 初始值
help_text='', 幫助信息(在標簽旁邊顯示)
error_messages=None, 錯誤信息 {'required': '不能為空', 'invalid': '格式錯誤'}
show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具有默認值的插件(可用於檢驗兩次輸入是否一直)
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類型
2.2 插件方法
- from django.forms import widgets #使用插件將CharField 中的內容生成文本域 textarea 標簽
textarea = fields.CharField(
????error_messages={"required": "文本域不能為空"}
????widget = widgets.Textarea
)
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
常用插件
單radio,值為字符串
user = fields.CharField(
initial=2,
widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
)
單radio,值為字符串
user = fields.ChoiceField(
choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.RadioSelect
)
單select,值為字符串
user = fields.CharField(
initial=2,
widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
)
單select,值為字符串
user = fields.ChoiceField(
choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.Select
)
多選select,值為列表
user = fields.MultipleChoiceField(
choices=((1,'上海'),(2,'北京'),),
initial=[1,],
widget=widgets.SelectMultiple
)
單checkbox
user = fields.CharField(
widget=widgets.CheckboxInput()
)
多選checkbox,值為列表
user = fields.MultipleChoiceField(
initial=[2, ],
choices=((1, '上海'), (2, '北京'),),
widget=widgets.CheckboxSelectMultiple
?
三、定義自己的驗證規則
1. 第一種方式自定義函數
將自定義的函數加入 validators = [] 參數中
from django.forms import ValidationError
def mobile_validate(value):
pattern_mobile= '^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$'
if not re.match(pattern_mobile, str(value)):
raise ValidationError('手機號碼格式錯誤')
#Form類中
class UserForm(forms.Form):
phone_number = fields.IntegerField(
validators= [mobile_validate,], #將自定義的函數加入validators參數中
error_messages= {
"required": "手機號不能為空",
"invalid": "手機號格式有誤"
}
)
#或
phone_number = forms.CharField(validators=[mobile_validate, ],
error_messages={'required': '手機不能為空'},
widget=forms.TextInput(attrs={'class': "phone",
'placeholder': '+86 13356475897'}))
2. 第二種方式自定義函數
將自定義的函數加入 validators = [] 參數中
from django.core.validators import RegexValidator
class UserForm(Form):
phone_number = fields.IntegerField(
validators=[RegexValidator('^1\d{10}$', '手機號非法'), RegexValidator('^133[0-9]{8}$', '只能為聯通號')],
)
Django 中的Form表單認證