1、校验字段功能

1、reg页面准备

models

from django.db import models

class UserInfo(models.Model):
useranme = models.CharField(max_length=32)
password = models.CharField(max_length=32)
email = models.EmailField()
telephone = models.CharField(max_length=32)

生成数据表

C:\PycharmProjects\formsdemo>python manage.py makemigrations
C:\PycharmProjects\formsdemo>python manage.py migrate

主url

from django.contrib import admin
from django.urls import path, re_path, include urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^', include(('app01.urls', 'app01')))
]

url

from django.urls import path, re_path, include
from app01 import views urlpatterns = [
re_path(r'reg/$', views.reg, name='reg'),
]

模板层

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>用户名 <input type="text" name="user"></p>
<p>密码 <input type="password" name="pwd"></p>
<p>确认密码 <input type="password" name="_pwd"></p>
<p>邮箱 <input type="text" name="email"></p>
<p>手机号 <input type="text" name="tel"></p>
<input type="submit" value="注册">
</form> </body>
</html>

view

from django.shortcuts import render, HttpResponse

def reg(request):
if request.method == 'POST':
print(request.POST)
return HttpResponse('注册成功') return render(request, 'reg.html')

<QueryDict: {'csrfmiddlewaretoken': ['5EwZsUEKRVj836bplmS03PVruttZhG'], 'user': ['alex'], 'pwd': ['123'], '_pwd': ['123'], 'email': ['123@qq.com'], 'tel': ['1234566778']}>

  

2、定义规则

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10)
email = forms.EmailField()

3、form.is_valid()

reg视图代码

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10)
email = forms.EmailField() def reg(request):
if request.method == 'POST': # 1.form.is_valid() 是否通过验证
form = UserForm({'name': 'alex', 'email': '123@qq.com'})
print(form.is_valid()) # True 返回布尔值 form = UserForm({'name': 'a', 'email': ''})
print(form.is_valid()) # False form = UserForm({'name': 'alex', 'email': '123@qq.com', 'age': ''})
print(form.is_valid()) # True
#
form = UserForm({'name': 'alex', 'xxx': '123@qq.com'})
print(form.is_valid()) # False form = UserForm({'name': 'a', 'email': '', 'xxx': ''})
print(form.is_valid()) # False if form.is_valid():
pass
else:
pass """
forms组件只会校验定义过的字段,
定义的data,必须满足条件且存在 True
多余的字段,不影响
"""
return HttpResponse('注册成功') return render(request, 'reg.html')

4、form.cleaned_data:清洗过的数据   form.errors:报错信息

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10)
email = forms.EmailField() def reg(request):
if request.method == 'POST': # 1.form.is_valid() 是否通过验证
form = UserForm({'name': 'alex', 'email': '123@qq.com'})
print(form.is_valid()) # True 返回布尔值 form = UserForm({'name': 'a', 'email': ''})
print(form.is_valid()) # False form = UserForm({'name': 'alex', 'email': '123@qq.com', 'age': ''})
print(form.is_valid()) # True
#
form = UserForm({'name': 'alex', 'xxx': '123@qq.com'})
print(form.is_valid()) # False form = UserForm({'name': 'a', 'email': '', 'xxx': ''})
print(form.is_valid()) # False # 2. form.cleaned_data
# form.errors
if form.is_valid():
print('cleaned_data1:', form.cleaned_data)
print('errors1:', form.errors)
else:
print('cleaned_data2:', form.cleaned_data)
print('errors2:', form.errors) # 取出error——msg
print(form.errors.get("name"))
print(type(form.errors.get("name"))) # ErrorList
print(form.errors.get("name")[0]) # Ensure this value has at least 4 characters (it has 1). """
if 所有字段校验成功,则
form.cleaned_data: {'name': 'alex', 'email': '123@qq.com'} 只保留定义过的字段
form.errors: 空 if 校验不成功,则
form.cleaned_data:{'name': 'alex'} 只保留定义过的字段,
form.errors: <li>email<ul class="errorlist"> 定义过的字段,未通过的信息 (cleaned_data + errors 之和,必定是定义过的所有字段)
""" return HttpResponse('注册成功') return render(request, 'reg.html')

(1)验证通过

验证字段

(2)验证不通过

  示例1:验证字段

  示例2:验证字段

5、取出 forms.error错误信息

6、完整演示代码

url

from django.urls import path, re_path, include
from app01 import views urlpatterns = [
re_path(r'reg_test/$', views.reg_test, name='reg_test'),
]

view

from django.shortcuts import render, HttpResponse

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10)
pwd = forms.CharField(min_length=4)
_pwd = forms.CharField(min_length=4)
email = forms.EmailField()
tel = forms.CharField() def reg_test(request):
if request.method == "POST":
form = UserForm(request.POST) # from表单的name属性值应该与forms组件字段名称一致
print(form) if form.is_valid():
print(form.cleaned_data)
return HttpResponse("注册成功")
else:
print(form.cleaned_data) # {'email': '123@qq.com', 'tel': 'a3456789'}
print(form.errors) # <ul class="errorlist"><li>name<ul class="errorlist"><li>This fie print(type(form.errors)) # ErrorList
print(form.errors.get('name')) # <ul class="errorlist"><li>This field is required.</li></ul>
print(type(form.errors.get('name'))) # ErrorList
print(form.errors.get('name')[0]) # This field is required.
return HttpResponse("注册失败") return render(request, 'reg.html')

html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>用户名 <input type="text" name="user"></p>
<p>密码 <input type="password" name="pwd"></p>
<p>确认密码 <input type="password" name="_pwd"></p>
<p>邮箱 <input type="text" name="email"></p>
<p>手机号 <input type="text" name="tel"></p>
<input type="submit" value="注册">
</form> </body>
</html>

注意点:

from表单的name属性值应该与forms组件字段名称一致

<tr><th><label for="id_name">Name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="name" maxlength="10" minlength="4" required id="id_name" /></td></tr>
<tr><th><label for="id_pwd">Pwd:</label></th><td><ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul><input type="text" name="pwd" value="123" minlength="4" required id="id_pwd" /></td></tr>
<tr><th><label for="id__pwd"> pwd:</label></th><td><ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul><input type="text" name="_pwd" value="123" minlength="4" required id="id__pwd" /></td></tr>
<tr><th><label for="id_email">Email:</label></th><td><input type="email" name="email" value="123@qq.com" required id="id_email" /></td></tr>
<tr><th><label for="id_tel">Tel:</label></th><td><input type="text" name="tel" value="a3456789" required id="id_tel" /></td></tr>

UserForm(request.POST)

2、forms组件的渲染标签功能

1、方式1: 用户名 {{ form.name }}

views

from django.shortcuts import render, HttpResponse

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10)
pwd = forms.CharField(min_length=4)
r_pwd = forms.CharField(min_length=4)
email = forms.EmailField()
tel = forms.CharField() def reg_html(request):
form = UserForm() return render(request, 'reg_html.html', locals())

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <h3>forms组件渲染方式1</h3>
<form action="" method="post">
{% csrf_token %}
<p>{{ form.name.label }} {{ form.name }}</p>
<p>{{ form.pwd.label }} {{ form.pwd }}</p>
<p>{{ form.r_pwd.label }} {{ form.r_pwd }}</p>
<p>{{ form.email.label }} {{ form.email }}</p>
<p>{{ form.tel.label }} {{ form.tel }}</p>
<input type="submit" value="注册">
</form> </body>
</html>

原生标签与渲染标签的区别

 

2、方式2:推荐

views视图

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10, label="用户名")
pwd = forms.CharField(min_length=4, label="密码")
r_pwd = forms.CharField(min_length=4, label="确认密码")
email = forms.EmailField(label="邮箱")
tel = forms.CharField(label="电话") def reg_html(request):
form = UserForm() return render(request, 'reg_html.html', locals())

html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <h3>forms组件渲染方式2:推荐</h3>
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
<p><label for="">{{ field.label }}:</label>{{ field }}</p>
{% endfor %} </form> </body>
</html>

3、方式3: {{ form.as_p }}  不灵活

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <h3>forms组件渲染方式3 </h3>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<hr>
{{ form.as_ul }}
<hr>
{{ form.as_table }}
</form> </body>
</html>

3、显示error与重置输入信息功能

views视图

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms   # 导入forms组件

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4, max_length=10, label="用户名")
pwd = forms.CharField(min_length=4, label="密码")
r_pwd = forms.CharField(min_length=4, label="确认密码")
email = forms.EmailField(label="邮箱")
tel = forms.CharField(label="电话") def reg_html(request):
if request.method == 'POST':
form = UserForm(request.POST) if form.is_valid():
print(form.cleaned_data) # 所有感觉的字段以及对应的值
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict: {"校验错误的字段":["错误信息"]}
print(form.errors.get('name')) # ErrorList {'错误信息',}
return render(request, 'reg_html.html', locals()) form = UserForm()
return render(request, 'reg_html.html', locals())

html

novalidate  当提交表单时不对表单数据(输入)进行验证

  

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <h3>forms组件渲染方式1</h3>
{# novalidate 当提交表单时不对表单数据(输入)进行验证#}
<form action="" method="post" novalidate>
{% csrf_token %}
<p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p>
<p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p>
<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p>
<p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p>
<p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p>
<input type="submit" value="注册">
</form> </body>
</html>

4、forms组件的参数配置

forms组件 代码

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms  # 导入forms组件

from django.forms import widgets   # HTML Widget classes

# 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4,
max_length=10,
label="用户名",
error_messages={'required': '该字段不能为空', 'min_length': '不能少于4个字符'},
# widget=widgets.TextInput(), # 定制Html控件
widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加样式
)
pwd = forms.CharField(min_length=4,
label="密码",
# widget=widgets.PasswordInput(), # 定制Html控件
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
error_messages={'required': '该字段不能为空'},
)
r_pwd = forms.CharField(min_length=4,
label="确认密码",
error_messages={'required': '该字段不能为空'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
)
email = forms.EmailField(label="邮箱",
error_messages={'required': '该字段不能为空', 'invalid': '格式错误'},
widget=widgets.EmailInput(attrs={'class': 'form-control'})
)
tel = forms.CharField(label="电话",
error_messages={'required': '该字段不能为空 '},
widget=widgets.TextInput(attrs={'class': 'form-control'})
) def reg_html(request):
if request.method == 'POST':
form = UserForm(request.POST) if form.is_valid():
print(form.cleaned_data) # 所有清洗的字段以及对应的值
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict: {"校验错误的字段":["错误信息"]}
print(form.errors.get('name')) # ErrorList {'错误信息',}
return render(request, 'reg_html.html', locals()) form = UserForm()
return render(request, 'reg_html.html', locals())

加入bootstrap后的 html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style type="text/css">
span{
color: red;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h3>forms组件渲染方式1</h3>
{# novalidate 当提交表单时不对表单数据(输入)进行验证#}
<form action="" method="post" novalidate>
{% csrf_token %}
<p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p>
<p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p>
<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p>
<p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p>
<p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p>
<input type="submit" value="注册">
</form>
</div>
</div>
</div> </body>
</html>

5、forms组件的局部钩子

1、ValidationError:验证错误

models

from django.db import models

class UserInfo(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
email = models.EmailField()
tel = models.CharField(max_length=32)

froms组件,如何进行验证错误?

from app01.models import UserInfo       # 导入user表
from django.core.exceptions import ValidationError # 导入验证错误 from django import forms # 导入forms组件
from django.forms import widgets # HTML Widget classes # 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4,
max_length=10,
label="用户名",
error_messages={'required': '该字段不能为空', 'min_length': '不能少于4个字符'},
# widget=widgets.TextInput(), # 定制Html控件
widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加样式
)
pwd = forms.CharField(min_length=4,
label="密码",
# widget=widgets.PasswordInput(), # 定制Html控件
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
error_messages={'required': '该字段不能为空'},
)
r_pwd = forms.CharField(min_length=4,
label="确认密码",
error_messages={'required': '该字段不能为空'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
)
email = forms.EmailField(label="邮箱",
error_messages={'required': '该字段不能为空', 'invalid': '格式错误'},
widget=widgets.EmailInput(attrs={'class': 'form-control'})
)
tel = forms.CharField(label="电话",
error_messages={'required': '该字段不能为空 '},
widget=widgets.TextInput(attrs={'class': 'form-control'})
) # 验证用户名
def clean_name(self):
val = self.cleaned_data.get("name") # 获取清洗后的字段中的name ret = UserInfo.objects.filter(name=val) # 数据库中的user
if not ret:
return ret
else:
raise ValidationError('该用户已经注册') # 验证错误

forms组件源码

vies视图中

def reg_html(request):
if request.method == 'POST':
form = UserForm(request.POST) if form.is_valid():
print(form.cleaned_data) # 所有清洗的字段以及对应的值
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict: {"校验错误的字段":["错误信息"]}
print(form.errors.get('name')) # ErrorList {'错误信息',}
return render(request, 'reg_html.html', locals()) form = UserForm()
return render(request, 'reg_html.html', locals())

模板层:不变

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style type="text/css">
span{
color: red;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h3>forms组件渲染方式1</h3>
{# novalidate 当提交表单时不对表单数据(输入)进行验证#}
<form action="" method="post" novalidate>
{% csrf_token %}
<p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p>
<p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p>
<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p>
<p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p>
<p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p>
<input type="submit" value="注册">
</form>
</div>
</div>
</div> </body>
</html>

2、校验方法:clean_name 源码

_clean_fields 方法的源码
    def _clean_fields(self):
for name, field in self.fields.items(): # {"name": name规则对象,"pwd": pwd规则对象...}
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
if field.disabled:
value = self.get_initial_for_field(field, name)
else:
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.get_initial_for_field(field, name)
value = field.clean(value, initial)
else:
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 # 执行 def clean_name(self):
except ValidationError as e:
self.add_error(name, e)

3、局部钩子函数如何校验

1、forms代码:校验name,tel

from app01.models import UserInfo       # 导入user表
from django.core.exceptions import ValidationError # 导入验证错误 from django import forms # 导入forms组件
from django.forms import widgets # HTML Widget classes # 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4,
max_length=10,
label="用户名",
error_messages={'required': '该字段不能为空', 'min_length': '不能少于4个字符'},
# widget=widgets.TextInput(), # 定制Html控件
widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加样式
)
pwd = forms.CharField(min_length=4,
label="密码",
# widget=widgets.PasswordInput(), # 定制Html控件
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
error_messages={'required': '该字段不能为空'},
)
r_pwd = forms.CharField(min_length=4,
label="确认密码",
error_messages={'required': '该字段不能为空'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
)
email = forms.EmailField(label="邮箱",
error_messages={'required': '该字段不能为空', 'invalid': '格式错误'},
widget=widgets.EmailInput(attrs={'class': 'form-control'})
)
tel = forms.CharField(label="电话",
error_messages={'required': '该字段不能为空 '},
widget=widgets.TextInput(attrs={'class': 'form-control'})
) # 验证用户名
def clean_name(self):
val = self.cleaned_data.get("name") # 获取清洗后的字段中的name ret = UserInfo.objects.filter(name=val) # 数据库中的user
if not ret:
return ret
else:
raise ValidationError('该用户已经注册') # 验证错误 # 验证手机号
def clean_tel(self):
val = self.cleaned_data.get("tel")
if len(val) == 11:
return val
else:
raise ValidationError("手机号格式错误")

示例1:校验错误

示例2:校验正确

4、全局钩子校验

1、全局钩子clean 源码剖析

2、直接覆盖父类的clean方法,全局钩子

froms组件继承的是BaseFrom类,所以可以直接覆盖父类的clean方法,进行全局钩子校验

views视图

from django.shortcuts import render, HttpResponse

from app01.models import UserInfo       # 导入user表
from django.core.exceptions import ValidationError # 导入验证错误 from django import forms # 导入forms组件
from django.forms import widgets # HTML Widget classes # 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4,
max_length=10,
label="用户名",
error_messages={'required': '该字段不能为空', 'min_length': '不能少于4个字符'},
# widget=widgets.TextInput(), # 定制Html控件
widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加样式
)
pwd = forms.CharField(min_length=4,
label="密码",
# widget=widgets.PasswordInput(), # 定制Html控件
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
error_messages={'required': '该字段不能为空'},
)
r_pwd = forms.CharField(min_length=4,
label="确认密码",
error_messages={'required': '该字段不能为空'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
)
email = forms.EmailField(label="邮箱",
error_messages={'required': '该字段不能为空', 'invalid': '格式错误'},
widget=widgets.EmailInput(attrs={'class': 'form-control'})
)
tel = forms.CharField(label="电话",
error_messages={'required': '该字段不能为空 '},
widget=widgets.TextInput(attrs={'class': 'form-control'})
)
# 直接覆盖父类的clean方法, 全局钩子
def clean(self):
pwd = self.cleaned_data.get("pwd")
r_pwd = self.cleaned_data.get("r_pwd")
if pwd == r_pwd:
return self.cleaned_data
else:
raise ValidationError("两次密码不一致") def reg_html(request):
if request.method == 'POST':
form = UserForm(request.POST) if form.is_valid():
print(form.cleaned_data) # {"name": "alex", "pwd": "123",...}
else:
print(form.cleaned_data) # # 所有清洗的字段以及对应的值
print(form.errors) # ErrorDict: {"校验错误的字段":["错误信息"]}
print(form.errors.get('name')) # ErrorList {'错误信息',} # 获取全局钩子的error
print("error:", form.errors.get("__all__")[0])
errors = form.errors.get("__all__") return render(request, 'reg_html.html', locals()) form = UserForm()
return render(request, 'reg_html.html', locals())

html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style type="text/css">
span{
color: red;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h3>forms组件渲染方式1</h3>
{# novalidate 当提交表单时不对表单数据(输入)进行验证#}
<form action="" method="post" novalidate>
{% csrf_token %}
<p>{{ form.name.label }} {{ form.name }} <span>{{ form.name.errors.0 }}</span></p>
<p>{{ form.pwd.label }} {{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p>
{# <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> 局部钩子错误#}
<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span class="pull-right error">{{ errors.0 }}</span></p>
<p>{{ form.email.label }} {{ form.email }} <span>{{ form.email.errors.0 }}</span></p>
<p>{{ form.tel.label }} {{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p>
<input type="submit" value="注册">
</form>
</div>
</div>
</div> </body>
</html>

重点

# 接收全局钩子error   errors.0
# bootstarp样式 <span class="pull-right error">
<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span class="pull-right error">{{ errors.0 }}</span></p>

5、密码,确认密码,顺序

# 每个字段校验完,在走全局方法

 比如,先判断密码是否正确,符合规则再判断,两次密码是否一致

  

如果没有pwd传入进来的话,

    # 直接覆盖父类的clean方法, 全局钩子
def clean(self):
pwd = self.cleaned_data.get("pwd")
r_pwd = self.cleaned_data.get("r_pwd") # 先判断是否接受到pwd,r_pwd的值
if pwd and r_pwd:
if pwd == r_pwd:
return self.cleaned_data
else:
raise ValidationError("两次密码不一致")
else:
return self.cleaned_data

6、form.is_valid 调用源码

form.is_valid

def is_valid(self):
"""Return True if the form has no errors, or False otherwise."""
return self.is_bound and not self.errors def errors(self):
"""Return an ErrorDict for the data provided for the form."""
if self._errors is None:
self.full_clean()
return self._errors def full_clean(self):
"""
Clean all of self.data and populate self._errors and self.cleaned_data.
"""
self._errors = ErrorDict()
if not self.is_bound: # Stop further processing.
return
self.cleaned_data = {}
# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
return self._clean_fields() # 校验每一个字段
self._clean_form() # 校验全部字段
self._post_clean()
# 局部钩子
def _clean_fields(self):
for name, field in self.fields.items(): # 校验每一个字段
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
if field.disabled:
value = self.get_initial_for_field(field, name)
else:
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.get_initial_for_field(field, name)
value = field.clean(value, initial)
else:
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)
# 全局钩子调用顺序

        def _clean_form(self):
try:
cleaned_data = self.clean() # 全局钩子
except ValidationError as e:
self.add_error(None, e)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data def clean(self):
"""
Hook for doing any extra form-wide cleaning after Field.clean() has been
called on every field. Any ValidationError raised by this method will
not be associated with a particular field; it will have a special-case
association with the field named '__all__'.
"""
return self.cleaned_data @html_safe
class BaseForm:
"""
The main implementation of all the Form logic. Note that this class is
different than Form. See the comments by the Form class for more info. Any
improvements to the form API should be made to this class, not to the Form
class.
"""
def clean(self):
pass

7、总结:forms组件解耦,调用冲突

myforms.py  组件代码

from app01.models import UserInfo       # 导入user表
from django.core.exceptions import ValidationError # 导入验证错误
from django import forms # 导入forms组件
from django.forms import widgets # HTML Widget classes # 定义校验规则
class UserForm(forms.Form):
name = forms.CharField(min_length=4,
max_length=10,
label="用户名",
error_messages={'required': '该字段不能为空', 'min_length': '不能少于4个字符'},
# widget=widgets.TextInput(), # 定制Html控件
widget=widgets.TextInput(attrs={'class': 'form-control'}), # html控件添加样式
)
pwd = forms.CharField(min_length=4,
label="密码",
# widget=widgets.PasswordInput(), # 定制Html控件
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
error_messages={'required': '该字段不能为空'},
)
r_pwd = forms.CharField(min_length=4,
label="确认密码",
error_messages={'required': '该字段不能为空'},
widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
)
email = forms.EmailField(label="邮箱",
error_messages={'required': '该字段不能为空', 'invalid': '格式错误'},
widget=widgets.EmailInput(attrs={'class': 'form-control'})
)
tel = forms.CharField(label="电话",
error_messages={'required': '该字段不能为空 '},
widget=widgets.TextInput(attrs={'class': 'form-control'})
) # 验证用户名
def clean_name(self):
val = self.cleaned_data.get("name") # 获取清洗后的字段中的name ret = UserInfo.objects.filter(name=val) # 数据库中的user
if not ret:
return ret
else:
raise ValidationError('该用户已经注册') # 验证错误 # 验证手机号
def clean_tel(self):
val = self.cleaned_data.get("tel")
if len(val) == 11:
return val
else:
raise ValidationError("手机号格式错误") # 直接覆盖父类的clean方法, 全局钩子
def clean(self):
pwd = self.cleaned_data.get("pwd")
r_pwd = self.cleaned_data.get("r_pwd") # 先判断是否接受到pwd,r_pwd的值
if pwd and r_pwd:
if pwd == r_pwd:
return self.cleaned_data
else:
raise ValidationError("两次密码不一致")
else:
return self.cleaned_data

url

from django.urls import path, re_path, include
from app01 import views urlpatterns = [
re_path(r'reg_html/$', views.reg_html, name='reg_html'),
]

views视图代码

from django.shortcuts import render
from app01.myforms import * def reg_html(request):
if request.method == 'POST':
form = UserForm(request.POST) if form.is_valid():
print(form.cleaned_data) # {"name": "alex", "pwd": "123",...}
else:
print(form.cleaned_data) # # 所有清洗的字段以及对应的值
print(form.errors) # ErrorDict: {"校验错误的字段":["错误信息"]}
print(form.errors.get('name')) # ErrorList {'错误信息',} # 获取全局钩子的error
# print("error:", form.errors.get("__all__")[0])
errors = form.errors.get("__all__") return render(request, 'reg_html.html', locals()) form = UserForm()
return render(request, 'reg_html.html', locals())

模板层

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style type="text/css">
span{
color: red;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-lg-offset-3">
<h3>forms组件渲染方式1</h3>
{# novalidate 当提交表单时不对表单数据(输入)进行验证#}
<form action="" method="post" novalidate>
{% csrf_token %}
<p>{{ form.name.label }} {{ form.name }} <span class="pull-right error">{{ form.name.errors.0 }}</span></p>
<p>{{ form.pwd.label }} {{ form.pwd }} <span class="pull-right error">{{ form.pwd.errors.0 }}</span></p>
{# 局部钩子错误 <p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p> #}
{# 全局钩子错误#}<p>{{ form.r_pwd.label }} {{ form.r_pwd }} <span class="pull-right error">{{ errors.0 }}</span></p>
<p>{{ form.email.label }} {{ form.email }} <span class="pull-right error">{{ form.email.errors.0 }}</span></p>
<p>{{ form.tel.label }} {{ form.tel }} <span class="pull-right error">{{ form.tel.errors.0 }}</span></p>
<input type="submit" value="注册">
</form>
</div>
</div>
</div> </body>
</html>

03、 forms组件的更多相关文章

  1. Python-S9—Day85-ORM项目实战之forms组件以及Modelform补充、跨域请求及应用

    01 forms组件补充1 02 forms组件补充2 03 ModelForm回顾 04 浏览器的历史 05 jsonop实现跨域请求 06 jsonop实现跨域请求2 07 jsonop实现跨域请 ...

  2. Django学习之八:forms组件【对form舒心了】

    目录 Django forms组件 bound and unbound form instance forms渲染有关 隐藏一个字段,不渲染它 form 校验 form类 ModelForm 利用Mo ...

  3. Django组件-Forms组件

    Django的Forms组件主要有以下几大功能: 页面初始化,生成HTML标签 校验用户数据(显示错误信息) HTML Form提交保留上次提交数据 一.小试牛刀 1.定义Form类 from dja ...

  4. Django组件--forms组件(注册用)

    一.forms组件--校验类的使用 二.form组件--校验类的参数 三.forms组件校验的局部钩子--自定义校验规则(要看源码理解) 四.forms组件校验的全局钩子--校验form表单两次密码输 ...

  5. web框架开发-Django的Forms组件

    校验字段功能 针对一个实例:用户注册. 模型:models.py class UserInfo(models.Model): name=models.CharField(max_length=32) ...

  6. python django(forms组件)

    forms组件最大的作用,就是做数据校验. 普通做法,一个一个写校验规则,没有解耦.校验规则,都在视图函数里面. 网页校验 修改urls.py,增加路径addbook from app01 impor ...

  7. Auth模块、Forms组件

    Auth模块 auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这 ...

  8. django之forms组件

    在django中forms组件有其强大的功能,里面集合和众多的函数和方法:下面来看一下它的源码 """ Form classes """ f ...

  9. forms组件

    昨日回顾: 批量插入数据: -queryset的方法:bulk_create(对象列表,数字(一次插入多少)) 分页器: from django.core.paginator import Pagin ...

随机推荐

  1. l2dct

    http://paste.ubuntu.com/15664711/ diff -crbB ns-allinone-2.35/ns-2.35/queue/red.cc ns-2.35/queue/red ...

  2. MyEclipse 智能提示设置

    在实际的开发当中,编译器没有智能提示,确实是效率很低,下面我就给大家讲一下在MyEclipse中设置智能提示,方便大家的开发,希望能帮到大家. 方法一:首先,在MyEclipse的菜单栏中找到wind ...

  3. golang 防知乎 中文验证码 源码

    原创,转载请注明出处! 最开始用图形来模仿文字进行各种角度的倒立和排列,后来切换为文字后,有很多问题.总结如下: 1.程序在画图形和画文字方面不一样,图形的是从原点开始(0,0),而文字则从文字的基线 ...

  4. PHP_CodeSniffer 使用攻略

    安装 PHP_CodeSniffer 安装 phpcs phpcs 是 PHP 代码规范的检测工具. # 下载 $ curl -OL https://squizlabs.github.io/PHP_C ...

  5. web开发方面会遇到哪些缓存?分别如何优化

    Web缓存定义: Web缓存游走于服务器和客户端之间,这个服务器可能是源服务器(资源所驻留的服务器Add),数量可能是1个或多个. Web缓存就在服务器-客户端之间搞监控,监控请求,并且把请求输出的内 ...

  6. PHP中抽象方法、抽象类和接口的用法

    在类中,没有方法体的方法就是抽象方法. abstract 可见性 function 方法名称(参数1,.....);      // 如果没有显示地指定可见性,则默认为public 如: public ...

  7. Hadoop HBase概念学习系列之行、行键(十一)

    行是由列簇中的列组成.行根据行键依照字典顺序排序. HBase的行使用行键标识,可以使用行键查询整行的数据. 对同一个行键的访问都会落在同样的物理节点上.如果表包含2个列簇,属于两个列簇的文件还是保存 ...

  8. 我遇到的问题:耗时久/效率低 ---> 应对方案: 行动-结果指向

    这一篇打的时候,时间都挺靠后的了, 当时出现错误,很慌了,一个是时间比较久,5点多了,一个是陈果已经做了很多题了,这些是事实. 导致我慌张的原因,简单来说是比较,长久以来,我都爱去和别人比较.如果赢了 ...

  9. 在web.xml中配置404错误拦截

    <error-page> <error-code>404</error-code> <location>/home.do</location> ...

  10. PHP SPL神器实现堆排序

    之前学习过内部排序的八大算法,也一一写过代码实现.其中堆排序的原理是 将一颗二叉树初始化为堆 依次将最后一个结点与堆顶结点交换.然后调整堆顶元素位置,重置堆. 将二叉树初始化为堆可以看做从最后一个非叶 ...