Erlo

Django笔记:表单验证

时间:2020-10-19   阅读:12次   来源:博客园
页面报错
点赞

对于请求中提交的表单数据,Django中可以使用类的方式进行处理,就像数据库中的表对应于Django中的一个ORM模型类,表单也是对应于一个Form类,Form类主要用于表单数据的验证功能,使得我们在验证表单中的数据时变得非常方便快捷。当然,不使用Form类也是可以处理表单数据的,只是大多数情况下使用Form类会方便很多,也是看个人的使用习惯和工作需要了。

一、Form类

Form类在from django import forms中,使用时需要定义一个Form的子类,相当于将请求的表单数据封装到一个特殊的类中,并自动完成一些数据的验证工作。

1、Form基本使用

Form子类中的属性名对应于HTML标签中的name属性值,可以根据表单中的数据类型在类中定义相应的属性字段。

示例:在app下新建一个forms.py用于存放所有的表单类

"""forms.py"""
from django import forms


class MessageBoardForm(forms.Form):
    """新建一个Form子类,用于接收表单中的4个值:title,content,email,reply"""
    # 接收文本类型数据,error_messages参数用于指定数据不满足相应条件时的错误提示信息
    title = forms.CharField(max_length=100, min_length=2, error_messages={'max_length': '最多只能有100个字符!'})
    # 接收文本类型数据,widget参数用于指定控件类型,forms.Textarea表示多行文本框控件
    content = forms.CharField(widget=forms.Textarea)
    # 接收邮箱格式数据
    email = forms.EmailField(error_messages={'required': '必须输入邮箱!'})
    # 接收布尔类型数据,required参数表示此字段是否为必须的,默认为True,False表示可以不传此参数,即没有接收到此字段也是允许的
    reply = forms.BooleanField(required=False)
"""views.py"""
from django.views.generic import View
from django.http import HttpResponse

from .forms import MessageBoardForm


# 定义一个视图类
class IndexView(View):

    # 处理post请求
    def post(self, request):
        # 将表单数据传入Form子类中,如果表单数据有多种类型时,
        # 可以直接传入,如form = MessageBoardForm(request.POST, request.FILES)
        form = MessageBoardForm(request.POST)
        # 判断所有字段是否都通过验证
        if form.is_valid():
            # 通过验证后,所有字段的数据都存放在cleaned_data中
            title = form.cleaned_data.get('title')
            content = form.cleaned_data.get('content')
            email = form.cleaned_data.get('email')
            reply = form.cleaned_data.get('reply')
            print(title)
            print(content)
            print(email)
            print(reply)
            return HttpResponse('success!')
        else:
            # get_json_data方法以字典的形式输出没有通过验证的错误信息
            print(form.errors.get_json_data())
            return HttpResponse('fail!')

2、常用Field字段

常用的Field字段和参数使用如下:

3、验证器

Form类中的各个Field字段其实都有一些基本的验证器,如果表单中的某个字段想要额外添加一些验证功能,可以指定validators参数给字段添加一些验证器,或者给这个字段定义一个额外的形如clean_[字段名]自定义验证方法。
内置验证器:内置验证器通过字段的validators参数指定对应的验证器列表即可,Django内置的验证器都在django.core.validators中,常用的内置验证器:

自定义验证:需要针对某个字段进行特殊验证时,可以在Form表单类中定义一个clean_[字段名]的方法,就会自动执行这个方法进行验证了,如果不符合要求,直接抛出异常即可,符合要求则返回对应的值。如果想要针对多个字段之间的验证,可以重写clean()方法,当所有字段的验证都通过后就会执行这个方法。

"""forms.py"""
from django import forms
from django.core import validators
from .models import User


class RegisterForm(forms.Form):
    """定义一个注册功能的Form子类,用来接收注册的相关信息"""
    username = forms.CharField(max_length=100)
    # 添加一个正则表达式的验证器,message参数表示验证失败时的错误提示信息
    telephone = forms.CharField(validators=[validators.RegexValidator(r'1[345678]d{9}', message='请输入正确格式的手机号码!')])
    pwd1 = forms.CharField(max_length=16, min_length=6)
    pwd2 = forms.CharField(max_length=16, min_length=6)

    def clean_telephone(self):
        # 当字段的基本验证通过后,会将数据存储在cleaned_data中
        telephone = self.cleaned_data.get('telephone')
        # 在数据库中查找是否有相同的手机号,User为用户的ORM模型类
        exists = User.objects.filter(telephone=telephone).exists()
        if exists:
            raise forms.ValidationError(message='{}已经被注册!'.format(telephone))

        # 需要返回处理后的值
        return telephone

    def clean(self):
        # 执行这个方法时表示所有字段都已验证成功,当然,需要先调用父类的clean()方法
        cleaned_data = super().clean()
        pwd1 = cleaned_data.get('pwd1')
        pwd2 = cleaned_data.get('pwd2')
        if pwd1 != pwd2:
            raise forms.ValidationError(message='两次输入的密码不一致!')
        
        # 返回处理后的数据
        return cleaned_data

二、ModelForm类

如果表单提交的信息与已有的ORM模型是一致的,比如提交的信息会直接存储到数据库中,而数据库中对应表在代码中已有相应的ORM模型类了,那么就可以使用ModelForm类,可以免去我们很多的重复工作,ModelForm类有许多用法都是和Form类是类似的,使用时可以参考下。
使用ModelForm比较简单,需要定义一个ModelForm的子类,基本使用如下:

  1. 需要定义一个名为Meta的内部类来关联ORM模型类,Meta类的常用属性如下:
    • model:指定关联的ORM模型类。
    • fields:指定关联的字段,__all__表示全部字段,也可以使用列表指定需要的字段。
    • exclude:指定排除的字段,即除了此属性指定的字段,其他字段都需要关联。
    • error_messages:指定验证失败时的错误提示信息。
"""forms.py"""
from django import forms
from .models import Book


class MyForm(forms.ModelForm):
    # 如果想要自定义验证方式,也是和Form类一样的定义方式
    def clean_page(self):
        page = self.cleaned_data.get('page')
        if page > 1000:
            raise forms.ValidationError('page不能大于1000!')
        return page

    class Meta:
        # ORM模型类
        model = Book

        # 指定需要验证的字段,__all__表示所有字段,也可以使用列表将需要的字段放进去即可
        fields = '__all__'
        # fields = ['title', 'page']

        # fields和exclude两个属性必须指定其中一个
        # 表示除了这个字段其他字段都需要
        # exclude = ['price']

        # 指定验证失败时的错误提示信息
        error_messages = {
            'title': {
                'required': '请输入标题!',
                'invalid': '请输入正确格式的标题!'
            }
        }
  1. 虽然可以关联到ORM模型类,但是ModelForm子类中也是可以定义自己的属性字段的,定义方式也是和Form子类的定义是一样的,比如提交的表单信息比ORM模型中的字段多的时候就可以这样做。
  2. 验证时,可以在ORM模型的字段定义中指定validators参数,添加额外的验证器即可。如果要对某个字段自定义验证方式时,在ModelForm子类中像Form类一样,定义一个clean_[字段名]的方法来处理即可。
"""models.py"""
from django.db import models
from django.core import validators


class Book(models.Model):
    title = models.CharField(max_length=100)
    page = models.IntegerField()
    # 可以直接在ORM模型字段中添加验证器
    price = models.FloatField(validators=[validators.MaxValueValidator(limit_value=250)])
  1. 当表单的验证都通过之后,可以调用save()方法将数据直接保存到数据库中。如果不想直接提交到数据库中,或者还需要给ORM模型中的某些字段指定值,可以使用如user = user_form.save(commit=False),指定commit参数为False之后,就只是生成对应的模型对象并返回,并不会映射到数据库中。修改完成后,再调用模型对象的save()方法即可。
"""views.py"""
from django.http import HttpResponse
from django.views.decorators.http import require_POST
from .forms import RegisterForm


# 定义一个视图函数,只允许post的请求方式
@require_POST
def register(request):
    # 将post的数据传入ModelForm类中
    user_form = RegisterForm(request.POST)
    if user_form.is_valid():
        # 只是同步ORM模型类,但并不映射到数据库中
        user = user_form.save(commit=False)
        # 重新指定密码
        user.password = user_form.cleaned_data.get('password')
        # 保存到数据库中
        user.save()
        return HttpResponse('success!')
    else:
        return HttpResponse('fail!')

相关推荐

提交留言

评论留言

还没有评论留言,赶紧来抢楼吧~~

吐槽小黑屋()

* 这里是“吐槽小黑屋”,所有人可看,只保留当天信息。

  • Erlo吐槽

    Erlo.vip2020-10-22 20:02:12Hello、欢迎使用吐槽小黑屋,这就是个吐槽的地方。
  • 返回顶部