Django之Form表单验证

经常使用的Field

使用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;

 

提取错误信息:

若是验证失败了,那么有一些错误信息是咱们须要传给前端的。这时候咱们能够经过如下属性来获取:

  1. form.errors:这个属性获取的错误信息是一个包含了html标签的错误信息。
  2. form.errors.get_json_data():这个方法获取到的是一个字典类型的错误信息。将某个字段的名字做为key,错误信息做为值的一个字典。
  3. form.as_json():这个方法是将form.get_json_data()返回的字典dumpjson格式的字符串,方便进行传输。
  4. 上述方法获取的字段的错误值,都是一个比较复杂的数据。好比如下:
{'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'}

 

ModelForm:

你们在写表单的时候,会发现表单中的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指定一个列表,将须要的字段写进去。好比只想验证titlecontent,那么可使用如下代码实现:

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!', } }

 

save方法:

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()) 
相关文章
相关标签/搜索