一 建立一個form組件css
導入forms模塊組件:from django import formshtml
建立組件:建立一個類繼承者forms.Form這個類git
類型:正則表達式
CharField:字符串類型,min_length:字符長度不能小於多少;max_length:字符的長度不能大於多少,error_messages:能夠根據保存信息顯示對應的中文報錯,required:該字段不可以爲空,widget:對input標籤操做。數據庫
IntegerField:整數類型,invalid:格式錯誤django
MultiplechioceField:設置字段爲多選框(單選框)。initial=[數字,]:初始個數。choices=((value,數據),(value,數據)):爲多選框(單選框賦值)。widgets.CheckboxSelectMultiple:設置爲複選框bootstrap
其餘類型:app
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類型 ...
根據不一樣要求爲表單加上不一樣的屬性值:導入from django.forms impost widgetside
widgets.PasswoedInput:加上密文的屬性值,addrs:爲指定的標籤加上屬性。函數
widgets.TextInput:文本信息
widgets.Select:下拉菜單,choices:爲option出入值和value屬性值
鉤子clean:首先導入異常:from django.core.exceptions import ValidationError。
局部鉤子:clean_字段名,就是使用clean_加上一個字段名。用於字段校驗
raise calidationsError:拋出錯誤信息
cleaned_data:若是符合條件,數據就會存放在這裏面,可使用get獲取是一個有序的字典格式,從上往下依次判斷添加。
for name, field in self.fields.items(): try: value = field.clean(value) self.cleaned_data[name] = value if hasattr(self, 'clean_%s' % name): value = getattr(self, 'clean_%s' % name)() self.cleaned_data[name] = value except ValidationError as e: self.add_error(name, e)
全局鉤子:clean,直接在這個函數裏面定義功能,能夠用於多個字段的操做和比較,直接能夠獲取cleaned_data裏面的數據。
__all__:全局拋出來的錯誤存放在這個裏面的。
self.clean() # def self.clean():return self.cleaned_data return not self.errors # True或者False
from django import forms from django.forms import widgets from django.core.exceptions import ValidationError class LoginForm(forms.Form): user=forms.CharField(min_length=5,max_length=12, error_messages={ "required":"該字段不能爲空", "min_length":"該字段的長度不能小於5", "max_length":"該字段的長度不能大於12"}, widget=widgets.TextInput(attrs={"class":"form-control"}) ) pwd=forms.CharField( error_messages={ "invalid": "必須是數字" }, widget=widgets.PasswordInput(attrs={"class":"form-control",}) ) gender=forms.CharField( widget=widgets.Select(choices=((1,'男'),(0,'女'),)) ) usersss = forms.MultipleChoiceField( initial=[2, ], choices=((1, '上海'), (2, '北京'),), widget=widgets.CheckboxSelectMultiple ) def clean_user(self): print("============",self.cleaned_data.get("pwd")) # ============ None if not self.cleaned_data.get("user").isdigit(): return self.cleaned_data.get("user") else: raise ValidationError("該字段不能是純數字") def clean_pwd(self): print("-----------------",self.cleaned_data.get("user")) import re val=self.cleaned_data.get("pwd") ret=re.findall("^\d{6}yuan$",val) if ret: return val else: raise ValidationError("密碼不符合設定要求") def clean(self): if self.cleaned_data.get("user") and self.cleaned_data.get("pwd"): if self.cleaned_data.get("user") != self.cleaned_data.get("pwd"): return self.cleaned_data else: raise ValidationError("用戶名與密碼不能一致!") return self.cleaned_data
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
經常使用選擇插件:
# 單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 # )
二 實例form對象
實例化時: self.fields={ "username":"字段規則對象", "password":"字段規則對象", }
LoginForm:form自建實例的對象存放的地點,request.POST:將數據傳遞給對應的字段,綁定數據的表單實例
is_valid:校驗,將檢驗是否符合要求,返回的是一個布爾值
cleaned_data:檢驗正確數據就存放在這裏面,是以字典的格式存放的,出數據。
errors:檢驗沒有經過或錯誤的信息存放在這個裏面,是以字典的格式存放的。errors.get獲取裏面的某些數據。
from django.shortcuts import render,HttpResponse # Create your views here. from django import forms from .models import * from django.forms import widgets from .forms import * def login(request): if request.method=="POST": #print(request.POST) #<QueryDict: {'csrfmiddlewaretoken': ['0xrifjX7jplIZwngbrRjpHPXw6kyDVa2Erca0sGYfjH9UuDfHzNUdMzlh7EH2v44'], 'user': ['asdas'], 'pwd': ['12321321']}> login_form=LoginForm(request.POST) # 將數據傳給對應字段 綁定數據的表單實例 ''' # self.cleaned_data={"pwd":"12312412"} # self.errors={"user":"yuan",} ''' if login_form.is_valid(): print("經過驗證") print(login_form.cleaned_data) print("use:",login_form.cleaned_data.get("user")) print(login_form.errors) ############### # user=login_form.cleaned_data.get("user") # pwd=login_form.cleaned_data.get("pwd") # UserInfo.objects.filter(username=user,password=pwd) # UserInfo.objects.filter(**login_form.cleaned_data) return HttpResponse("OK") else: # print("驗證失敗") # print(login_form.cleaned_data) # {'pwd': 77777} # print(login_form.errors) # ################## login_form.errors是什麼類型 # print(type(login_form.errors))# <class 'django.forms.utils.ErrorDict'> # ###################獲取login_form.errors的某個鍵的值 # print(login_form.errors.get("user")) # print(type(login_form.errors.get("pwd")))# <class 'django.forms.utils.ErrorList'> # # #login_form.errors={"user":["小於5位","不是數字"],"pwd":["",""]} errors=login_form.errors# {"user":["該字段不能是純數字",],"pwd":["",""]} print("errors-->",errors) error_all=errors.get("__all__") return render(request, "login.html", {"login_form": login_form,"errors":errors,"error_all":error_all}) #### get請求 login_form=LoginForm() # form組件的實例對象 未綁定表單實例 return render(request,"login.html",{"login_form":login_form})
三 html文件渲染
模板導入input標籤:直接用對象.字段取出內容 {{ 對象.字段}}
模板導入錯誤信息:直接使用srrors.字段名.0取出數據{{ srrors.字段名.0 }}
form組件只可以直接渲染input標籤,form標籤仍是須要本身寫的。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 新 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> <style> .container{ margin-top: 100px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-6"> <form action="/login/" method="post"> {% csrf_token %} <div class="form-group"> <label for="user">user</label> {{ login_form.user }} <span>{{ errors.user.0 }}</span> </div> <div class="form-group"> <label for="pwd">pwd</label> {{ login_form.pwd }} <span>{{ errors.pwd.0 }}</span> </div> <div class="form-group"> <label for="gender">gender</label> {{ login_form.gender }}<span>{{ error_all.0 }}</span> </div> <p>{{ login_form.usersss }}</p> <button type="submit" class="btn btn-default">Submit</button> </form> <hr> {# <form action="">#} {# {{ login_form.as_p }}#} {# </form>#} </div> </div> </div> </body> </html>
四 其餘渲染對象
對於<label>/<input>
對,還有幾個輸出選項:
{{ form.as_table }}
以表格的形式將它們渲染在<tr>
標籤中{{ form.as_p }}
將它們渲染在<p>
標籤中{{ form.as_ul }}
將它們渲染在<li>
標籤中注意,你必須本身提供<table>
或<ul>
元素。
{{ form.as_p }}
結果以下:
<form action=""> <p> <label for="id_username">Username:</label> <input id="id_username" maxlength="100" name="username" type="text" required=""> </p> <p> <label for="id_password">Password:</label> <input id="id_password" maxlength="100" name="password" placeholder="password" type="password" required=""> </p> <p> <label for="id_telephone">Telephone:</label> <input id="id_telephone" name="telephone" type="number" required=""> </p> <p> <label for="id_email">Email:</label> <input id="id_email" name="email" type="email" required=""> </p> <p> <label for="id_is_married">Is married:</label> <input id="id_is_married" name="is_married" type="checkbox"> </p> <input type="submit" value="註冊"> </form>
這種渲染有了限制,不能個自定義的渲染,而是將全部的字段所有渲染過去。
手動渲染:咱們沒有必要非要讓Django 來分拆表單的字段;若是咱們喜歡,咱們能夠手工來作每一個字段都是表單的一個屬性,可使用{{ form.name_of_field }}
訪問,並將在Django 模板中正確地渲染
<div class="fieldWrapper"> {{ form.Username.errors }} {{ form.Username.label_tag }} {{ form.Username }} </div>
五 表單渲染的錯誤信息
registerForm=RegisterForm(request.POST) print(type(registerForm.errors)) #<class 'django.forms.utils.ErrorDict'> print(type(registerForm.errors["username"])) #<class 'django.forms.utils.ErrorList'>
使用{{ form.name_of_field.errors }} 顯示錶單錯誤的一個清單,並渲染成一個ul。看上去可能像: <ul class="errorlist"> <li>Sender is required.</li> </ul>
補充練習:
from django.shortcuts import render # Create your views here. from .models import UserInfor from django.forms import ModelForm from django import forms from .models import * print(City.objects.all().values_list("id","name")) # class RegForm(forms.Form): # user = forms.CharField(max_length=32) # #gender_tuple=(0,'上海'),(1,'北京'),(2,'保定') # gender = forms.ChoiceField(choices =City.objects.all().values_list("id","name")) # # def __init__(self,*args,**kwargs): # super(RegForm,self).__init__(*args,**kwargs) # #print("Ok") # print(self.fields["gender"].choices) # self.fields["gender"].choices=City.objects.all().values_list("id","name") ''' class UserInfor(models.Model): user=models.CharField(max_length=32) gender=models.IntegerField(choices=((1,"男"),(2,"女"))) city=models.ForeignKey("City",default=1) roles=models.ManyToManyField("Roles",default=1) ||||| class UserInfor(forms.Form): user=forms.CharField() gender=forms.TypedChoiceField(choices=((1,"男"),(2,"女"))) city=forms.ModelChoiceField(choices=City.objects.all()) roles=forms.ModelMultipleChoiceField(choices=Roles.objects.all()) ''' class RegForm(ModelForm): class Meta: model=UserInfor fields="__all__" def reg(reqeust): form=RegForm() print(form.fields) return render(reqeust,"reg.html",{"form":form})