@form表单
form使用HTML5语法,顶部需添加说明
from .forms import NameForm
from django.core.mail import send_mail
if request.method == 'POST':
# 接受request.POST参数构造form类的实例
form = NameForm(request.POST)
# 验证数据是否合法
if form.is_valid():
#form.cleaned_data字典中读取所有的表单数据
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']
recipients = ['[email protected]']
if cc_myself:
recipients.append(sender)
send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/')
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
= = =
#template表单渲染格式
Django自动为每个input元素设置了一个id名称,对应label的for参数。
{{ form.as_p }}
{{ form.as_ul }}
{{ form.as_table }}
#手动渲染表单字段
{{ form.non_field_errors }}
{{ form.subject.errors }}
#{{ form.subject.label_tag }}
{{ form.subject }}
#渲染表单错误信息errorlist
{% if form.subject.errors %}
{% for error in form.subject.errors %}
- {{ error|escape }}
{% endfor %}
{% endif %}
#循环表单的字段
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
{{ field.help_text|safe }}
{% endif %}
{% endfor %}
#不可见字段特殊处理hidden_fields()和visible_fields()
{# 循环那些不可见的字段 #}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{# 循环可见的字段 #}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
#重用表单模板 include+with参数,给每个表单模板取个别名
{% include "form_snippet.html" with form=comment_form %}
使用{% for field in comment_form %}
# 单独的表单模板文件form_snippet.html:
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
= = =
1 表单的绑定属性
Form.is_bound True/False
f= ContactForm()#新建一个未绑定的表单
data={'name':anna,'age':12,'marriage':True}
f= ContactForm(date)#绑定了
即使data={}也算绑定
2 使用表单验证数据
Form.clean()
Form.is_valid()#验证数据是否合适的布尔值
3 Form.errors属性保存了错误信息字典
- f.errors
{'sender': ['Enter a valid email address.'], 'subject': ['This field is required.']}
- Form.errors.as_data()返回一个字典,将字段映射到原始的ValidationError实例
{'sender': [ValidationError(['Enter a valid email address.'])],
'subject': [ValidationError(['This field is required.'])]}
- Form.errors.as_json(escape_html=False)返回序列化后的错误字典
{"sender": [{"message": "Enter a valid email address.", "code": "invalid"}],
"subject": [{"message": "This field is required.", "code": "required"}]}
4 Form.add_error(field, error)向特定字段添加错误信息
5 Form.has_error(field, code=None)判断某个字段是否有指定code错误,当code为None任何错误均返回True
6 Form.non_field_errors()返回Form.errors中不是与特定字段相关联的错误
7 Form.has_changed()表单是否发生了变化
f = ContactForm(data, initial=data)
f.has_changed()#表单是否发生了变化True、False
8 Form.changed_data返回有变化的字段的列表
f = ContactForm(request.POST, initial=data)#
if f.has_changed():
print("The following fields changed: %s" % ", ".join(f.changed_data))
9 通过fileds属性访问表单的字段
for row in f.fields.values(): print(row)
f.fields['name']
f.as_table().split('\n')[0]#显示tr里的第一个
f.fields['name'].label = "Username"#修改name字段为Username
10 f.cleaned_data不仅负责验证数据还会将其转为正确的格式
cleaneddata只包含合法的字段,只包含Form定义的字段,data里没赋值的值是空
f.cleaned_data
{'nick_name': '', 'first_name': 'John', 'last_name': 'Lennon'}
11 如果表单是绑定的输出的html将包含数据data
###渲染
f = ContactForm()
f.as_table()
Form.as_p()
Form.as_url()
Form.as_table()
= = =
将上传的文件绑定到表单*处理带有FileField和ImageField字段
为了上传文件,你需要确保你的
核心字段
>>> from django import forms
>>> f = forms.CharField(required=False)
>>> f.clean('foo')
'foo'
>>> f.clean(' ')
' '
>>> f.clean(0)
'0'
label()添加人类友好提示,若无,则为该字段首字母大写
>>> class CommentForm(forms.Form):
... name = forms.CharField(label='Your name')
... url = forms.URLField(label='Your website', required=False)
... comment = forms.CharField()
>>> f = CommentForm(auto_id=False)
>>> print(f)
Your name:
Your website:
Comment:
>>> print tf['name'].label_tag()#输出label
Your name:
label_suffixDjango默认为上面的label参数后面加个冒号后缀
>>> class ContactForm(forms.Form):
... age = forms.IntegerField()
... nationality = forms.CharField()
... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')#
>>> f = ContactForm(label_suffix='?')#
>>> print f.as_p()
initial()给表单元素定义初始值*input元素的value参数的值
如data没有填值的话,initial的值不会作为“默认”的数据。initial值只用于原始表单的显示
>>> class CommentForm(forms.Form):
... name = forms.CharField(initial='Your name')
... url = forms.URLField(initial='http://')
... comment = forms.CharField()
... day = forms.DateField(initial=datetime.date.today)#传入一个可调用的对象
>>> f = CommentForm(auto_id=False)
print f
Name:
Url:
Comment:
>>> data = {'name': '', 'url': '', 'comment': 'Foo'}
>>> f = CommentForm(data)
>>> f.is_valid()
False
# The form does *not* fall back to using the initial values.
>>> f.errors
{'url': ['This field is required.'], 'name': ['This field is required.']}
***widget
最重要的参数之一,指定渲染Widget时使用的widget类,也就是这个form字段在HTML页面中是显示为文本输入框?密码输入框?单选按钮?多选框?还是别的....
help_text该参数用于设置字段的辅助描述文本
subject = forms.CharField(max_length=100, help_text='100 characters max.')
f = HelpTextContactForm(auto_id=False)
print f.as_table()
error_messages该参数允许你覆盖字段引发异常时的默认信息。 传递的是一个字典,其键为你想覆盖的错误信息
name = forms.CharField(error_messages={'required': 'Please enter your name'})#如果error是因为required导致的
validators指定一个列表,其中包含了为字段进行验证的函数
localize参数帮助实现表单数据输入的本地化
disabled设置有该属性的字段在前端页面中将显示为不可编辑状态
即使非法篡改了前端页面的属性,向服务器提交了该字段的值,也将依然被忽略
***内置Field类型
|field|css|data|
|:--|:-|:-|
|BooleanField | CheckboxInput | required|
|CharField max_length | TextInput | min_length strip empty_value required|
|ChoiceField | Select | required invalid_choice|
|TypedChoiceField | Select | required invalid_choice coerce empty_value|
|DateField | DateInput | input_formats required invalid %Y-%m-%d|
|DateTimeField | DateTimeInput | input_formats required invalid'%Y-%m-%d %H:%M:%S'|
|DurationField | TextInput | min_length invalid required|
|EmailField | EmailInput | min_length required invalid|
|FileField | ClearableFileInput | missing, invalid, required, empty, max_length max_length allow_empty_file|
|FilePathField | Select | required invalid_choice path recursive match allow_files allow_folders|
|FloatField | NumberInput TextInput | max_value, invalid, required, min_value|
|ImageField | ClearableFileInput | missing, invalid, required, empty, invalid_image pillow|
|IntegerField | NumberInput TextInput | max_value, invalid, required, min_value|
|GenericIPAddressField | TextInput | protocol unpack_ipv4|
|MultipleChoiceField | SelectMultiple | invalid_list, invalid_choice, required|
|TypedMultipleChoiceField | SelectMultiple | invalid_list, invalid_choice, required coerce empty_value|
|NullBooleanField|
|RegexField | TextInput | max_length,min_length和strip参数,类似CharField|
|SlugField | TextInput |
|TimeField | TextInput | '%H:%M:%S'|
|URLField | UrlInput |
|UUIDField | TextInput |
|ComboField |
|MultiValueField |
|MultiValueField |
|SplitDateTimeField |
***自定义字段
只需要创建一个django.forms.Field的子类,并实现clean()和__init__()构造方法。
__init__()构造方法需要接收前面提过的那些核心参数,比如widget、required,、label、help_text、initial。
还可以通过覆盖get_bound_field()方法来自定义访问字段的方式
= = =
###widget
@指定使用的widget
每个字段都有一个默认的widget类型。如果你想要使用一个不同的Widget,可以在定义字段时使用widget参数。 像这样:
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)#覆盖原来的TextInput Widget
@widget添加css特殊属性
可以在创建Widget时使用Widget.attrs参数来实现这一目的:
class CommentForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
url = forms.URLField()
comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))
@许多widget具有可选的额外参数,下面的示例中,设置了SelectDateWidget的years 属性,注意参数的传递方法:
from django import forms
BIRTH_YEAR_CHOICES = ('1980', '1981', '1982')
FAVORITE_COLORS_CHOICES = (
('blue', 'Blue'),
('green', 'Green'),
('black', 'Black'),
)
class SimpleForm(forms.Form):
birth_year = forms.DateField(widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES))
favorite_colors = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
choices=FAVORITE_COLORS_CHOICES,
)
@Meta类内部的widgets属性
from django.forms import ModelForm, Textarea
from myapp.models import Author
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
widgets = {
'name': Textarea(attrs={'cols': 80, 'rows': 20}), # 改写name属性
}
将fields属性的值设为__all__,表示将映射的模型中的全部字段都添加到表单类中来。
from django.forms import ModelForm
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = '__all__'
exclude属性:
表示将model中,除了exclude属性中列出的字段之外的所有字段,添加到表单类中作为表单字段。
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
exclude = ['title']