使用Field能够是对数据验证的第一步.你期待对上传上来的数据为何类型就使用什么类型的Fieldhtml
公共参数:前端
lable: 设置前端label中的字符串正则表达式
widget: 设置input中的属性数据库
error_messages: 自定义错误字段的提示信息django
from django import forms from django.forms import widgets from app01 import models class MyForm(forms.Form): username = forms.CharField(max_length=8, min_length=3, label='用户名', error_messages={ 'required': '用户名不能为空', 'max_length': '用户名最大为8位', 'min_length': '用户名最小为3位' }, widget=widgets.TextInput(attrs={'class': 'form-control'}))
TextInput为input类型其余有: PasswordInput EmailInput CheckBoxInput 等等json
CharField后端
用来接收文本app
参数:函数
max_length: 最大长度ui
min_length: 最小长度
require: 这个字段是不是必须的.默认是必须的
error_messages: 在某个条件验证失败的时候,给出错误信息
EmailField
用来接收邮件,会自动验证邮件是否合法
错误信息的key: required invalid
FloatField
用来接收浮点类型,而且若是验证经过后,会将这个字段的值转换成浮点类型
参数:
max_value: 最大的值
min_value: 最小的值
错误信息的key: required invalid max_value min_value
IntegerField
用来接收整形,而且验证经过以后,会将这个字段的值转换成整形
参数:
max_value: 最大的值
min_value: 最小的值
错误信息的key: required invalid max_value min_value
URLField
用来接收url格式的字符串
错误信息: required invalid
经常使用验证器:
在验证某个字段的时候,能够传递一个validators参数用来指定验证器,进一步对数据进行过滤. 验证器有不少,可是不少验证器咱们其实已经经过这个Field或者一些参数就能够指定了.好比,EmailValidator, 咱们能够经过EmailField来指定,好比 MaxValueValidator, 咱们能够经过max_value参数来指定,如下是一些经常使用的验证器
1. MaxValueValidator: 验证最大值
2. MinValueValidator: 验证最小值
3. MaxLengthValidator: 验证最大长度
4. MinLengthValidator: 验证最小长度
5. EmailValidator: 验证是不是邮箱格式
6. URLValidator: 验证是不是URL格式
7. RegexValidator: 若是还须要更加复杂的验证,咱们可使用正则表达式的验证器: RegexValidator
class MyForm(forms.Form): telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message='请输入正确格式的手机号码!')])
有时候对一个字段验证,不是一个长度,一个正则表达式可以写清楚的,还须要一些其余复杂的逻辑,那么咱们能够对某个字段,进行自定义的验证。好比在注册的表单验证中,咱们想要验证手机号码是否已经被注册过了,那么这时候就须要在数据库中进行判断才知道。对某个字段进行自定义的验证方式是,定义一个方法,这个方法的名字定义规则是:clean_fieldname
。若是验证失败,那么就抛出一个验证错误。好比要验证用户表中手机号码以前是否在数据库中存在,那么能够经过如下代码实现:
class MyForm(forms.Form): telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message='请输入正确格式的手机号码!')]) def clean_telephone(self): telephone = self.cleaned_data.get('telephone') exists = User.objects.filter(telephone=telephone).exists() if exists: raise forms.ValidationError("手机号码已经存在!") return telephone
以上是对某个字段进行验证,若是验证数据的时候,须要针对多个字段进行验证,那么能够重写clean
方法。好比要在注册的时候,要判断提交的两个密码是否相等。那么可使用如下代码来完成:
class MyForm(forms.Form): telephone = forms.CharField(validators=[validators.RegexValidator("1[345678]\d{9}",message='请输入正确格式的手机号码!')]) pwd1 = forms.CharField(max_length=12) pwd2 = forms.CharField(max_length=12) def clean(self): pwd1 = self.cleaned_data.get('pwd1') pwd2 = self.cleaned_data.get('pwd2') if pwd1 != pwd2: self.add_error('pwd2','两次密码不正确')
return self.cleaned_data;
若是验证失败了,那么有一些错误信息是咱们须要传给前端的。这时候咱们能够经过如下属性来获取:
form.errors
:这个属性获取的错误信息是一个包含了html
标签的错误信息。form.errors.get_json_data()
:这个方法获取到的是一个字典类型的错误信息。将某个字段的名字做为key
,错误信息做为值的一个字典。form.as_json()
:这个方法是将form.get_json_data()
返回的字典dump
成json
格式的字符串,方便进行传输。{'username': [{'message': 'Enter a valid URL.', 'code': 'invalid'}, {'message': 'Ensure this value has at most 4 characters (it has 22).', 'code': 'max_length'}]}
那么若是我只想把错误信息放在一个列表中,而不要再放在一个字典中。这时候咱们能够定义一个方法,把这个数据从新整理一份。实例代码以下:
class MyForm(forms.Form): username = forms.URLField(max_length=4) def get_errors(self): errors = self.errors.get_json_data() new_errors = {} for key,message_dicts in errors.items(): messages = [] for message in message_dicts: messages.append(message['message']) new_errors[key] = messages return new_errors
这样就能够把某个字段全部的错误信息直接放在这个列表中。
校验成功可使用form_obj.is_vaild()验证,所有验证成功则为True,不然为False
校验成功会将成功的字段添加进cleaned_data中
def edit_password(request): form_obj = EditPasswordForm() if request.method == 'POST': back_dic = {'code': 100, 'msg':''} old_password = request.POST.get('id_old_password') password = request.POST.get('id_password') confirm_password = request.POST.get('id_confirm_password') form_obj = EditPasswordForm({'old_password': old_password,'password':password, 'confirm_password':confirm_password}) if form_obj.is_valid(): print(form_obj.cleaned_data) 输出为: {'old_password': '456', 'password': 'a159357', 'confirm_password': 'a159357'}
你们在写表单的时候,会发现表单中的Field
和模型中的Field
基本上是如出一辙的,并且表单中须要验证的数据,也就是咱们模型中须要保存的。那么这时候咱们就能够将模型中的字段和表单中的字段进行绑定。
好比如今有个Article
的模型。示例代码以下:
from django.db import models from django.core import validators class Article(models.Model): title = models.CharField(max_length=10,validators=[validators.MinLengthValidator(limit_value=3)]) content = models.TextField() author = models.CharField(max_length=100) category = models.CharField(max_length=100) create_time = models.DateTimeField(auto_now_add=True)
那么在写表单的时候,就不须要把Article
模型中全部的字段都一个个重复写一遍了。示例代码以下:
from django import forms class MyForm(forms.ModelForm): class Meta: model = Article fields = "__all__"
MyForm
是继承自forms.ModelForm
,而后在表单中定义了一个Meta
类,在Meta
类中指定了model=Article
,以及fields="__all__"
,这样就能够将Article
模型中全部的字段都复制过来,进行验证。若是只想针对其中几个字段进行验证,那么能够给fields
指定一个列表,将须要的字段写进去。好比只想验证title
和content
,那么可使用如下代码实现:
from django import forms class MyForm(forms.ModelForm): class Meta: model = Article fields = ['title','content']
若是要验证的字段比较多,只是除了少数几个字段不须要验证,那么可使用exclude
来代替fields
。好比我不想验证category
,那么示例代码以下:
class MyForm(forms.ModelForm): class Meta: model = Article exclude = ['category']
使用ModelForm
,由于字段都不是在表单中定义的,而是在模型中定义的,所以一些错误消息没法在字段中定义。那么这时候能够在Meta
类中,定义error_messages
,而后把相应的错误消息写到里面去。示例代码以下:
class MyForm(forms.ModelForm): class Meta: model = Article exclude = ['category'] error_messages ={ 'title':{ 'max_length': '最多不能超过10个字符!', 'min_length': '最少不能少于3个字符!' }, 'content': { 'required': '必须输入content!', } }
ModelForm
还有save
方法,能够在验证完成后直接调用save
方法,就能够将这个数据保存到数据库中了。示例代码以下:
form = MyForm(request.POST) if form.is_valid(): form.save() return HttpResponse('succes') else: print(form.get_errors()) return HttpResponse('fail')
这个方法必需要在clean
没有问题后才能使用,若是在clean
以前使用,会抛出异常。另外,咱们在调用save
方法的时候,若是传入一个commit=False
,那么只会生成这个模型的对象,而不会把这个对象真正的插入到数据库中。好比表单上验证的字段没有包含模型中全部的字段,这时候就能够先建立对象,再根据填充其余字段,把全部字段的值都补充完成后,再保存到数据库中。示例代码以下:
form = MyForm(request.POST) if form.is_valid(): article = form.save(commit=False) article.category = 'Python' article.save() return HttpResponse('succes') else: print(form.get_errors()) return HttpResponse('fail')
1. 后端先实例化forms对象
form_obj = MyForm()
2. 前端的三种渲染方式
1. {{ form_obj.as_p }} 2. {{ form_obj.name.label }}{{ form_obj.name }} 3. {% for foo in form_obj %} <p>{{ foo.label }} {{ foo }} </p> {% endfor %}
3. form前端经常使用属性
name: 将该字段对应的input框渲染到页面 label: 渲染设置的字段名, 若是没设置则该字段名首字母大写 auto_id: 字段中对应的属性id的值 与 label中的for一块儿使用
示例
{% for foo in form_obj %} <div class="form-group"> <label for="{{ foo.auto_id }}" >{{ foo.label }}</label> {{ foo }} <span class="error pull-right" style="color: red"></span> </div> {% endfor %}
后端代码示例
def edit_password(request): form_obj = EditPasswordForm() if request.method == 'POST': back_dic = {'code': 100, 'msg':''} old_password = request.POST.get('id_old_password') password = request.POST.get('id_password') confirm_password = request.POST.get('id_confirm_password') form_obj = EditPasswordForm({'old_password': old_password,'password':password, 'confirm_password':confirm_password}) if form_obj.is_valid(): if request.user.check_password(old_password) and password == confirm_password: request.user.set_password(confirm_password) request.user.save() back_dic['url'] = '/login/' auth.logout(request) else: back_dic['code'] = 101 back_dic['msg'] = {'old_password':['原密码错误']} else: back_dic['code'] = 101 back_dic['msg'] = form_obj.errors return JsonResponse(back_dic) return render(request,'edit_password.html', locals())
4. 设置标签样式
使用django.forms.widgets
from django import forms from django.forms import widgets password = forms.CharField(max_length=8,min_length=3,error_messages={ 'max_length': '密码最长8位', 'required': '密码不能为空', 'min_length':'密码最少3位' },widget=widgets.PasswordInput(attrs={'class':'c1 form-control'})) hobby = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),label="爱好", initial=3, widget=forms.widgets.Select() ) hobby1 = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),label="爱好", initial=[1, 3],widget=forms.widgets.SelectMultiple() ) keep = forms.ChoiceField( label="是否记住密码",initial="checked", widget=forms.widgets.CheckboxInput())