Django之forms组件
Posted sxy-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django之forms组件相关的知识,希望对你有一定的参考价值。
Django之forms组件
校验字段功能
# reg.html <form action="" method="post"> {% csrf_token %} <p>用户名<input type="text" name="username"></p> <p>密码<input type="text" name="password"></p> <p>确认密码<input type="text" name="pwd"></p> <p>邮箱<input type="email" name="email"></p> <p>手机号<input type="text" name="tel"></p> <input type="submit"> </form>
# views.reg from django import forms class User(forms.Form): name = forms.CharField(min_length=4) password = forms.CharField(min_length=4) pwd = forms.CharField(min_length=4,) email = forms.EmailField() tel = forms.CharField() def reg(request): if request.method == ‘POST‘: print(request.POST) form = User(request.POST) # 传过来的字典键名和forms的字段名要相同 才能实现检验的功能 # 已经校验的form 校验的字段信息会保留if form.is_valid(): # 传过来的键会一 一和User表中的字段进行对应,然后根据规则进行校验 字段可以多不可以少 少了字段或者校验不符 都为false print(form.cleaned_data) # cleaned_data都为校验forms字段中成功的键值 else: print(form.cleaned_data) print(123) # print(form.errors) # errors是一个字典 键为校验失败的字段名 值为一个列表 列表中存储错误信息 # print(type(form.errors)) # print(type(form.errors.get(‘name‘))) # print(form.errors.get(‘name‘)[0]) return render(request, ‘reg.html‘, locals()) form = User() return render(request, ‘reg.html‘, locals())
form.is_valid(): 传过来的键会一 一和User表中的字段进行对应,然后根据规则进行校验,字段可以多不可以少,少了字段或者校验不符,值都为false。
forms.cleaned_data 都为校验forms字段中成功的键值。
form.errors 是一个字典,键为校验失败的字段名,值为一个列表,列表中存储字段的错误信息。
渲染标签功能
上面说到,如果想要用forms对字段进行校验,就要求传入的name和自定义的类的字段名相同,但如果我们不想做这种操作怎么办?
forms提供了渲染标签的功能。
渲染方式1
from django import forms
class User(forms.Form):
name = forms.CharField(min_length=4, label=‘用户名‘)
password = forms.CharField(min_length=4, label=‘密码‘)
pwd = forms.CharField(min_length=4, label=‘确认密码‘)
email = forms.EmailField(label=‘邮箱‘)
tel = forms.CharField(label=‘电话‘)
def reg(request): if request.method == ‘POST‘: print(request.POST) form = User(request.POST) # 传过来的字典键名和forms的字段名要相同 才能实现检验的功能 # 已经校验的form 校验的字段信息会保留 print(form.is_valid()) if form.is_valid(): # 传过来的键 可以多但是不可以少 少了或者错了 都为false print(form.cleaned_data) # cleaned_data都为校验forms字段中成功的键值 else: print(form.cleaned_data) print(123) # print(form.errors) # errors是一个字典 键为校验失败的字段名 值为一个列表 列表中存储错误信息 # print(type(form.errors)) # print(type(form.errors.get(‘name‘))) # print(form.errors.get(‘name‘)[0]) return render(request, ‘reg.html‘, locals()) form = User() return render(request, ‘reg.html‘, locals())
我们来分析一下上面的代码,第一次请求网页是get请求,实例化出一个form对象,然后传入模板
当我们提交数据,就会走POST的代码,这时form对象中已经有了各个字段以及各个字段的值。
因此再次渲染模板时,可以直接通过form.字段名得到字段的值,通过forms.字段名.label可以得到字段的label值,从而自定义输入框的名字。
forms.CharField forms.EmailField 默认会宣称成<input type=‘text‘>标签
<div class="container"> <div class="row"> <div class="col-md-6 col-offset-3"> <h3>forms渲染标签方式一</h3> <form action="" method="post" novalidate="novalidate"> {# novalidate 使表单不会验证表单的输入 直接提交数据#} {% csrf_token %} <p>{{form.name.label}}{{ form.name }}</p> <p>{{form.password.label}}{{ form.password }}</p> <p>{{form.pwd.label}}{{ form.pwd }}</p> <p>{{form.email.label}}{{ form.email }}</p> <p>{{form.tel.label}}{{ form.tel }}</p> <input type="submit"> </form> </div> </div> </div>
渲染方式二
<h3>forms渲染标签方式二</h3> <form action="" method="post"> {% csrf_token %} {% for field in form %} <p> <label for="">{{ field.label }}</label> {{ field }} </p> {% endfor %} </form>
第二种直接通过for循环,更加简单。
渲染方式三
<h3>渲染方式3</h3> <form action="" method="post"> {% csrf_token %} {{ form.as_p }} </form>
渲染方式三虽然特别简单,但是不推荐使用,因为这种方式把格式给定死了,当你想要做一些修改的时候不能进行操作。
渲染错误信息
<form action="" method="post" novalidate="novalidate"> {# novalidate 使表单不会验证表单的输入 直接提交数据#} {% csrf_token %} <p>{{form.name.label}}{{ form.name }}<span class="pull-right error">{{ form.name.errors.0 }}</span></p> <p>{{form.password.label}}{{ form.password }}<span class="pull-right error">{{ form.password.errors.0 }}</span></p> <p>{{form.pwd.label}}{{ form.pwd }}<span class="pull-right error">{{ form.pwd.errors.0 }}</span><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"> </form>
视图函数仍为上面的函数,第一次请求渲染出页面,第二次做字段校验时,错误的字段会放入forms.errors中,各个字段的错误信息可通过form.字段名.errors.0取出。
如果没有错误,模板语法不会报错,只是什么都不显示;如果有错误,就将错误显示在输入框后。
显示出来的错误信息是Django内部自己定义好的,如果想要自己定义错误信息,可在User表的每一个字段增加error_message属性
error_messages={‘required‘: ‘该字段不能为空‘, ‘invalid‘:‘输入格式错误‘} 第一个是输入为空时显示的错误信息,第二个是校验不合法时提示的错误信息。
注:forms默认每一个字段不能为空。
forms组件的一些其他参数配置
我们上面定义User类的时候用的是CharField和EmailField,渲染出来的分别是<input type=‘text‘>和<input type=‘email‘>,如果想要改变渲染的类型,或者想给渲染的标签增加一些属性该怎么做呢?
from django import forms from django.forms import widgets class User(forms.Form): name = forms.CharField(min_length=4, label=‘用户名‘, error_messages={‘required‘: ‘该字段不能为空‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) password = forms.CharField(min_length=4, label=‘密码‘, widget=widgets.PasswordInput(attrs={‘class‘:‘form-control‘}), error_messages={‘required‘: ‘该字段不能为空‘}) pwd = forms.CharField(min_length=4, label=‘确认密码‘, error_messages={‘required‘: ‘该字段不能为空‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) email = forms.EmailField(label=‘邮箱‘, error_messages={‘required‘: ‘该字段不能为空‘, ‘invalid‘:‘输入格式错误‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) tel = forms.CharField(label=‘电话‘, error_messages={‘required‘: ‘该字段不能为空‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘}))
通过widget参数可以指定渲染出来的标签类型,同时给标签增加属性。
局部钩子和全局钩子
前面实现的校验功能都是一些非常简单的功能,比如最小长度,邮箱格式。
我们想要实现的目标是可以自定义一些更加复杂的规则,实现一些更加复杂的校验。
from django.shortcuts import render,HttpResponse # Create your views here. from django import forms from django.forms import widgets from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class User(forms.Form): name = forms.CharField(min_length=4, label=‘用户名‘, error_messages={‘required‘: ‘该字段不能为空‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) password = forms.CharField(min_length=4, label=‘密码‘, widget=widgets.PasswordInput(attrs={‘class‘:‘form-control‘}), error_messages={‘required‘: ‘该字段不能为空‘}) pwd = forms.CharField(min_length=4, label=‘确认密码‘, error_messages={‘required‘: ‘该字段不能为空‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) email = forms.EmailField(label=‘邮箱‘, error_messages={‘required‘: ‘该字段不能为空‘, ‘invalid‘:‘输入格式错误‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) tel = forms.CharField(label=‘电话‘, error_messages={‘required‘: ‘该字段不能为空‘}, widget=widgets.TextInput(attrs={‘class‘:‘form-control‘})) def clean_tel(self): val = self.cleaned_data.get(‘tel‘) if len(val) == 11: return val # 通过正常返回值 else: raise ValidationError(‘手机号码格式错误‘) #不通过抛出异常 def clean_password(self): val = self.cleaned_data.get(‘password‘) if len(val) >=4 : return val else: raise ValidationError(‘手机号码不能小于四位‘) def clean(self): password = self.cleaned_data.get(‘password‘) pwd = self.cleaned_data.get(‘pwd‘) if password: # password没有通过第一次校验 只抛出第一次校验的错误 if password == pwd: return self.cleaned_data else: raise ValidationError(‘两次密码不一致‘) else: return self.cleaned_data def reg(request): if request.method == ‘POST‘: print(request.POST) form = User(request.POST) # 传过来的字典键名和forms的字段名要相同 才能实现检验的功能 # 已经校验的form 校验的字段信息会保留 print(form.is_valid()) if form.is_valid(): # 传过来的键 可以多但是不可以少 少了或者错了 都为false print(form.cleaned_data) # cleaned_data都为校验forms字段中成功的键值 else: print(form.cleaned_data) print(123) # print(form.errors) # errors是一个字典 键为校验失败的字段名 值为一个列表 列表中存储错误信息 # print(type(form.errors)) # print(type(form.errors.get(‘name‘))) # print(form.errors.get(‘name‘)[0]) errors = form.errors.get(‘__all__‘) # 全局钩子错误 return render(request, ‘reg.html‘, locals()) form = User() return render(request, ‘reg.html‘, locals())
通过在类中定义 clean_字段名 的方法,可以实现对字段的自定义校验,成为局部钩子。
通过定义clean方法,可以对多个字段之间进行相互校验,clean方法的校验在局部钩子之后,成为全局钩子。
方法中的返回值和抛出的异常可以参考源码。
局部钩子的字段校验错误,错误信息会放在forms.errors中,键值为字段名,键值为错误信息。
全局钩子的字段校验错误,错误信息也放在forms.error中,键值为‘__all__‘,键值为错误信息。
以上是关于Django之forms组件的主要内容,如果未能解决你的问题,请参考以下文章