[form对象].is_valid( )
方法进行校验, 校验通过返回**True[form对象].cleaned_data
获得校验后的数据[form对象].errors
获得错误信息简单的用户注册界面示例
属性 | 释义 |
---|---|
min_length | 最小长度 |
max_length | 最大长度 |
require | 该字段必须得填 |
label | 该字段的标签 |
建议在应用文件夹下创建一个专门存放forms组件的文件 (不创建直接写在views.py中也可以)
导入组件并创建类
from django import forms
class RegisterForm(forms.Form):
# 校验name字段,最大长度为8,最短为3,下面的字段类似
name = forms.CharField(max_length=8, min_length=3, lable=‘用户名‘)
password = forms.CharField(max_length=10, min_length=4, lable=‘密码‘)
re_password = forms.CharField(max_length=10, min_length=4, lable=‘确认密码‘)
email = forms.EmailField(lable=‘邮箱‘)
from app01.myform import RegisterForm
def register(request):
if request.method == ‘POST‘:
# 实例得到form对象,将需要校验的数据传入(数据可以是前端传过来的数据,也可以是自己后端已有的数据)
# dic = {‘name‘:‘shawn‘,‘password‘:‘1111‘,‘re_password‘:‘1111‘,‘email‘:‘123@qq.com‘}
# form_data = RegisterForm(dic) # 示例:直接将已有的数据传入
form_data = RegisterForm(request.POST) # 将前端post请求的数据传入
# 进行校验 is_valid()
if form_data.is_valid():
print(‘校验成功‘)
# 获得校验成功的数据 cleaned_data
print(form_data.cleaned_data)
return HttpResponse(‘校验成功‘)
else:
print(‘检验失败‘)
# 获得检验失败的错误提示 errors
print(form_data.errors)
# forms组件可以自动生成HTML代码,因此可以直接在页面上进行显示
form_data = RegisterForm() # 先产生form空对象,再将其传给前端
return render(request, ‘re_form.html‘, {‘form‘: form_data})
ps :
cleaned_data
属性必须是经过is_valid( )
校验之后才产生的, 在校验之前使用会报错 : 属性不存在
re_path(‘^re_form/‘, views.register)
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading">注册页面</div>
<div class="panel-body">
<form action="" method="post">
<p>用户名:{{ form.name }}</p>
<p>密码:{{ form.password }}</p>
<p>确认密码:{{ form.re_password }}</p>
<p>邮箱:{{ form.email }}</p>
<br>
<input type="submit" class="btn btn-block btn-success" value="注册">
</form>
</div>
</div>
</div>
</div>
</div>
<form action="" method="post">
<p>用户名:{{ form.name }}</p>
<p>密码:{{ form.password }}</p>
<p>确认密码:{{ form.re_password }}</p>
<p>邮箱:{{ form.email }}</p>
<br>
<input type="submit" class="btn btn-block btn-success" value="注册">
</form>
<form action="" method="post">
<p>{{ form.name.label }}:{{ form.name }}</p>
<p>{{ form.password.label }}:{{ form.password }}</p>
<p>{{ form.re_password.label }}:{{ form.re_password }}</p>
<p>{{ form.email.label }}:{{ form.email }}</p>
<br>
<input type="submit" class="btn btn-block btn-success" value="注册">
</form>
<form action="" method="post" novalidate>
{% for foo in form %}
<div class="form-group">
{# 循环取出 name,password,re_password,email #}
<p>{{ foo.label }}:{{ foo }}</p>
</div>
{% endfor %}
<input type="submit" class="btn btn-block btn-success" value="注册">
</form>
<form action="" method="post" novalidate>
{{ form.as_p }} {# 与上两种显示方式相同 #}
{{ form.as_ul }} {# 前面带点 #}
{{ form.as_table }} {# 在一行显示 #}
<input type="submit" class="btn btn-block btn-success" value="注册">
</form>
from django import forms
from django.forms import widgets
class RegisterForm(forms.Form):
# 校验name字段,最大长度为8,最短为3,下面的字段类似
name = forms.CharField(max_length=8, min_length=3, label=‘用户名‘,
# 自定义错误信息
error_messages={
‘min_length‘: ‘用户名最少3位!‘,
‘max_length‘: ‘用户账户最大8位‘,
‘required‘: ‘用户名不能为空!‘,
},
# 添加一个form-control类
widget=widgets.TextInput(attrs={‘class‘:‘form-control‘}))
password = forms.CharField(max_length=10, min_length=4, label=‘密码‘,
error_messages={
‘min_length‘: ‘密码最少4位!‘,
‘max_length‘: ‘密码最大10位‘,
‘required‘: ‘密码不能为空!‘,
},
widget=widgets.PasswordInput(attrs={‘class‘:‘form-control‘}))
re_password = forms.CharField(max_length=10, min_length=4, label=‘确认密码‘,
error_messages={
‘min_length‘: ‘密码最少4位!‘,
‘max_length‘: ‘密码最大10位‘,
‘required‘: ‘密码不能为空!‘,
},
widget=widgets.PasswordInput(attrs={‘class‘:‘form-control‘}))
email = forms.EmailField(label=‘邮箱‘,
error_messages={
‘invalid‘: ‘邮箱格式不正确‘,
‘required‘: ‘邮箱不能为空‘,
},
widget=widgets.TextInput(attrs={‘class‘:‘form-control‘}))
from app01.myform import RegisterForm
def register(request):
if request.method == ‘POST‘:
form_data = RegisterForm(request.POST) # 将前端post请求的数据传入
if form_data.is_valid():
print(form_data.cleaned_data)
return HttpResponse(‘校验成功‘)
else:
# 将带有错误信息的form对象返回前端页面
return render(request, ‘re_form.html‘, {‘form‘: form_data})
form_data = RegisterForm() # 将form对象传给前端
return render(request, ‘re_form.html‘, {‘form‘: form_data})
<form action="" method="post" novalidate>
{% for foo in form %}
{# 在后方设置一个span标签用来放错误提示 #}
<p>{{ foo.label }}:{{ foo }}
<span style="color: red">{{ foo.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit" class="btn btn-block btn-success" value="注册">
</form>
ps :
<form action="" method="post" novalidate>
: form 表单标签内的novalidate
表示前端不进行校验
def clean_字段名(self):
字段值 = self.cleaned_data.get(‘字段名‘)
[判断逻辑代码]
[不通过抛出 ValidationError 异常]
[通过则返回该字段值]
def clean(self):
字段值1 = self.cleaned_data.get(‘字段1‘)
字段值2 = self.cleaned_data.get(‘字段2‘)
[判断逻辑代码]
[不通过抛出 ValidationError 异常]
[通过则 return self.cleaned_data]
myform.py 新增钩子函数
# 局部钩子
def clean_name(self):
name = self.cleaned_data.get(‘name‘)
for i in [‘爱德华‘,‘sb‘]:
if i in name:
raise ValidationError(f‘用户名中包含敏感词汇:"{i}"‘)
else:
return name
# 全局钩子
def clean(self):
password = self.cleaned_data.get(‘password‘)
re_password = self.cleaned_data.get(‘re_password‘)
if password == re_password:
return self.cleaned_data
else:
raise ValidationError(‘两次密码不一致‘)
views.py 文件
from app01.myform import RegisterForm
def register(request):
if request.method == ‘POST‘:
form_data = RegisterForm(request.POST) # 将前端post请求的数据传入
if form_data.is_valid():
return HttpResponse(‘校验成功‘)
else:
# 获取到 ValidationError 中的 error 信息传给前端
error = form_data.errors.get(‘__all__‘)
return render(request, ‘re_form.html‘, {‘form‘: form_data,‘error‘:error})
form_data = RegisterForm() # 将form空对象传给前端
return render(request, ‘re_form.html‘, {‘form‘: form_data})
re_form.html 文件
<form action="" method="post" novalidate>
{% for foo in form %}
<p>{{ foo.label }}:{{ foo }}
<span style="color: red; display:inline-block">{{ foo.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit" class="btn btn-block btn-success" value="注册">
{# 判断错误信息是否为None,是None就不渲染error #}
{% if error is None %}
<span style="color: red; display:inline-block"></span>
{% else %}
<span style="color: red; display:inline-block">{{ error }}</span>
{% endif %}
</form>
需求一演示 :
需求二演示 :
else:
print(‘检验失败‘)
# 获得检验失败的错误提示 errors
print(form_data.errors)
为什么是一个
ul
标签格式, 一定是重写了__str__
方法
from django.forms.utils import ErrorDict
发现其内部重写了
__str__
方法, 返回的是as_ul
方法, 该方法内部就是定义了html的格式并返回并且还有一些其他的方法 : 比如 json 格式, data 数据, text 格式等等
而返回
as_ul
方法则是为了方便渲染模板
username = forms.CharField(
min_length=8,
label="用户名",
initial="shawn" # 设置默认值
)
username = forms.CharField(
min_length=8,
label="用户名",
initial="shawn",
error_messages={
"required": "不能为空",
"invalid": "格式错误",
"min_length": "用户名最短8位"
}
)
# 设置render_value在输入错误的时候, 保留输入的内容value值
pwd = forms.CharField(
min_length=4,
label="密码",
widget=forms.widgets.PasswordInput(attrs={‘class‘: ‘a1‘}, render_value=True)
)
gender = forms.fields.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "未知")),
label="性别",
initial=3,
widget=forms.widgets.RadioSelect()
)
keep = forms.ChoiceField(
label="是否记住密码",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
Copyhobbies1 = forms.MultipleChoiceField(
choices=((1, "read"), (2, "run"), (3, "play"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
Copyeducation = forms.ChoiceField(
choices=((1, "高中"), (2, "中专"), (3, "大专"), (4, "本科"), (5, "研究生"), (6, "硕士")),
label="学历",
initial=3,
widget=forms.widgets.Select(attrs={‘class‘: ‘form-control‘})
)
Copyhobbies2 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 2],
widget=forms.widgets.SelectMultiple(attrs={‘class‘: ‘form-control‘})
)
插件名称 | 对应input |
---|---|
TextInput | input type="text" |
PasswordInput | input type="password" |
HiddenInput | input type="hidden" |
NumberInput | input type="number" |
EmailInput | input type="email" |
URLInput | input type="url" |
Textarea | textarea |
DateInput | input type="data" |
DateTimeInput | input type="datetime" |
TimeInput | 只获取时分秒 |
CheckboxInput | input type="checkbox" |
CheckboxSelectMultiple | 多选按钮 |
Select | select框 |
NullBooleanSelect | select框 三个选项 0 1 null |
SelectMultiple | 可多选的select框 |
RadioSelect | input type="radion" |
FileInput | 可以查看当前目录下的所有文件。作用不大 |
原文:https://www.cnblogs.com/songhaixing/p/14589384.html