服務端假設全部用戶提交的數據都是不可信任的,因此Django框架內置了form組件來驗證用戶提交的信息html
form組件的2大功能:
1 驗證(顯示錯誤信息)
2 保留用戶上次輸入的信息
-- 能夠生成html標籤
應用:python
class A_Form(Form): 字段=fields.字段類型(默認參數: required=True, widget=widgets.插件(attrs={})) 經常使用字段:Charfield,RegexField,IntegerField,EmailField 經常使用參數:max_length,min_length, widget=widgets.Select(choices=models.Classes.objects.values_list('id','title')) error_messages={ 'required':'用戶名不能爲空', 'max_length':'太長了', 'min_length':'過短了', } label='用戶名', # obj.t1.label disabled=False, # 是否能夠編輯 label_suffix='--->', # Label內容後綴 help_text='。。。。。。', # 提供幫助信息 obj=A_Form(initial='')#生成空的html標籤,含有默認值 obj=A-Form(request.POST)#拿到瀏覽器請求,傳入form作驗證 obj.is_valid()#判斷驗證是否經過 obj.cleaned_data()#驗證經過後的值 字典形式 obj.errors #form 返回的錯誤信息 是個對象 'obj.errors.字典.0 ' 獲取第一個錯誤信息
原理:git
LoginForm實例化時:self.fields={ 'username':正則表達式 'password':正則表達式} 循環self.fields flag=True errors cleaned_data for k,v in self.fields.items(): username ,正則 input_value=request.POST.get(k) input_value,正則 flag=false /true return flag
ModelForm a. class Meta: model, # 對應Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信息 help_texts=None, # 幫助提示信息 widgets=None, # 自定義插件 error_messages=None, # 自定義錯誤信息(總體錯誤信息from django.core.exceptions import NON_FIELD_ERRORS) field_classes=None # 自定義字段類 (也能夠自定義字段) localized_fields=('birth_date',) # 本地化,如:根據不一樣時區顯示數據 如: 數據庫中 2016-12-27 04:10:57 setting中的配置 TIME_ZONE = 'Asia/Shanghai' USE_TZ = True 則顯示: 2016-12-27 12:10:57 b. 驗證執行過程 is_valid -> full_clean -> 鉤子 -> 總體錯誤 c. 字典字段驗證 def clean_字段名(self): # 能夠拋出異常 # from django.core.exceptions import ValidationError return "新值" d. 用於驗證 model_form_obj = XXOOModelForm() model_form_obj.is_valid() model_form_obj.errors.as_json() model_form_obj.clean() model_form_obj.cleaned_data e. 用於建立 model_form_obj = XXOOModelForm(request.POST) #### 頁面顯示,並提交 ##### # 默認保存多對多 obj = form.save(commit=True) # 不作任何操做,內部定義 save_m2m(用於保存多對多) obj = form.save(commit=False) obj.save() # 保存單表信息 obj.save_m2m() # 保存關聯多對多信息 f. 用於更新和初始化 obj = model.tb.objects.get(id=1) model_form_obj = XXOOModelForm(request.POST,instance=obj) ... PS: 單純初始化 model_form_obj = XXOOModelForm(initial={...})
擴展:正則表達式
1.因爲form組件中每一個字段都是類的數據屬性(全局變量),在類每次實例化以後,數據屬性不會發生改變,會保留上次的更新結果
致使沒法動態顯示數據庫的內容數據庫
解決方法一:每次實例化以前,更新xx字段的值 xx=fields.MultipleChoiceField( # choices=models.Classes.objects.values_list('id','title'), widget=widgets.SelectMultiple ) def __init__(self,*args,**kwargs): super(TeacherForm,self).__init__(*args,**kwargs) self.fields['xx'].choices=models.Classes.objects.values_list('id','title') 解決方法二:不推薦 from django.forms import models as form_model xx=form_model.ModelMultipleChoiceField(queryset=models.Classes.objects.all()) models中: def __str__(self): return self.title
2. 擴展字段django
單選:ChoiceField 多選:MultipleChoiceField Select框: 單選 cls_id = fields.IntegerField( # widget=widgets.Select(choices=[(1,'上海'),(2,'北京')]) widget=widgets.Select(choices=models.Classes.objects.values_list('id','title')) ) cls_id = fields.ChoiceField( choices=models.Classes.objects.values_list('id','title'), widget=widgets.Select(attrs={'class': 'form-control'}) ) obj = FooForm({'cls_id':1}) 多選 xx = fields.MultipleChoiceField( choices=models.Classes.objects.values_list('id','title'), widget=widgets.SelectMultiple ) obj = FooForm({'cls_id':[1,2,3]}) 文件:FileField
經常使用選擇插件json
1 # 單radio,值爲字符串 2 # user = fields.CharField( 3 # initial=2, 4 # widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) 5 # ) 6 7 # 單radio,值爲字符串 8 # user = fields.ChoiceField( 9 # choices=((1, '上海'), (2, '北京'),), 10 # initial=2, 11 # widget=widgets.RadioSelect 12 # ) 13 14 # 單select,值爲字符串 15 # user = fields.CharField( 16 # initial=2, 17 # widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) 18 # ) 19 20 # 單select,值爲字符串 21 # user = fields.ChoiceField( 22 # choices=((1, '上海'), (2, '北京'),), 23 # initial=2, 24 # widget=widgets.Select 25 # ) 26 27 # 多選select,值爲列表 28 # user = fields.MultipleChoiceField( 29 # choices=((1,'上海'),(2,'北京'),), 30 # initial=[1,], 31 # widget=widgets.SelectMultiple 32 # ) 33 34 35 # 單checkbox 36 # user = fields.CharField( 37 # widget=widgets.CheckboxInput() 38 # ) 39 40 41 # 多選checkbox,值爲列表 42 # user = fields.MultipleChoiceField( 43 # initial=[2, ], 44 # choices=((1, '上海'), (2, '北京'),), 45 # widget=widgets.CheckboxSelectMultiple 46 # )
擴展插件瀏覽器
1 擴展插件: 2 Textarea 3 CheckboxInput 4 CheckboxSelectMultiple 5 RadioSelect 6 FileInput 7 8 t1=fields.CharField( 9 widget=widgets.Textarea(attrs={}) 10 ) 11 t2=fields.CharField( 12 widget=widgets.CheckboxInput 13 ) 14 t3=fields.MultipleChoiceField( 15 choices=[(1,'籃球'),(2,'足球')], 16 widget=widgets.CheckboxSelectMultiple 17 ) 18 t4=fields.ChoiceField( 19 choices=[(1,'籃球'),(2,'足球')], 20 widget=widgets.RadioSelect 21 ) 22 t5=fields.FileField( 23 widget=widgets.FileInput 24 )
Django內置字段:框架
1 Field 2 required=True, 是否容許爲空 3 widget=None, HTML插件 4 label=None, 用於生成Label標籤或顯示內容 5 initial=None, 初始值 6 help_text='', 幫助信息(在標籤旁邊顯示) 7 error_messages=None, 錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'} 8 show_hidden_initial=False, 是否在當前插件後面再加一個隱藏的且具備默認值的插件(可用於檢驗兩次輸入是否一直) 9 validators=[], 自定義驗證規則 10 localize=False, 是否支持本地化 11 disabled=False, 是否能夠編輯 12 label_suffix=None Label內容後綴 13 14 15 CharField(Field) 16 max_length=None, 最大長度 17 min_length=None, 最小長度 18 strip=True 是否移除用戶輸入空白 19 20 IntegerField(Field) 21 max_value=None, 最大值 22 min_value=None, 最小值 23 24 FloatField(IntegerField) 25 ... 26 27 DecimalField(IntegerField) 28 max_value=None, 最大值 29 min_value=None, 最小值 30 max_digits=None, 總長度 31 decimal_places=None, 小數位長度 32 33 BaseTemporalField(Field) 34 input_formats=None 時間格式化 35 36 DateField(BaseTemporalField) 格式:2015-09-01 37 TimeField(BaseTemporalField) 格式:11:12 38 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 39 40 DurationField(Field) 時間間隔:%d %H:%M:%S.%f 41 ... 42 43 RegexField(CharField) 44 regex, 自定製正則表達式 45 max_length=None, 最大長度 46 min_length=None, 最小長度 47 error_message=None, 忽略,錯誤信息使用 error_messages={'invalid': '...'} 48 49 EmailField(CharField) 50 ... 51 52 FileField(Field) 53 allow_empty_file=False 是否容許空文件 54 55 ImageField(FileField) 56 ... 57 注:須要PIL模塊,pip3 install Pillow 58 以上兩個字典使用時,須要注意兩點: 59 - form表單中 enctype="multipart/form-data" 60 - view函數中 obj = MyForm(request.POST, request.FILES) 61 62 URLField(Field) 63 ... 64 65 66 BooleanField(Field) 67 ... 68 69 NullBooleanField(BooleanField) 70 ... 71 72 ChoiceField(Field) 73 ... 74 choices=(), 選項,如:choices = ((0,'上海'),(1,'北京'),) 75 required=True, 是否必填 76 widget=None, 插件,默認select插件 77 label=None, Label內容 78 initial=None, 初始值 79 help_text='', 幫助提示 80 81 82 ModelChoiceField(ChoiceField) 83 ... django.forms.models.ModelChoiceField 84 queryset, # 查詢數據庫中的數據 85 empty_label="---------", # 默認空顯示內容 86 to_field_name=None, # HTML中value的值對應的字段 87 limit_choices_to=None # ModelForm中對queryset二次篩選 88 89 ModelMultipleChoiceField(ModelChoiceField) 90 ... django.forms.models.ModelMultipleChoiceField 91 92 93 94 TypedChoiceField(ChoiceField) 95 coerce = lambda val: val 對選中的值進行一次轉換 96 empty_value= '' 空值的默認值 97 98 MultipleChoiceField(ChoiceField) 99 ... 100 101 TypedMultipleChoiceField(MultipleChoiceField) 102 coerce = lambda val: val 對選中的每個值進行一次轉換 103 empty_value= '' 空值的默認值 104 105 ComboField(Field) 106 fields=() 使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式 107 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) 108 109 MultiValueField(Field) 110 PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用 111 112 SplitDateTimeField(MultiValueField) 113 input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] 114 input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] 115 116 FilePathField(ChoiceField) 文件選項,目錄下文件顯示在頁面中 117 path, 文件夾路徑 118 match=None, 正則匹配 119 recursive=False, 遞歸下面的文件夾 120 allow_files=True, 容許文件 121 allow_folders=False, 容許文件夾 122 required=True, 123 widget=None, 124 label=None, 125 initial=None, 126 help_text='' 127 128 GenericIPAddressField 129 protocol='both', both,ipv4,ipv6支持的IP格式 130 unpack_ipv4=False 解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用 131 132 SlugField(CharField) 數字,字母,下劃線,減號(連字符) 133 ... 134 135 UUIDField(CharField) uuid類型 136 ...
Django內置插件:函數
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
3 額外的正則:
user = fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')])
4 頁面展現:
1 obj = Foo() 2 obj = Foo(init..) 3 4 # 靈活 5 <form> 6 {{obj.xx}} 7 {{obj.xx}} 8 {{obj.xx}} 9 {{obj.xx}} 10 </form> 11 # 簡單 12 {{obj.as_p}} 13 <ul> 14 {{obj.as_ul}} 15 </ul> 16 <table> 17 {{obj.as_table}} 18 </table>
5 定製:
class Test1Form(Form): user = fields.CharField(validators=[]) pwd = fields.CharField() # 爲每一個字段定製本身的要求 必需要有返回值 def clean_user(self): v = self.cleaned_data['user'] if models.Student.objects.filter(name=v).count(): raise ValidationError('用戶名已經存在') return self.cleaned_data['user'] def clean_pwd(self): return self.cleaned_data['pwd'] # 爲全部字段定製統一的要求 def clean(self): # user = self.cleaned_data.get('user') # email = self.cleaned_data.get('email') # if models.Student.objects.filter(user=user,email=email).count(): # raise ValidationError('用戶名和郵箱聯合已經存在') return self.cleaned_data
6 自定義驗證規則
http://www.cnblogs.com/wupeiqi/articles/6144178.html
轉載自:
https://www.cnblogs.com/liuguniang/p/7141837.html