Django有两个预制好的表单类forms.Form和forms.ModelForm。为什么要使用Django的forms?当然是因为我懒!
看下用forms.Form创建表单可以有多方便吧。
第一步:创建一个表单类,比如做个邮件采集
from django import forms
class TryAForm(forms.Form):
email = forms.EmailField()
建议在views.py同级目录下创建一个form.py
第二步:在views.py的视图中调用这个表单类,看上去像这样
def try_it(request):
if request.method == 'POST':
try_a_form = TryAForm(request.POST)
if try_a_form.is_valid():
cd = try_a_form.cleaned_data #得到表单中的数据
messages.success(request,'Hi~'+cd['username']) #通过列表读取字段值
else:
try_a_form = TryAForm() #如果不是POST,实例化一个空表单
template = 'account/tryit.html'
context = {
'form':try_a_form,
}
return render(request,template,context)
第三部:编辑模版(account/tryit.html),增加以下内容
<form action="." method="post">
{{ form.as_p }}
{% csrf_token %}
<p><input type="submit" value="提交"></p>
</form>
关于表单验证可以说是比较让人烦躁的工作之一,Django提供了数据验证功能,常用的Field参数了解下:
class TryAForm(forms.Form):
char = forms.CharField(initial='hahaha',max_length=8,min_length=6,required=True,help_text='请输入6-8个字符')
email = forms.EmailField(label='邮箱',empty_value='123@123.com',required=False)
float = forms.FloatField(max_value=8,min_value=2,required=True)
Int = forms.IntegerField(max_value=8,min_value=2,required=True)
URL = forms.URLField(required=True)
比较常用的包括required(是否必填),empty_value(为空是自动补全),initial(初始值),disabled(不可编辑)
表单除了验证,还有样式的问题。我用的最多的是bootstrap,原因是我懒。个人感觉在同类样式库里,比较好上手,遇到问题,网上资料最多。
推荐使用django-widget-tweaks定制表单的bootstrap样式
pip install django-widget-tweaks
在项目的setting.py中添加插件
INSTALLED_APPS = [
#...
"widget_tweaks",
#...
]
创建一个应用bootstrap样式的代码片段,比如tryit_snippet.html
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group">
{{ field.errors }}
<label for="{{ field.id_for_label }}" class="form-label" >
{{ field.label }}
</label>
<!-- {{ field }} -->
{% render_field field class="form-control" %}
</div>
{% endfor %}
每个字段的div样式使用form-group,label样式用form-label,input字段使用form-control
编辑表单类,添加template_name=样式代码片段文件
class TryAForm(forms.Form):
template_name = "account/tryit_snippet.html"
char = forms.CharField(initial='hahaha',max_length=8,min_length=6,required=True,help_text='请输入6-8个字符')
email = forms.EmailField(label='邮箱',empty_value='123@123.com',required=False)
float = forms.FloatField(initial=6,disabled=True,required=True)
Int = forms.IntegerField(max_value=8,min_value=2,required=True)
URL = forms.URLField(required=True)
编辑模版文件,把form.as_p 更新为form
<form action="." method="post">
{{ form }}
{% csrf_token %}
<p><input type="submit" value="提交"></p>
</form>
Django还提供了很多定制化部件,更多内容可以查看部件 | Django 文档 | Django (djangoproject.com)
我们在Django的模型中已经给每个字段做了定义,哪个是字符,哪个是数字等。使用forms.ModelForm可以快速根据模型的信息创建表单。
比如有一个用户信息的数据模型,直接让表单字段套用模型字段,像这样
from django import forms
from django.contrib.auth.models import User
class UserEditForm(forms.ModelForm):
class Meta:
model = User
不过这个就太简单粗暴了,项目中不太会这样用。不过一些非常简单的定制已经可以满足大部分的需求了,了解下:
class ProfileEditForm(forms.ModelForm):
template_name = "account/form_snippet.html"
class Meta:
model = Profile
fields = ('date_of_birth','photo')
labels = {
'date_of_birth':'出生日期',
'photo':'我的头像',
}
widgets = {
"date_of_birth":forms.TextInput(attrs={"class":"form-control"})
}
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
# self.fields['date_of_birth'].widget.attrs.update({'class':'form-control'})
self.fields['photo'].widget.attrs.update({'class':'form-control'})
大部分参数都是在Meta下配置的
model:需要绑定的model
fields:需要绑定表单的字段
labels:因为Model中的字段名都是英文,这里可以设置如何显示label
widgets:定制css样式
定义CSS样式的另一个方式是在初始化方法中定制self.fields[].widget.attrs.update()
HTML代码片段和在forms.Form用法是一样的
片段实例account/form_snippet.html
{% for field in form %}
<div>
{{ field.errors }}
<label for="{{ field.id_for_label }}" class="form-label" >
{{ field.label }}
</label>
{{ field }}
</div>
<p> </p>
{% endfor %}
这里没有使用widget-tweaks,所以没有引入{% load widget_tweaks %}
因为input的样式通过widgets写到了表单类中。