django表單系統中,所有的表單類都作為django.forms.Form的子類創建,包括ModelForm
.
關於django中的表單系統有兩種:
- 基於django.forms.Form
- 基於django.forms.ModelForm
表單API
form.is_bound()
表單有兩種狀態:綁定和未綁定,使用form.is_bound()來判斷.
form.is_valid()
驗證表單數據是否合法,返回True或者False
form.errors
表單的錯誤字典
Form.has_error(field,code=None)
該方法返回一個布爾值,指定一個字段是否具有與特定錯誤的錯誤code。如果code是None,它將返回True
form.initial
提供初始值,在表單未綁定的情況下,為表單字段設置初始值.
作為一個有參數的表單, 在實例化一個表單時可以通過指定initial
字段來指定表單中數據的初始值. 以這種方式提供的初始值將覆蓋表單字段的初始值和附加模型實例的值。
>>> article = Article.objects.get(pk=1)
>>> article.headline
'My headline'
>>> form = ArticleForm(initial={'headline': 'Initial headline'}, instance=article)
>>> form['headline'].value()
'Initial headline'
這些值僅對未綁定的表單顯示
>>> f = ContactForm(initial={'subject': 'Hi there!'})
form.has_changed()
檢查表單數據是否發生變化
form.clened_data
在每個字段Form類不僅負責驗證數據,也為“清潔” -它歸到一個一致的格式。這是一個很好的功能,因為它允許以各種方式輸入特定字段的數據,總是導致一致的輸出。
例如,DateField標准化輸入到Python datetime.date對象。不管你是否傳遞一個字符串中的格式'1994-07-15',一個datetime.date對象,或者一些其他的格式,DateField將始終將它規范化為一個datetime.date,只要它是有效的對象。
一旦你創建一個Form實例與一組數據並驗證它,你可以通過它訪問干凈的數據cleaned_data屬性:
>>> data = {'subject': 'hello',
... 'message': 'Hi there',
... 'sender': 'foo@example.com',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
請注意,任何基於文本的領域-如CharField或EmailField-始終清潔輸入Unicode字符串。
如果您的數據並沒有被驗證通過,該cleaned_data詞典只包含有效的字段:
>>> data = {'subject': '',
... 'message': 'Hi there',
... 'sender': 'invalid email address',
... 'cc_myself': True}
>>> f = ContactForm(data)
>>> f.is_valid()
False
>>> f.cleaned_data
{'cc_myself': True, 'message': 'Hi there'}
當Form有效時,cleaned_data將包括一個鍵和值 的所有其字段,即使數據沒有包括一些可選字段的值。在這個例子中,數據字典不包括用於一個值 nick_name字段,但是cleaned_data包含它,用空值:
>>> from django import forms
>>> class OptionalPersonForm(forms.Form):
... first_name = forms.CharField()
... last_name = forms.CharField()
... nick_name = forms.CharField(required=False)
>>> data = {'first_name': 'John', 'last_name': 'Lennon'}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
>>> f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}
在本例中,cleaned_data為值nick_name設置為空字符串,因為nick_name是CharField和CharField請客空值作為空字符串。每個字段類型都知道它的“空白”的值是多少-例如,對DateField,這是None不是空字符串。
form.as_p()
將表單渲染成<p>標簽:
>>> f = ContactForm()
>>> f.as_p()
'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" required /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>'
>>> print(f.as_p())
<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></p>
<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></p>
<p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></p>
<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
form.as_ul()
將表單渲染成形式為一系列的<li>標記,每個<li>含有一個字段。它不包括<ul>
或</ul>
,這樣就可以在指定的任何HTML屬性<ul>的靈活性:
>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>
form.as_table()
跟上面的as_ul()相同,需要自己添加table標簽
>>> f = ContactForm()
>>> f.as_ul()
'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
>>> print(f.as_ul())
<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" required /></li>
<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" required /></li>
<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" required /></li>
<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>
設置表單必填行與錯誤行的樣式
關鍵字:
- Form.error_css_class
- Form.required_css_class
用法:
from django import forms
class ContactForm(Form):
error_css_class = 'error' #錯誤行樣式在HTML中表示class='error'
required_css_class = 'required' #必填樣式在Html中表示clss=‘required’
然后在css文件中定義error與required類就行了.
配置表單元素的HTML id屬性,<label>標簽
from.auto_id
>>> f = ContactForm(auto_id=False) #這樣在html中表單不包含< label >標簽
>>> f = ContactForm(auto_id=True) #在html中表單<label>標簽將為每個表單的id
>>> f = ContactForm(auto_id='id_for_%s') #在html中表單<label>標簽為id_for_字段id
From.prefix
可以為Django表單添加一個命名空間
>>> mother = PersonForm(prefix='mother')
>>> father = PersonForm(prefix='father')
Field.required
表示該字段為必填 缺省為必填項,如需要指定不為必須
>>> f=forms.CharField(required=True)
Field.label
表示友好的label,表單在頁面顯示時用到它
name=from.CharField(label="Your name")
Field.help_text
顯示字段描述文本
Field.error_message
覆蓋默認的錯誤信息
name = forms.CharField(error_messages={'required':'Please enter your name'}) #覆蓋required的默認錯誤信息
widget
負責渲染網頁上的HTML表單
widget.attrs
設置weidget實例樣式
class CommentForm(forms.Form):
name=forms.CharField(widget=forms.TextInput(attrs={'class':'special'}))
comment = forms.CharField(widget= forms.TextInput(attrs={'size':'40'}))
以上自定義了name字段的輸入樣式為類 special,comment更改size的大小為40。
內建的widget
TextInput
NumberInput
EmailInput
URLInput
PasswprdInput
HiddenInput
DateInput 日期
DateTimeInput 日期/時間
TimeInput 時間
Textarea
CheckboxInput
Select
NullBooleanSelect 渲染成 unknown,yes,no三個選項
SelectMultiple
RadioSelect
CheckboxSelectMultiple 復選框列表
FileInput 文件上傳
SelectDateWidget
ModelForm表單
from django.forms import ModelForm
from myapp.models import Article
class ArticleForm(ModelForm):
class Meta:
model = Article #表單對應的model
fields = ['pub_date', 'headline', 'content', 'reporter'] #表單中顯示的字段,對應models.py中對應的字段
這里需要注意一下:model=article
,指定表單對應的model
使用方式:
>>>form = ArticleForm()
>>>article = Article.objects.get(pk=1)
>>>form = ArticleForm(instance = article) #賦值instance可以使form表單是可以接受對象的數據
這里需要注意的:instance=article
,賦值實例instance,可以使form表單可以接受對象類型的數據
instance 屬性,表示與它綁定的模型實例
save()方法
每一個ModelForm都有一個save()方法,這個方法可以根據綁定的form表單創建並且保存一個數據庫對象,ModelForm的子類可以接受一個model的子類作為instance的參數,如果存在那么save()方法會更新這個實例,否則會創建一個新的實例
def table_change(request,table_db_name,obj_id):
if table_db_name in admin.enabled_admins:
obj = admin.enabled_admins[table_db_name].model.objects.get(id=obj_id)
field = [field.name for field in admin.enabled_admins[table_db_name._meta.fields]
if request.method == 'POST':
form = model_form(request.POST,instance=obj)
if form.is_valid():
form.save()
else:
form = model_form(instance=obj)
return render(request,"king_admin/table_change.html",{'form':form})
save(commit=False)
save()方法接受一個commit的參數,其值為True或者False。默認為True。
如果你聲明 save(commit=False),那么它就會返回一個還未保存至數據庫的對象,這樣的話 你可以用這個對象添加一些額外的數據,然后在用save()保存到數據庫.
def edit(request,sid):
edit_obj = get_object_or_404(PointRule,id=sid)
if request.method == 'POST':
form = PointRuleForm(request.POST.copy(),instance=edit_obj)
if form.is_valid():
point = form.save(commit=False)
point.update_user = request.user #在form.save(commit=False時,添加一些表單中未有的數據)
point.save()
return redirect('point:index')
else:
messages.error(request, u'數據驗證錯誤')
else:
form = PointRuleForm(instance=edit_obj)
return render(request,'point/edit.html',locals())
save_m2m()方法
在save(commit=False)的時候,如果你的model中含有many-to-many的數據模型,那么你將無法使用save()方法去保存數據,只能使用save_m2m()方法來保存.
在為聲明save(commit=False),則不用如此保存,用save()就好了...
field字段使用
選擇model中所有字段為表單中的字段
__all__
例子:
from django.forms import ModelForm
class AuthorForm(ModelForm)
class Meta:
model = Author
fields='__all__'
剔除指定字段的所有數據 exclude
class PartialAuhorForm(ModelForm):
class Meta:
model = Author
exclude = ['title'] #添加Author model中除了titile字段的所有字段至PartialAuhorForm表單
覆蓋字段的默認值
form django.forms import ModelForm, Textarea
form myapp.models import Author
class AuthorForm(ModelForm):
class Meta:
model=Author
fields=('name','title','birth_date')
widgets={'name':Textarea(attrs={'cols':80,'rows':20})}
from django.utils.translation import ugettext_lazy as _
class AuthorForm(ModelForm):
class Meta:
model=Author
fields=('name','title','birth_date')
labels = { 'name':_('Writer'), }
help_texts = {'name':_('some useful help text.'),}
error_messages={ 'name':{'max_length':_("this writer name is too long")} }