博客
关于我
Django Form组件
阅读量:614 次
发布时间:2019-03-12

本文共 8442 字,大约阅读时间需要 28 分钟。

文章目录

使用Form组件验证

views:

from django.shortcuts import render, HttpResponsefrom django import forms# 先定义一个Form类class LoginForm(forms.Form):    name = forms.CharField(        label='用户名',        initial='陌生人',        strip=True,        error_messages={               'required': '用户名不能为空',        }    )    # 密码框    password = forms.CharField(        label='密码',        min_length=6,        widget=forms.PasswordInput(render_value=True),        error_messages={               'required': '密码不能为空',            'min_length': '密码不能小于6位',        }    )    # 单选框    gender = forms.ChoiceField(        choices=[(1, '男'), (2, '女'), (3, '保密')],        label='性别',        initial=3,        widget=forms.RadioSelect(),        error_messages={               'required': '请选择性别'        }    )    # 下拉单选    hobby = forms.ChoiceField(        label='爱好',        widget=forms.Select(),        choices=((1, '篮球'), (2, '足球'), (3, '乒乓球')),        initial=2,    )    # 多选    hobby2 = forms.MultipleChoiceField(        label='爱好2',        choices=((1, '摩托车'), (2, '汽车'), (3, '游艇')),        initial=[1, 3],        widget=forms.SelectMultiple()    )    # 单选checkbox    keep = forms.ChoiceField(        label='是否记住密码',        initial='checked',        widget=forms.CheckboxInput()    )    # 多选checkbox    city = forms.ChoiceField(        label='居住城市',        choices=[(1, '北京'), (2, '天津'), (3, '上海'), (4, '武汉')],        initial=4,        widget=forms.Select()    )# 写一个函数视图def login(request):    form_obj = LoginForm()    if request.method == 'POST':        form_obj = LoginForm(request.POST)        if form_obj.is_valid():            pass    return render(request, 'app/login.html', {   'form_obj': form_obj})

templates:

{% csrf_token %}

{ { form_obj.name }} { { form_obj.name.errors.0 }}

{ { form_obj.password }} { { form_obj.password.errors.0 }}

{ { form_obj.gender }} { { form_obj.gender.errors.0 }}

{ { form_obj.hobby }} { { form_obj.hobby.errors.0 }}

{ { form_obj.hobby2 }} { { form_obj.hobby2.errors.0 }}

{ { form_obj.keep }} { { form_obj.keep.errors.0 }}

{ { form_obj.city }} { { form_obj.city.errors.0 }}

常用Form组件内置字段

Field    required=True,               是否允许为空    widget=None,                 HTML插件    label=None,                  用于生成Label标签或显示内容    initial=None,                初始值    help_text='',                帮助信息(在标签旁边显示)    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}    validators=[],               自定义验证规则    localize=False,              是否支持本地化    disabled=False,              是否可以编辑    label_suffix=None            Label内容后缀CharField(Field)    max_length=None,             最大长度    min_length=None,             最小长度    strip=True                   是否移除用户输入空白 IntegerField(Field)    max_value=None,              最大值    min_value=None,              最小值DecimalField(IntegerField)    max_value=None,              最大值    min_value=None,              最小值    max_digits=None,             总长度    decimal_places=None,         小数位长度 DateField(BaseTemporalField)    格式:2015-09-01TimeField(BaseTemporalField)    格式:11:12DateTimeField(BaseTemporalField)格式:2015-09-01 11:12  RegexField(CharField)    regex,                      自定制正则表达式    max_length=None,            最大长度    min_length=None,            最小长度    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}ChoiceField(Field)    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)    required=True,             是否必填    widget=None,               插件,默认select插件    label=None,                Label内容    initial=None,              初始值    help_text='',              帮助提示

字段校验

RegexValidator验证器

from django.core.validators import RegexValidatorno = forms.CharField(    label='员工编号',    validators=[RegexValidator(r'^[0-9]+', '请输入数字'), RegexValidator('^110[0-9]+$', '请以110开头')])

自定义函数验证

import refrom django.core.exceptions import ValidationErrordef mobile_validate(value):    mobile_re = re.compile(r'^1[2356789]{1}[0-9]{9}$')    if not mobile_re.match(value):        raise ValidationError('手机号格式错误')class LoginForm(forms.Form):     mobile = forms.CharField(        label='手机号',        validators=[mobile_validate, ],        error_messages={               'required': '手机号不能为空',        }    )

Hook方法

局部钩子

在Fom类中定义 clean_字段名()方法,就能够实现对特定字段进行校验

class LoginForm(forms.Form):      description = forms.CharField(        label='内容描述',        initial='暂无描述',        min_length=4,        error_messages={               'required': '不能为空',            'invalid': '格式错误',            'min_length': '最少评论4个字'        }    )    def clean_description(self):        value = self.cleaned_data.get('description')        if '666' in value:            raise ValidationError('请不要喊666')        else:            return value

全局钩子

在Fom类中定义clean()方法,就能够实现对字段进行全局校验

class LoginForm(forms.Form):    # 密码框    password = forms.CharField(        label='密码',        min_length=6,        widget=forms.PasswordInput(),        error_messages={               'required': '密码不能为空',            'min_length': '密码不能小于6位',        }    )    repassword = forms.CharField(        label='请再次输入密码',        min_length=6,        widget=forms.PasswordInput(),        error_messages={               'required': '密码不能为空',            'min_length': '密码不能小于6位',        }    )    def clean(self):        password_value = self.cleaned_data.get('password')        repassword_value = self.cleaned_data.get('repassword')        if password_value == repassword_value:            return self.cleaned_data        else:            self.add_error('repassword', '两次密码不一致')

源码分析

  1. 在执行form_obj.is_valid()进行判断

  2. 进入is_valid方法

    def is_valid(self):    """        Returns True if the form has no errors. Otherwise, False. If errors are        being ignored, returns False.        """    return self.is_bound and not self.errors

    self.is_bound判断是否有数据

    self.errors判断是否有错误信息

  3. 进入errors属性方法

    @propertydef errors(self):    "Returns an ErrorDict for the data provided for the form"    if self._errors is None:        self.full_clean()        return self._errors
  4. 进入full_clean方法

    self._errors存放错误信息

    cleaned_data存放验证通过的数据

    def full_clean(self):    """        Cleans all of self.data and populates self._errors and        self.cleaned_data.        """    self._errors = ErrorDict()    if not self.is_bound:  # Stop further processing.        return    self.cleaned_data = {     }    # If the form is permitted to be empty, and none of the form data has    # changed from the initial data, short circuit any validation.    if self.empty_permitted and not self.has_changed():        return    self._clean_fields()    self._clean_form()    self._post_clean()
  5. 执行_clean_fields方法,循环每个字段,分别校验

    def _clean_fields(self):    for name, field in self.fields.items():        # value_from_datadict() gets the data from the data dictionaries.        # Each widget type knows how to retrieve its own data, because some        # widgets split data over several HTML fields.        if field.disabled:            value = self.get_initial_for_field(field, name)            else:                value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))                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)
  6. 执行_clean_form方法

    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

转载地址:http://vwhxz.baihongyu.com/

你可能感兴趣的文章
[gym102832L][CCPC2020 长春站 L]Coordinate Paper
查看>>
阶乘分解 (算法竞赛进阶指南 P136,质因数分解)
查看>>
官方win10重装系统
查看>>
2021-04-13 Python 随机列表、集合、元组、字典的生成和排序
查看>>
hslogic_基于FPGA的混沌加密
查看>>
SAR图像超分辨技术
查看>>
拉道radau伪谱算法
查看>>
fpga工程师笔试题
查看>>
神经网络遗传算法函数极值寻优-非线性函数极值
查看>>
emd分解matlab程序
查看>>
简单的记事本日志类
查看>>
map容器
查看>>
基于 React hooks + Typescript + Cesium 实现泛光尾迹线
查看>>
Java版取色器(7)——界面简单装饰
查看>>
pycharm报错“ModuleNotFoundError: No module named 'pymysql'”
查看>>
服务器间共享挂载操作
查看>>
Problem F: 零起点学算法106——首字母变大写
查看>>
Problem H: 计算数列和2/1,3/2,5/3,8/5......
查看>>
QT之深入理解QThread
查看>>
如何快速调试 sCrypt 单元测试错误
查看>>