zoukankan      html  css  js  c++  java
  • Django form表单的校验、局部钩子及全局钩子

    #form表单的校验、局部钩子及全局钩子#

    ## views.py 视图函数 ##

    from django import forms                #调用forms模块
        from django.forms import widgets        #调用widgets模块,用来对form组件的参数配置。
        from django.core.exceptions import ValidationError  #调用 ValidationError 模块。用来手动触发raise错误。
        from fileupdate.models import *      #载入必要的数据库列表。
    
    
        class FormReg(forms.Form):
    
            name = forms.CharField(min_length=4, widget=widgets.TextInput(attrs={'class': 'form-control '}), label='姓名',
                                   error_messages={'required': '*不能为空', })
            pwd = forms.CharField(min_length=4, widget=widgets.PasswordInput(attrs={'class': 'form-control'}), label='密码')
            r_pwd = forms.CharField(min_length=4, widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
                                    label='确认密码')
            email = forms.EmailField(widget=widgets.EmailInput(attrs={'class': 'form-control'}), label='邮箱')
            tel = forms.CharField(max_length=13, label='电话', widget=widgets.TextInput(attrs={'class': 'form-control'}))
            ##字段的校验,通过对widget的属性设置,可定义INPUT标签的type类型,以及标签的其他属性。通过对label设置,可以自定义form渲染时的标签名,
            ##另外,通过对error_messages属性设置,可对验证信息进行自定义。注意:字典中错误信息的key值是固定的
        
            def clean_name(self):    #局部钩子   注意:名字必须为clean_%s ,这是根据源码来设置的。
                                    #其原理是,当字段校验完毕后,再进行查找是否有以clean_开头的函数名,如果有,就调用该函数,
                                    #运行我们自定义的函数,如果满足条件就返回当前被校验字段的内容。否则手动触发ValidationError错误,源码中会捕获并将值返回。
                val = self.cleaned_data.get('name')     #通过cleaned_data获得对应字段的'干净数据'
                user_obj = User.objects.filter(name=val).first()  #与对应的数据库中字段相比较,并获得一个字段对象
                if not user_obj:   #对字段进行判断,如果为空(数据库中没有对应的名字),那么返回这个校验值。
                    return val
                else:
                    raise ValidationError('名字存在')   #如果存在,那么手动触发异常(异常名为ValidationError),并设置自定义内容。
        
            def clean(self):   #全局钩子  注意:名字必须为clean,这是根据源码来设置的。
                             #其原理是对校验完毕的字段,再进行字段间的校验。当字段校验完毕,查找是否有clean的函数,如果有就运行该
                             #函数,其功能是对所有校验的字段进行校验比对。如果满足条件,就将cleaned_data返回(这与源码相匹配)
                             #如果不满足就手动触发ValidationError错误。
                pwd = self.cleaned_data.get('pwd') 
                r_pwd = self.cleaned_data.get('r_pwd')
                if pwd and r_pwd:   #如果两个字段中一个为空值那么就不用再进行校验。直接返回cleaned_data,通过校验功能返回错误信息。
                    if pwd == r_pwd:
                        return self.cleaned_data
                    else:
                        raise ValidationError('两次密码不一致!')
                else:
                    return self.cleaned_data
    
        def reg(request):
        
            if request.method == 'POST':  #如果是一次POST提交,那么进行校验。
                formreg = FormReg(request.POST)  #对提交的信息实例化。
        
                if formreg.is_valid():  #通过is_valid()方法进行判断,(注意:当执行这个函数时,将对所有字段进行校验,运行局部钩子和全局钩子)
                    return HttpResponse('OK')
                else:
                    print('cleaneddata', formreg.cleaned_data)
                    print('errordata', formreg.errors)
                    error = formreg.errors.get('__all__') #当设置了全局钩子时,要设置一个变量来获得全局钩子返回的错误信息。
                                #这是由于,全局钩子的错误在form对象的errors中,当clean()方法抛出异常时,源码会自动捕获,并将错误
                                #存储在errors字典中,其中键名'__all__'就是全局钩子的变量。
                    return render(request, 'reg.html', locals())
        
            formreg = FormReg()   #当为get请求时,实例化一个空的对象,通过这个空的实例化对象可以渲染前段,自动生成form表单。
            return render(request,'reg.html', locals())

    ## reg.html 前端页面 ##

      <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>reg</title>
            <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
                  integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        </head>
        <body>
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3">
                    <form action="" method="post" novalidate>
                        {% csrf_token %}
                        {% for field in formreg %}
                            <p>
                                <label for="">{{ field.label }}</label>
                            {{ field }} 
                                {% if field.name == 'r_pwd' %}
                                    <span style="color: crimson">{{ field.errors.0 }} {{ error.0 }}</span>
                                {% else %}
                                    <span style="color: crimson">{{ field.errors.0 }}</span>
                                {% endif %}
        
                            </p>
                        {% endfor %}
        
                        <p><input type="submit"></p>
                    </form>
                </div>
            </div>
        </div>
        
        </body>
        </html>
    View Code
  • 相关阅读:
    牛客IOI周赛17-提高组 卷积 生成函数 多项式求逆 数列通项公式
    6.3 省选模拟赛 Decompose 动态dp 树链剖分 set
    AtCoder Grand Contest 044 A Pay to Win 贪心
    5.29 省选模拟赛 树的染色 dp 最优性优化
    luogu P6097 子集卷积 FST FWT
    CF724C Ray Tracing 扩展欧几里得 平面展开
    5.30 省选模拟赛 方格操作 扫描线 特殊性质
    5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集
    Spring main方法中怎么调用Dao层和Service层的方法
    Bug -- WebService报错(两个类具有相同的 XML 类型名称 "{http://webService.com/}getPriceResponse"。请使用 @XmlType.name 和 @XmlType.namespace 为类分配不同的名称。)
  • 原文地址:https://www.cnblogs.com/sly27/p/10167332.html
Copyright © 2011-2022 走看看