form组件

1. 用途

  • 数据校验
  • 标签渲染
  • 渲染错误信息

2. 用法(已注册验证为例)

  • 先建一个user表迁移数据库就不说了, 字段为name,pwd,email

  • 写一个类继承Form , 这个类用来设置校验规则的

    from django import forms
    from django.forms import widgets
    from django.core.exceptions import ValidationError
    
    class MyForm(forms.Form):
        name = forms.CharField(
            max_length=8, min_length=3, label='用户名',
            error_messages={'max_length': '最大长度为8', 'min_length': '最小长度为3', 'invalid': '不符合邮箱格式', 'required': '这个必须填'},
            widget=widgets.TextInput(
                attrs={'class': 'form-control', 'placeholder': '请输入用户名', 'id': 'name'}
            )
        )
    
    
    
    
        pwd = forms.CharField(
            max_length=8, min_length=3, label='密码',
            error_messages={'max_length': '最大长度为8', 'min_length': '最小长度为3', 'required': '这个必须填'},
            widget=widgets.PasswordInput(
                attrs={'class': 'form-control', 'placeholder': '请输入密码', 'id': 'pwd'}
            )
    
        )
        re_pwd = forms.CharField(
            label='确认密码',
            error_messages={'required': '这个必须填'},
            widget=widgets.PasswordInput(
                attrs={'class': 'form-control', 'placeholder': '请确认密码', 'id': 're_pwd'}
            )
        )
        email = forms.EmailField(
            label='邮箱',
            error_messages={'invalid': '不符合邮箱格式', 'required': '这个必须填'},
            widget=widgets.EmailInput(
                attrs={'class': 'form-control', 'placeholder': '请输入邮箱', 'id': 'email'}
            )
        )
        
        
      def clean(self):
            pwd = self.cleaned_data.get('pwd')
            re_pwd = self.cleaned_data.get('re_pwd')
            if pwd == re_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
    
        def clean_name(self):
            name = self.cleaned_data.get('name')
            res = models.User.objects.filter(name=name)
            if res:
                raise ValidationError('用户名已经存在')
            else:
                return name
      各种参数们介绍:
      forms.CharField  表示该字段为字符类型
    
      EmailField  表示该字段为email类型
    
      max_length=8, min_length=3 对该字段的长度就行限制
    
      label='用户名' , 为该字段添加一个label属性, 
          在前台渲染时循环这个类的对象可以通过  对象.label  取到这个'用户名'三个字
    
      error_messages={'max_length': '最大长度为8','required': '这个必须填','invalid': '不符合邮箱格式'}
          不符合校验规则是给出的提示信息, key为校验规则,value为对应的提示信息
    
      widget: 可以等于以下几个值
         1. widgets.PasswordInput()  该输入框为密码类型
         2. widgets.TextInput()   该输入框为文本类型
         3. 等等
        其中在这个括号里面可以为这个文本框添加属性,
              如: 
                  widget=widgets.TextInput(
                      attrs={'class': 'form-control', 'placeholder': '请输入用户名', 'id': 'name'}
                  )
      
    

`

  • 注意:需要校验的字段,可以比类的属性多,但是不能少

  • 在视图函数里实例化这个类

    def index(request):
        if request.method == 'GET':
            myform = MyForm()
            return render(request, 'index.html', locals())
        
        elif request.method == 'POST':
            #将前台传过来的数据转为字典格式作为参数实例化上面的类,而key与类的属性要对应
            #这里因为request.POST是字典格式,且前台传过来时key与属性已经对应了
            myform = MyForm(request.POST)
            
            #通过校验
            if myform.is_valid():
                'myform.is_valid为真, 则数据通过了所有的校验,包括钩子函数的校验'
                name=self.cleaned_data.get('name')  '通过校验的数据在cleaned_data里面'
                return JsonResponse({'num':200,'mdg':'ok'})
            
            #没通过校验,将错误信息给前台(这里前台是用ajax传的数据,所以这里我用的是JsonResponse)
            else:
              return JsonResponse(myform.errors)
        
    错误信息都放在myform.errors,在前台都可以取出来,不记得就console.log一下就可以了
    myform.errors是一个字段格式,没通过类的那个属性校验的错误信息是 类的属性名:错误信息
        没通过钩子的错误信息是'__all__':错误信息
    

3. 前端渲染模板与错误信息

  • 渲染模板

    方式一: 不用for循环
        

    用户名: {{ myform.name }}

    密码: {{ myform.pwd }}

    邮箱: {{ myform.email }}

    {{ myform.name }} 这个东西就是一个input框 方式二:for循环form对象(用的比较多):
    {% for foo in myform %}

    {{ foo.label }}:{{ foo }}

    {% endfor %}
    方式三:(不建议用):
    {{ myform.as_ul }} //这里会直接循环成ul>li>input框的形式 {{ myform.as_p }} //这里会直接循环成p>input框的形式
  • 渲染错误信息

    • myforms对象有errors
    • 属性(name)也有errors
    {{ myform.name.errors.0 }}
    

钩子

当那些字段的校验规则不能满足时,就用钩子

单个数据用局部钩子, 返回单个数据

用到多个数据时, 用全局钩子, 返回cleaned_data

4. 局部钩子校验

在类中定义一个方法,名字叫:clean_字段名字,

内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛异常(ValidationError)

注意: 在字段校验完成后才会触发钩子

def clean_name(self):
    # self:当前form对象
    #程序能走到该函数,前面校验已经通过了,所以可以从cleaned_data中取出数据
    name = self.cleaned_data.get('name')
    if name.startswith('sb'):
        # 失败,抛异常
        raise ValidationError('不能以傻逼开头')
    # 正常,把name返回
    return name

5. 全局钩子

重写clean方法

在类中定义一个方法,名字叫:clean

def clean(self):
    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('两次密码不一致')

局部钩子一定要返回单个数据 , 晚上糊涂了返回了一个cleaned_data
然后,呵呵
cleaned_data里面的name值就是这样的

form组件_第1张图片

解释一下就是cleaned_data里面的name又是一个cleaned_data ,这个cleaned_data里面的name又是一个cleaned_data
就是cleaned_data=>name=>cleaned_data=>name=>cleaned_data...

你可能感兴趣的:(form组件)