博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django Form组件
阅读量:614 次
发布时间:2019-03-12

本文共 8472 字,大约阅读时间需要 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.label }} {
{ form_obj.name }} {
{ form_obj.name.errors.0 }}

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

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

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

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

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

{ form_obj.city.label }} {
{ 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/

你可能感兴趣的文章