forms组件
-forms是什么?
就是一个类,可以校验字段(前台传过来的字段)
-怎么用:
*** {#浏览器的格式校验提示 novalidate取消提示: 可以提交 格式不符合浏览器格式 的数据 #}
<form method="post" novalidate></form>
-forms是什么?
就是一个类,可以校验字段(前台传过来的字段)
-怎么用:
*** {#浏览器的格式校验提示 novalidate取消提示: 可以提交 格式不符合浏览器格式 的数据 #}
<form method="post" novalidate></form>
***总结
from django import forms
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
from django.forms import widgets
from django.http import JsonResponse
class MyForm(forms.Form):
name=forms.CharField(max_length=8,min_length=3,widget=widgets.TextInput(attrs={'placeholder':'输入用户名','class':'form-control name'}),label='用户名:',error_messages={'max_length':'不能过8位'})
pwd=forms.CharField(max_length=8,min_length=3,widget=widgets.PasswordInput(attrs={'placeholder':'输入密码','class':'form-control pwd'}),label='密码',error_messages={'min_length':'不能少于3位'})
pwd2=forms.CharField(max_length=8,min_length=3,widget=widgets.PasswordInput(attrs={'placeholder':'重复密码','class':'form-control pwd2'}),label='重复密码',error_messages={'min_length':'不能少于3位'})
email=forms.EmailField(widget=widgets.EmailInput(attrs={'placeholder':'输入邮箱','class':'email form-control'}),label='邮箱',error_messages={})
tim=forms.DateTimeField(widget=widgets.TimeInput(attrs={'class':'form-control tim','placeholder':'输入时间'}),label='时间')
def clean_name(self):
name=self.cleaned_data.get('name')
if name=='123':
raise ValidationError('名字错误1')
return name
def clean(self):
pwd=self.cleaned_data.get('pwd')
pwd2=self.cleaned_data.get('pwd2')
if pwd==pwd2:
return self.cleaned_data
else:
raise ValidationError('密码不一致')
def ss(request):
if request.method=='GET':
dic={'name':'123','pwd':'45w','pwd2':'45aa','email':"123@qq.com",'tim':'2018-10-19 00:00:00','age':18}
f=MyForm(dic)
# print(f.cleaned_data) #报错 因为是校验后的数据
if f.is_valid(): #MyForm内【所有的字段】 第一次校验格式通过了 【再进行】 第二次逻辑校验了通过 走下面
print('校验成功字段1',f.cleaned_data)
else:#有一个字段,有一次校验没通过 走这里
print('校验成功段',f.cleaned_data)
print('所有失败的字段',f.errors.as_data())
#取出逻辑错误字段(错误种可能只有格式错误,所以要try)
#【第一次格式都没通过】,【不会进行/不存】在逻辑的【校验/错误】 2次密码格式都没通过只会报格式错误
try:
all=f.errors.as_data().get('__all__')[0]
print(type(all))
except Exception:
all=''
return render(request,'ss.html')
【视图函数部分】
-校验字段功能:
-先写一个类,继承Form
from django.shortcuts import render, HttpResponse
from django import forms
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
# 写一个类,要校验那些字段,就是类的属性
class MyForm(forms.Form):
# 定义一个属性,可以用来校验字符串类型
# 限制最大长度是8,最小长度是3
name=forms.CharField(max_length=8,min_length=3,label='用户名:',widget=widgets.TextInput(attrs={'class':'form-control name1',' placeholder':'大于3位小于8位'}),error_messages={'max_length':'不能超过8位数','min_length':'不能少于3位数','required':'*必填'})
pwd=forms.CharField(max_length=8,min_length=3,required=True)
# 校验是否是邮箱格式
email=forms.EmailField() # errors_messages有个
email=forms.EmailField() # errors_messages有个
'invalid':'邮箱地址格式错误'
def login(request):
#实例化产生对象,传入要校验的数据(字典)
myform=MyForm(request.POST)
# is_valid如果是true表示校验成功,反之,校验失败
#实例化产生对象,传入要校验的数据(字典)
myform=MyForm(request.POST)
# is_valid如果是true表示校验成功,反之,校验失败
#校验失败的信息( 总的一个失败的信息 )
print(myform.errors) #标签形式的错误信息
print(myform.errors) #标签形式的错误信息
print(myform.errors.as_data()) #字典形式的错误信息
if myform.is_valid(): (第一层校验的字段 通过)
# 校验通过的数据
print(myform.cleaned_data)
return HttpResponse('校验成功')
else:
print(myform.cleaned_data)
return render(request,'login.html',local())
【template层】
-注意:校验字段可以多,但是不能少
传过来的字典必须有form类的校验字段 少了
-渲染模板
-第一中方式:(灵活性最高)
<form action="" method="post" >
<p>用户名: {{ myform.name }}</p>
<p>密码: {{ myform.pwd }}</p>
<p>邮箱: {{ myform.email }}</p>
<input type="submit" value="提交">
</form>
-第二种方式:for循环form对象(用的比较多):
<form action="" method="post" >
{% for foo in myform %}
<p>{{ foo.label }}:{{ foo }}</p><span>{{ foo.errors.0 }}</span> #渲染错误信息
{% endfor %}
<input type="submit" value="提交">
</form>
-第三种方式(不建议用):
<form action="" method="post" >
{# {{ myform.as_p }}#}
{{ myform.as_ul }}
<input type="submit" value="提交">
</form>
-渲染错误信息(第一层校验(报错的字段 不会进行第二次校验))
if myform.is_valid(): (第一层校验的字段 通过)
# 校验通过的数据
print(myform.cleaned_data)
return HttpResponse('校验成功')
else:
print(myform.cleaned_data)
return render(request,'login.html',local())
【template层】
-注意:校验字段可以多,但是不能少
传过来的字典必须有form类的校验字段 少了
-渲染模板
-第一中方式:(灵活性最高)
<form action="" method="post" >
<p>用户名: {{ myform.name }}</p>
<p>密码: {{ myform.pwd }}</p>
<p>邮箱: {{ myform.email }}</p>
<input type="submit" value="提交">
</form>
-第二种方式:for循环form对象(用的比较多):
<form action="" method="post" >
{% for foo in myform %}
<p>{{ foo.label }}:{{ foo }}</p><span>{{ foo.errors.0 }}</span> #渲染错误信息
{% endfor %}
<input type="submit" value="提交">
</form>
-第三种方式(不建议用):
<form action="" method="post" >
{# {{ myform.as_p }}#}
{{ myform.as_ul }}
<input type="submit" value="提交">
</form>
-渲染错误信息(第一层校验(报错的字段 不会进行第二次校验))
错误信息都在 myform({字典}).errors.as_data() 字典内包含了1,2层 (有1的一层 没2层)
- myforms有errors
-属性(name)也有errors
-错误信息,变成中文:
- error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填','invalid': '不符合邮箱格式'}
-给input标签指定样式,指定格式:
-widget=widgets.TextInput(attrs={'class':'form-control'})
-模板,渲染第一层错误信息:<span>{{ myform.name.errors.0 }}</span>
-局部钩子校验(第二层校验)
-定义一个函数,名字叫:clean_字段名字,内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛异常(ValidationError)
- def clean_name(self):
# self:当前form对象
name = self.cleaned_data.get('name')
if name.startswith('sb'):
# 失败,抛异常
raise ValidationError('不能以傻逼开头')
# 正常,把name返回
return name
-全局钩子 (第二层校验)
#重写clean方法
def clean(self):
#程序能走到该函数,前面校验已经通过了,所以可以从cleaned_data中取出密码和确认密码
pwd=self.cleaned_data.get('pwd')
re_pwd=self.cleaned_data.get('re_pwd')
#进行自己的校验
if pwd==re_pwd:
#通过,直接返回cleaned_data
return self.cleaned_data
else:
#失败,抛异常(ValidationError)
raise ValidationError('两次密码不一致')
- myforms有errors
-属性(name)也有errors
-错误信息,变成中文:
- error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填','invalid': '不符合邮箱格式'}
-给input标签指定样式,指定格式:
-widget=widgets.TextInput(attrs={'class':'form-control'})
-模板,渲染第一层错误信息:<span>{{ myform.name.errors.0 }}</span>
-局部钩子校验(第二层校验)
-定义一个函数,名字叫:clean_字段名字,内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛异常(ValidationError)
- def clean_name(self):
# self:当前form对象
name = self.cleaned_data.get('name')
if name.startswith('sb'):
# 失败,抛异常
raise ValidationError('不能以傻逼开头')
# 正常,把name返回
return name
-全局钩子 (第二层校验)
#重写clean方法
def clean(self):
#程序能走到该函数,前面校验已经通过了,所以可以从cleaned_data中取出密码和确认密码
pwd=self.cleaned_data.get('pwd')
re_pwd=self.cleaned_data.get('re_pwd')
#进行自己的校验
if pwd==re_pwd:
#通过,直接返回cleaned_data
return self.cleaned_data
else:
#失败,抛异常(ValidationError)
raise ValidationError('两次密码不一致')
from django import forms
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
class Myform(forms.Form):
from django.forms import widgets
name=forms.CharField(max_length=8,min_length=3,label='用户名:',widget=widgets.TextInput(attrs={'class':'form-control name1',' placeholder':'大于3位小于8位'}),error_messages={'max_length':'不能超过8位数','min_length':'不能少于3位数','required':'*必填'})
pwd=forms.CharField(max_length=8,min_length=3,label='密码:',widget=widgets.PasswordInput(attrs={'class':'form-control pwd1','placeholder':'大于3位小于8位'}),error_messages={'max_length':'不能超过8位数','min_length':'不能少于3位数','required':'*必填',})
r_pwd=forms.CharField(max_length=8,min_length=3,label='确认密码:',widget=widgets.PasswordInput(attrs={'class':'form-control pwd2','placeholder':'大于3位小于8位'}),error_messages={'max_length':'不能超过8位数','min_length':'不能少于3位数','required':'*必填'})
email=forms.EmailField(widget=widgets.EmailInput(attrs={'class':'form-control email1','placeholder':'例如:www@qq.com'}),error_messages={'required':'不能为空','invalid':'邮箱地址格式错误'})
#'invalid':'格式错误'邮箱的格式
# 钩子:在上面error-messages格式校验之后 再次进行的数据校验(上面name数据格式没通过(前台显示错误),不会进行name数据校验.两个错误是独立的)
# 局部钩子
def clean_name(self):
name=self.cleaned_data.get('name')
names=models.Info.objects.only('name')
names=[i.name for i in names]
if name in names:
raise ValidationError('姓名已存在')
return name
# 全局钩子
def clean(self):
pwd=self.cleaned_data.get('pwd')
r_pwd=self.cleaned_data.get('r_pwd')
if pwd!=r_pwd:
raise ValidationError('密码不一致')
return self.cleaned_data
def form(request):
if request.method=='GET':
myform=Myform()
elif request.method=='POST':
myform=Myform(request.POST)
print (myform.errors.as_data ()) #所有的 错误信息(字段格式错误信息 局部钩子 全局钩子信息)
if myform.is_valid(): #通过格式校验
print('true',myform.cleaned_data) #格式 通过的数据{'name': '王冬123', 'pwd': 'bbbbbb', 'r_pwd': 'cccccc', 'email': '279829702@qq.com'}
return redirect('http://www.baidu.com')
else:
print('else',myform.cleaned_data) #格式 通过的数据
print(myform.errors) #type()为一个继承了dict的类
# ul class="errorlist"><li>name<ul class="errorlist"><li>不能少于3位数</li></ul></li><li>pwd<ul class="errorlist"><li>不能少于3位数</li></ul></li><li>r_pwd<ul class="errorlist"><li>不能少于3位数</li></ul></li><li>email<ul class="errorlist"><li>邮箱地址格式错误</li></ul></li></ul>
print (myform.errors.as_data ())
#{'name': [ValidationError(['不能少于3位数'])], 'pwd': [ValidationError(['不能少于3位数'])], 'r_pwd': [ValidationError(['不能少于3位数'])], 'email': [ValidationError(['邮箱地址格式错误'])]}
try:
all=myform.errors.as_data ().get('__all__')[0]
print(all)
except Exception:
pass
return render(request,'form.html',locals())
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
<script src="/static/bootstrap-3.3.7-dist/jquery-3.3.1.js"></script>
<script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</head>
<body>
<h1>注册</h1>
<div class="container-fluid " style="margin-top: 100px">
<div class="row">
<div class="col-xs-4 col-xs-offset-4">
{#浏览器的格式校验提示 novalidate取消提示: 可以提交格式不符合的数据 #}
<form method="post" novalidate>
{% for foo in myform %}
<div class="form-group">
{{ foo.label }}{{ foo }}<span style="color: red">{{ foo.errors.0 }}</span>
</div>
{% endfor %}
<button class="btn btn-default">提交 </button><span style="color: red" >{{ all.0 }}</span>
</form>
</div>
</div>
</div>
</body>
<script>
$('.btn').click(function () {
$.ajax({
url:"/form",
type:'post',
data:{'name':$('.name1').val(),'pwd':$('.pwd1').val(),'r_pwd':$('.pwd2').val(),'email':$('.email1').val()},
success(data){
}
});
})
if ($('span').text()){
$('input').val('');
$('html').click(function () {
$('span').text('');
})
}
</script>
</html>