1、HTML中的表單
在HTML種,表單是在<form>...</form>種的元素,它允許用戶輸入文本,選擇選項,操作對象等,然后發送這些數據到服務器
表單元素允許用戶在表單種輸入內容如,文本域(textarea)、下拉列表、單選框(radio-buttons)、復選框(checkboxes)等。
大多數情況下被用到的表單標簽是輸入標簽(<input>),輸入類型是由類型屬性(type)定義的,大多數經常被用到的輸入類型下面做簡單介紹:
(1)文本域(Text Fields)
文本域通過<input type="text">標簽來設定,當用戶要在表單種輸入字母,數字等內容是,就會用到文本域,在大多數瀏覽器種,文本域的缺省寬度是20個字符:
<form> 姓名:<input type="text" name="username"><br> </form>
(2)密碼字段
密碼字段通過標簽<input type="password">來定義,密碼字段字符不會明文顯示,而是以星號或圓點替代:
<form> 姓名:<input type="text" name="username"><br> 密碼:<input type="password" name="password"> </form>
(3)單選按鈕(Radio Buttons)
<input type="radio">標簽定義了表單單選框選項
<form> 姓名:<input type="text" name="username"><br> 密碼:<input type="password" name="password"><br> 性別:<input type="radio" name="sex" value="man">男<input type="radio" name="sex" value="weman">女<br> </form>
(4)復選框(Checkboxes)
<input type="checkbox"定義了復選框,用戶可以從若干個給定的選擇種選擇多個
<form> 姓名:<input type="text" name="username"><br> 密碼:<input type="password" name="password"><br> 性別:<input type="radio" name="sex" value="man">男<input type="radio" name="sex" value="weman">女<br> 愛好:<input type="checkbox" name="vehicle" value="yundong">運動 <input type="checkbox" name="vehicle" value="youxi">游戲 <input type="checkbox" name="vehicle" value="xuexi">學習 </form>
(5)提交按鈕(Submit Button)
<input type="submit">定義了提交按鈕,當用戶單擊確認按鈕時,表單的內容就會被傳送到動作屬性定義的目的文件中
<form action="index.html" method="post"> 姓名:<input type="text" name="username"><br> 密碼:<input type="password" name="password"><br> 性別:<input type="radio" name="sex" value="man">男<input type="radio" name="sex" value="weman">女<br> 愛好:<input type="checkbox" name="vehicle" value="yundong">運動 <input type="checkbox" name="vehicle" value="youxi">游戲 <input type="checkbox" name="vehicle" value="xuexi">學習<br> <input type="submit" value="提交"> </form>
瀏覽器表單中的數據會發往action屬性指定的URL,並且使用它的method屬性指定的HTTP方法post,當點擊submit類型的提交時,會將數據發送到index.html中。
HTML5有許多新的input類型:
color類型選取顏色,date類型日期選擇器,datetime-local類型選擇一個日期和時間,email類型用於e-mail地址的輸入域,month類型允許選擇一個月份,number類型用於數值的輸入域,rang類型定義一定范圍內數字的輸入域,顯示為滑動條可設置最大值max和最小值min,search類型用於搜索域,tel類型定義電話號碼字段,time類型定義一個時間選擇,url類型用於URL地址的輸入域,week類型允許選擇周和年。
處理表單時只會用到GET和POST兩種HTTP方法,GET方法會將提交的數據捆綁到URL中,而POST通過加密的方式在后台提交
2、Django中的表單
Django會處理涉及表單的三個部分:
准備並重組數據,以便下一步的渲染;為數據創建HTML表單;接收並處理客戶端提交的表單以及數據。
Django表單系統的核心組件是Form類,Form類描述一張表單並決定它如何工作並呈現
Form類,類似於模型類的字段映射到數據庫字段的方式,表單類的字段會映射到HTML表單的<input>元素,表單字段本身也是類,它們管理表單數據並提交表單執行驗證,在瀏覽器中表單字段以HTML控件的形式展現給我們,在Django中每個字段類型都有與之匹配的控件類,在必要時也可以覆蓋
在Django中渲染一個對象的過程通常為:在視圖中獲取數據,然后將數據傳遞給模板,使用模板變量將數據擴展到HTML標記,下面我們在Django中構建表單
在app中新建forms.py文件:
from django import forms #首先它繼承Form類,然后通過控件類CharField定義文本域並指定屬性 class IndexForm(forms.Form): username = forms.CharField(label='姓名',max_length=100)
然后在編輯視圖並引入表單類:
#views.py from django.shortcuts import render from django.http import HttpResponse from .forms import IndexForm #新建視圖函數處理表單,首先判斷提交類型為post則通過表單類接收POST請求數據並填充表單類,然后判斷數據是否有效並提交到后台,此處做演示只做判斷並提示接收成功,
#如果提交類型不為POST則創建空表單通過變量傳遞給模板 def get_name(request): if request.method == 'POST': form = IndexForm(request.POST) print(form) if form.is_valid(): return HttpResponse('提交到后台成功!') else: form = IndexForm() return render(request,'index.html',{'form':form})
表單類生成的數據如下:
<tr><th><label for="id_username">姓名:</label></th><td><input type="text" name="username" value="root" maxlength="100" required id="id_username"></td></tr>
在模板中只需簡單的配置form標簽並接收變量,注意表單不包含提交標簽需要在模板中自己創建
<form action="{% url 'formtest' %}" method="post"> {% csrf_token %} #此處為跨站請求偽造保護功能django自提供 {{ form }} <input type="submit" value="提交"> </form>
頁面程序效果:
<form action="/" method="post"> <input type="hidden" name="csrfmiddlewaretoken" value="e9Je91NyzZFWx83yXQbSiHYYjH3g4tsiz22zAjEAhSfKnNzPjAINCVd1iHZAnC4B"> <label for="id_username">姓名:</label><input type="text" name="username" maxlength="100" required="" id="id_username"> <input type="submit" value="提交"> </form>
在模板中我們只需將表單在上下問中進行渲染,來得到對應的標簽元素,如上面的form變量渲染{{ form }}
但在表單渲染選項還可以使用其他渲染方式:
{{ form.as_table }}包裝在<tr>標記中的表格單元格顯示數據,但必須自己提供外層<table>元素
{{ form.as_p }}包裹在<p>標記中的顯示數據
{{ form.as_ul }}包裹在<li>標記中顯示數據,但必須自己提供外層<ul>元素
手動渲染字段:
循環遍歷每個字段對字段屬性手動渲染,如下field.errors輸出包含改字段驗證的錯誤信息,field.label_tag為帶<label>標簽的label值
#遍歷表單字段 <form action="{% url 'index' %}" method="post"> {% csrf_token %} {% for field in form %} {{ field.errors }} {{ field.label_tag }} {{ field }}<br> {% endfor %} <input type="submit" value="提交"> </form> #渲染效果 <form action="/" method="post"> <input type="hidden" name="csrfmiddlewaretoken" value="benu1PCIYH6XKtSxa7cQyR8wwwIYvae7w7GPs7tKGAGLA8oOwRJLS5nzvwEiOjQq"> <label for="id_subject">Subject:</label> <input type="text" name="subject" maxlength="100" required="" id="id_subject"><br> <label for="id_message">Message:</label> <textarea name="message" cols="40" rows="10" required="" id="id_message"></textarea><br> <label for="id_sender">Sender:</label> <input type="email" name="sender" required="" id="id_sender"><br> <label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself"><br> <input type="submit" value="提交"> </form>
field.label_tag:輸出field的label元素,如:<label for="id_subject">Subject:</label>
field:輸出field的input,如:<input type="text" name="subject" maxlength="100" required="" id="id_subject">
field.errors:輸出field的errors元素,一般在form表單驗證出錯時顯示
field.id_for_label:輸出字段的ID值
field.value:輸出字段填充的值
field.html_name:輸出字段的名稱
field.help_text:輸出與該字段的幫助文本
field.is_hidden:如果是隱藏字段屬性值為True否則為False
3、表單集
Formset表單集是多個表單的集合,Formset在web開發中應用很普遍,它可以讓用戶在同一個頁面提交多張表單,一鍵添加多個數據
Django針對不同的formset提供了三種方法:formet_factory,modelformset_factory和inlineformset_factory
(1)使用formset_factory
對應繼承forms.Form的自定義表單,我們可以使用formset_factory,通過設置extra指定表單數量,max_num指定表單數量最大值
首先創建表單並使用formset_factory方法指定創建表單集並指定表單數量
#forms.py from django import forms from django.forms import formset_factory class registerForm(forms.Form): username = forms.CharField(max_length=120) age = forms.IntegerField() pub_date = forms.DateField(required=False) registerFormset = formset_factory(registerForm,extra=3,max_num=5)
在視圖views.py里使用formset
#views.py from django.shortcuts import render,HttpResponse from .forms import registerFormset def register(request): if request.method == 'POST': formset = registerFormset(request.POST,request.FILES) if formset.is_valid(): return HttpResponse('formset is ok') else: formset = registerFormset() return render(request,'register.html',context={'formset':formset})
最后在模版中應用表單即可
<form action="{% url 'register' %}" method="post"> {{ formset.management_form }} {% for form in formset %} {{ form.as_p }} {% endfor %} </form>
4、從模型創建表單
首先創建model模型:
from django.db import models from django.utils import timezone TITLE_CHOICES = ( ('MR','Mr.'), ('MRS','Mrs.'), ('MS','Ms.'), ) class Author(models.Model): name = models.CharField(max_length=100,verbose_name='姓名') title = models.CharField(max_length=3,choices=TITLE_CHOICES,verbose_name='標題') birth_date = models.DateField(default=timezone.now,blank=True,null=True,verbose_name="創建時間") def __str__(self): return self.name
根據模型創建表單文件:
#forms.py #導入模型表單類 from django.forms import ModelForm from .models import Author #繼承模型表單類創建表單 class AuthorForm(ModelForm): class Meta: model = Author #指定model fields = ['name','title','birth_date'] #指定要顯示的字段,全顯示可使用"__all__"
在通過模型創建表單時,我們只需繼承Django的模型表單類,然后重寫它的屬性即可,model指定要創建表單的模型,fields指定顯示的模型字段,全顯示可以用“__all__"代替,還有其他的類屬性exclude指定排除的字段,labels指定提示信息,help_texts指定幫助提示信息,widgets指定自定義插件,error_messages自定義錯誤信息,field_classes自定義字段類,localized_fields本地化時區時間,根據setting中TIME_ZONE設置的不同時區顯示時間
from django import forms from django.forms import ModelForm from .models import Author class AuthorForm(ModelForm): class Meta: model = Author fields = ['name','title','birth_date'] widgets = { 'title':forms.Textarea(attrs={'cols':80,'rows':20}) } #覆蓋重寫title字段的類型 labels = { 'name':'作者', 'title':'頭銜', 'birth_date':'出生日期', } error_messages = { 'name':{ 'max_length':'名字長度在15個字符內', } }
在django中的模型字段和表單字段的字段類型定義都差不多,比較特殊的是ForeignKey和ManyToManyField模型字段在表單中的字段類型會有所不同:
ForeignKey由django.forms.ModelChoiceField表示,它是一個ChoiceField,其選項是一個模型QuerySet
ManyToManyField由django.forms.ModelMultipleChoiceField表示,它是一個MultipleChoiceField,其選項為一個模型QuerySet
另外,每個生成的表單字段的屬性設置如下:
如果模型字段設置了blank=True,那么表單字段的required屬性被設置為False,否知為True
表單字段的label設置為模型字段的verbose_name,並且首字母大寫
表單字段的help_text設置為模型字段的help_text
如果模型字段設置了choices,那么表單字段的widget會被設置為select,其選項來自模型字段的choices,這些選項通常包含一個默認選中的空選項,如果字段設置了必填,則會強制用戶進行選項,如果模型字段設置了blank=False以及一個明確的default值,則表單字段中不會包含空選項
在視圖中使用表單:
#views.py from django.shortcuts import render,HttpResponse from .forms import AuthorForm from .models import Author def test(request): if request.method == 'POST': author_form = AuthorForm(request.POST) if author_form.is_valid(): author_form.save(commit=True) return HttpResponse('提交成功') else: author_form = AuthorForm() obj = Author.objects.all() return render(request,'test.html',{"author_form":author_form,'obj':obj})
views.py中使用ModelForm的save()方法將表單數據保存到數據庫中,參數commit為True時寫如數據庫,如果為False則創建一個Model對象但不保存到數據庫中,如果要更新某個對象可以使用save的instance參數來指定要更新的model對象
在模板中提交並展示數據:
#test.html <body> <h2>Author Form:</h2> <form action="{% url 'test' %}" method="post"> {% csrf_token %} {{ author_form }} <input type="submit" value="提交"> </form> <h2>Author Form output:</h2> <ul> {% for i in obj %} <li>{{ i.id }}:{{ i.name }}:{{ i.title }}:{{ i.birth_date }}</li> {% endfor %} </ul> </body>
表單模板ModelForm中有一個工廠函數可以直接通過Model創建表單modelform_factory(),在不需要很多自定義的情況下是很方便的
from .models import Author from django import forms from django.forms.models import modelformset_factory modelform_Author = modelformset_factory(model=Author,fields=('__all__'),widgets={'title':forms.Textarea()})