django中定义form表单的优势
- HTML中提交后,若数据出现错误,返回的页面中仍然可以保留之前输入的数据。
- 通过校验规则可以方便的限制字段条件并校验。
先要确定给什么表单构建。
使用form类
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
#定义了一个form类,
字段最大长度max_length的定义,做了两件事,
1:在HTML的input上加了 maxlength="100"(浏览器会进行限制)
2:当Django收到浏览器发来的表单后,验证数据长度
渲染到HTML后:
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100">
注:不包含form标签和提交按钮,需要自己在HTML中写好。
is_valid
为所有字段进行验证,条件验证通过将:返回TRUE,将表单数据放到cleaned_data属性中。
视图
表单数据要通过视图处理,一般和发布的是同一个,可以重用相同逻辑。
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import NameForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
#如果访问视图的是一个GET 请求,它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。
#如果表单的提交使用POST 请求,那么视图将再次创建一个表单实例并使用请求中的数据填充它:form = NameForm(request.POST)。这叫做”绑定数据至表单“(它现在是一个绑定的表单)。
#调用表单的is_valid()方法;如果它不为True,我们将带着这个表单返回到模板。这时表单不再为空(未绑定),所以HTML 表单将用之前提交的数据填充,然后可以根据要求编辑并改正它。
#如果is_valid()为True,我们将能够在cleaned_data 属性中找到所有合法的表单数据。在发送HTTP 重定向给浏览器告诉它下一步的去向之前,我们可以用这个数据来更新数据库或者做其它处理。
HTML模板
最简单的:
<form action="/your-name/" method="post">
{% csrf_token %}{{ form }}
<input type="submit" value="Submit" />
</form>
#{{ form }}即服务端对应的表单
注:Django 原生支持一个简单易用的跨站请求伪造的防护。当提交一个启用CSRF 防护的POST 表单时,你必须使用上面例子中的csrf_token 模板标签。
Django Form类
绑定的和未绑定的表单实例
- 未绑定的没有关联数据。渲染时为空或默认值
- 绑定的包含提交来的数据,可检验数据是否合法。若不合法,将包含内联的错误信息,返回。
字段详解
from django import forms
class RegForm(forms.Form):
u = forms.CharField(max_length=10
,error_messages={"max_length":"最长10字符","required":"字段不能为空"})
p = forms.CharField(mix_length=8,
widget=widgets.PasswordInput(attrs={"placeholder":"password"})
gender = forms.CharField(initial=2,
widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)))
email = forms.EmailField()
is_married = forms.BooleanField(required=False)
)
widgets
对应HTML表单的widget(type的数据类型格式)
不同字段默认不同widget,默认charfield是textinput widget。在HTML 中生成一个<input type="text">。
字段的数据
提交通过is_valid验证后,验证后的表单数据将存放于form.cleaned_data字典中(数据类型转换已好)
使用表单模板
若在字段属性中设置label,则会渲染成对于<label>/<input> 对。
表单渲染的选项
输出选项:
{{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
{{ form.as_p }} 将它们渲染在<p> 标签中
{{ form.as_ul }} 将它们渲染在<li> 标签中
注意,若用table或ul。必须自己提供<table> 或<ul> 元素。
手动渲染
手工来做允许重新对字段排序。每个字段都是表单的一个属性。 使用{{ form.name_of_field }} 访问
<div class="fieldWrapper">
{{ form.Username.errors }}
{{ form.Username.label_tag }}
{{ form.Username }}
</div>
表单的错误信息及渲染
type(registerForm.errors)
#<class 'django.forms.utils.ErrorDict'> 错误清单,会渲染成ul
type(registerForm.errors["username"])
#<class 'django.forms.utils.ErrorList'>
form组件的钩子
即对接收到的form数据做自定义规则的判断。
定义Django的form时:
from django import forms class RegForm(forms.Form): username = forms.CharField(label='username', max_length=100) password = forms.CharField(label='password', max_length=100) repeat_password = forms.CharField(label='repeat_password',,max_length=100)
#钩子函数为对应字段添加判断条件。做最小长度判断 def clean_username(self): if len(self.cleaned_data.get("username"))>5: print(self.cleaned_data.get("password")) return self.cleaned_data.get("username") def clean_password(self): pass #全局钩子函数。判断两次密码输入是否一致 def clean(self): if self.cleaned_data["password"] == self.cleaned_data["repeat_password"]: return self.cleaned_data
———————————————————————————————————————————————————————————————————————————————————————
def foo(request):
if request.method=="POST":
regForm=RegForm(request.POST)
if regForm.is_valid():
pass
# 可用数据: regForm.cleaned_data,
# 将数据插入数据库表中
else:
pass
# 可用数据: regForm.errors
# 可以利用模板渲染讲errors嵌套到页面中返回
# 也可以打包到一个字典中,用于ajax返回
else:
regForm=RegForm()
return render(request,"register.html",{"regForm":regForm})
实例化时:
self.fields={
"username":"字段规则对象",
"password":"字段规则对象",
"repeat_password":"字段规则对象",
}
is_valid时:
self._errors = {}
self.cleaned_data = {}
#局部钩子:
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)
# 全局钩子:
self.clean() # def self.clean():return self.cleaned_data
return not self.errors # True或者False
Filed字段通用配置参数如下
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内容后缀