• django之form表单验证


    form组件的校验功能

     views.py

    from django.shortcuts import render, HttpResponse
    
    # Create your views here.
    
    from django import forms
    from django.forms import widgets
    
    class UserForm(forms.Form):
        name = forms.CharField(min_length=4,label='用户名') # 必须用required
        pwd = forms.CharField(min_length=4,label='密码')
        r_pwd = forms.CharField(min_length=4,label='确认密码')
        email = forms.EmailField(label='邮箱')
        tel = forms.CharField(label='手机')
    
    
    def reg(request):
        if request.method == 'POST':
    
            # form = UserForm({'name': 'ed', 'email': '123@qq.com'})  # 加多少个键值都无所谓,只要能匹配全Form里的字段就会返回True
            # print(form.is_valid())  # 返回布尔值
            
    
            form = UserForm(request.POST)  # form表单的name属性值应该与forms组件字段名称一致
    
            if form.is_valid():
                print(form.changed_data)  # 存的是通过校验的字典
            else:
                print(form.cleaned_data)  # {正确的键值,"email":"123@11.com"}
                print(form.errors)  # {"name":["insure this value has at least 4 characters]}
    
                print(type(form.errors))  # ErrorDict
                print(form.errors.get('name'))
                print(type(form.errors.get('name')))  # ErrorList
                print(form.errors.get('name')[0])  # This field is required.
            '''
            if 所有字段校验成功,则form.cleaned_data:{'name': 'edward', 'email': '123@qq.com'}
    
            '''
            return render(request, 'register.html', locals())
    
        form = UserForm()   # get请求的form,渲染form组件用
        return render(request, 'register.html', locals())

    html

    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:<input type="text" name="user"></p>
        <p>密码:<input type="password" name="pwd"></p>
        <p>确认密码:<input type="password" name="r_pwd"></p>
        <p>邮箱:<input type="email" name="email"></p>
        <p>手机号:<input type="text" name="tel"></p>
        <input type="submit" value="提交">
    </form>

    form组件渲染的三种方式

    <h3>form组件渲染方式1</h3>
    
    <form action="" method="post">
        {% csrf_token %}
        <p>{{ form.name.label }}:{{ form.name }} <span>{{ form.name.errors.0 }}</span></p>
        <p>{{ form.pwd.label }}:{{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p>
        <p>{{ form.r_pwd.label }}:{{ form.r_pwd }} <span>{{ form.r_pwd.errors.0 }}</span></p>
        <p>{{ form.email.label }}:{{ form.email }} <span>{{ form.email.errors.0 }}</span></p>
        <p>{{ form.tel.label }}:{{ form.tel }} <span>{{ form.tel.errors.0 }}</span></p>
        <input type="submit" value="提交">
    </form>
    
    
    <hr>
    <h3>form组件渲染方式2</h3>
    <form action="" method="post">
        {% csrf_token %}
    
        {% for filed in form %}
            <p>
                <label for="">{{ filed.label }}</label>
                {{ filed }}
            </p>
    
        {% endfor %}
    
    
        <input type="submit" value="提交">
    </form>
    
    <hr>
    <h3>form组件渲染方式3 --- 不建议使用这种方式,因为它只能固定放那么几个标签,缺乏灵活性,以后改动麻烦</h3>
    
    <form action="" method="post">
        {% csrf_token %}
    
        {{ form.as_p }}
    
        <input type="submit" value="提交">
    </form>

    显示错误信息和参数配置

    class UserForm(forms.Form):
        name = forms.CharField(min_length=4, label='用户名',
                               error_messages={"required": "该字段不能为空"},
                               widget=widgets.TextInput(attrs={'class': 'form-control'})
                               )  # 必须用要提示错误信息的关键词
        pwd = forms.CharField(min_length=4, label='密码',
                              widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
                              error_messages={
                                  "required": "该字段不能为空"
                              })
        r_pwd = forms.CharField(min_length=4, label='确认密码',
                                error_messages={"required": "该字段不能为空"},
                                widget=widgets.PasswordInput(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_name(self):
            val = self.cleaned_data.get('name')
    
            ret = UserInfo.objects.filter(name=val)
    
            if not ret:
                return val
            else:
                raise ValidationError('该用户已注册!')
                
                
     def clean_tel(self):
        val = self.cleaned_data.get('tel')
        ret = UserInfo.objects.filter(tel=val)
    
        if len(ret) == 11:
            return val
        else:
            raise ValidationError('手机号格式错误')
                
    # 源码
    def _clean_fields(self):
        try:
            if isinstance(field, FileField):
                initial = self.get_initial_for_field(field, name)
                value = field.clean(value, initial)
            else:
                value = field.clean(value)
            self.cleaned_data[name] = value
            if hasattr(self, 'clean_%s' % name):
                value = getattr(self, 'clean_%s' % name)()
                self.cleaned_data[name] = value
         except ValidationError as e :
            self.add_error(name, e)

    全局钩子

    为了解耦,新建一个myforms.py的文件,把有关forms的代码都放在这里面。

    # 全局钩子
    
    # 走完所有的校验才走clean
    def clean(self):
        # 走完所有的校验才走clean
        pwd = self.cleaned_data.get('pwd')
        r_pwd = self.cleaned_data.get('r_pwd')
        
        # 都满足不低于4个字符这个条件后才验证密码是否一致
        if pwd and r_pwd:
            if pwd == r_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
    
                else:
                    return self.cleaned_data
            
    #源码
    def clean(self):
        """
        Hook for doing any extra form-wide cleaning after Field.clean() has been
        called on every field. Any ValidationError raised by this method will
        not be associated with a particular field; it will have a special-case
        association with the field named '__all__'.
        """
        return self.cleaned_data
    
    def _clean_form(self):
        try:
            cleaned_data = self.clean()
        except ValidationError as e:
            self.add_error(None, e)
        else:
            if cleaned_data is not None:
                self.cleaned_data = cleaned_data
                
                
    # 全局钩子在前端没有显示,要在处理post请求的代码里给错误信息一个变量并传到前端
    errors = form.errors.get('__all__')
    
    # 当两次密码不一致时,在前端显示这个错误
    <p>
        {{ form.r_pwd.label }}:{{ form.r_pwd }}
        <span class="pull-right error">{{ form.r_pwd.errors.0 }}</span>
        <span class="pull-right error">{{ errors.0 }}</span>
    </p>

  • 相关阅读:
    经典背景音乐集(转)
    商业模式的思考
    PHP5.4的变化关注What has changed in PHP 5.4.x
    yii模版中的写法
    设计模式(一)工厂模式Factory(创建型)
    yii模版中的判断方法
    Yacc 与 Lex 快速入门(词法分析和语法分析)
    Windows PHP 中 VC6 X86 和 VC9 X86 的区别及 Non Thread Safe 的意思
    金融系列1《借贷记卡介绍》
    设计模式概论
  • 原文地址:https://www.cnblogs.com/lshedward/p/10351900.html
Copyright © 2020-2023  润新知