小谈Django中的form组件

form

简单Form示例

定义

from django import forms


class RegForm(forms.Form):
    user = forms.CharField(label="账号")
    pwd = forms.CharField(label="密码", widget=forms.PasswordInput)

使用

视图函数

def reg(request):
    form_obj = RegForm()
    if request.method == 'POST':
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():
            print(request.POST)
            # 上面的显示结果: 
            # <QueryDict: {'csrfmiddlewaretoken': ['wFp3cnKRpV1ZMuOdZl0rklwWkncSfULWeWaDPhaBa9eObp0Vnl4JBgZqj7MJuy4t'], 'user': ['alex'], 'pwd': ['123']}>
            print(form_obj.cleaned_data, type(form_obj.cleaned_data))
            # 上面的显示结果: 
            # {'user': 'alex', 'pwd': '123'} <class 'dict'>
            return HttpResponse('注册成功')

    return render(request, 'reg.html', {'form_obj': form_obj})

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post" novalidate>
    {% csrf_token %}
{#    {{ form_obj.as_p }}#}

    <p>
        <label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
        {{ form_obj.user }} <span>{{ form_obj.user.errors.0 }}</span>
    </p>
    <p>
        <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
        {{ form_obj.pwd }}
    </p>
    {{ form_obj.errors }}
    <button>注册</button>
</form>
</body>
</html>

模板更多

  • forms.Charfield --> 字段对象
  • widget --> 插件对象

生成所有字段的input框

{{ form_obj.as_p }}

生成某个字段的input框

{{ form_obj.user }}

某个字段的中文提示

{{ form_obj.user.label }}

某个字段的input框的ID

{{ form_obj.user.id_for_label }}

生成单个的input框并且设置label标签

<p>
    <label for="{{ form_obj.user.id_for_label }}">{{ form_obj.user.label }}</label>
    {{ form_obj.user }}
</p>
<label for="{{ form_obj.user.id_for_label }}"> -> 作用: 让input框聚焦 -> 鼠标点击"账号"光标自动切到input框中

所有字段的校验错误

{{ form_obj.errors }} -> 所有字段的所有错误
{{ form_obj.errors.0 }} -> 所有字段的第一个错误

某个字段的校验错误

{{ form_obj.user.errors }} -> 某个字段的所有错误
{{ form_obj.user.errors.0 }} -> 某个字段的第一个错误

widget=forms.PasswordInput

# input框显示密文
class RegForm(forms.Form)L
	...
    pwd = forms.CharField(label='密码', widget=forms.PasswordInput)

Form常用字段和插件

  • 字段用于对用户请求数据的验证 __> 与form表单校验相关
  • 插件用于自动生成HTML __> 和前段渲染相关

所有字段

# 导入forms模块语句:
# from django import forms
# 直接点进forms有下面这句, 然后点进去fields看
from django.forms.fields import *

# 看到所有的字段:
__all__ = (
    'Field', 'CharField', 'IntegerField',
    'DateField', 'TimeField', 'DateTimeField', 'DurationField',
    'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField',
    'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField',
    'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
    'SplitDateTimeField', 'GenericIPAddressField', 'FilePathField',
    'SlugField', 'TypedChoiceField', 'TypedMultipleChoiceField', 'UUIDField',
)

常用字段只写了三个 ; 如果样式不够 , 可以修改widget就可以了 , 可以点出很多东西

  • 比如ChoiceField(widget=forms.RadioSelect)
  • 比如MultipleChoiceField(widget=forms.CheckboxSelectMultiple)

Charfield

user = forms.CharField(label="账号")

ChoiceField

gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性别')

MultipleChoiceField

hobby = forms.MultipleChoiceField(choices=(('1','抽烟'),('2','喝酒'),('3','吐口水')), label='爱好')

inital

class RegForm(forms.Form):
    gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性别', initial='2') # 设置默认值, 渲染在前段页面就是input框中value的值

error_messages

class RegForm(forms.Form):
    user = forms.CharField(
        label="账号",
        min_length=6,
        # 在前段显示错误的信息; 如果不设置, 显示的是默认的,英文的
        error_messages={
            'required': '不能为空!',
            'min_length':'至少是6位!'
        }
    )

widget

# 前段的input框显示密文
class RegForm(forms.Form)L
	...
    pwd = forms.CharField(label='密码', widget=forms.PasswordInput)
# widget=forms.PasswordInput
# 上下两个一样,主要看点进去"from django import forms"中的forms,看模块如何导入的.
# widget=forms.widgets.PasswordInput

required

class RegForm(forms.Form):
    user = forms.CharField(
        # required默认是True_>必填的;改成False可以不填
        required=False,
        label="账号",
        min_length=6,
        # 在前段显示错误的信息; 如果不设置, 显示的是默认的,英文的
        error_messages={
            'required': '不能为空!',
            'min_length':'至少是6位!'
        }
    )

disabled

是否禁用

min_length

最小长度

choices

可选择的数据

方法一 :

class RegForm(forms.Form):
    ...
    gender = forms.ChoiceField(choices=(('1','男'),('2','女')),label='性别', initial='2')
    hobby = forms.MultipleChoiceField(choices=(('1','抽烟'),('2','喝酒'),('3','吐口水')), label='爱好')

方法二 :

class RegForm(forms.Form):
    ...
    gender = forms.ChoiceField(label='性别', initial='2')    
    
    def __init__(self, *args, **kwargs):
        super(RegForm, self).__init__(*args, **kwargs)
        # self.fields['gender'].choices = [('1','男'),('2','女')]
        # 上下两句效果一样, 但是models中gender类得添加双下str方法
        self.fields['gender'].choices = models.gender.objects.all()

校验

1. 自带的校验规则

各个字段都有自己自带的校验规则 , 比如required...

2. 自定义校验规则

1. 写函数

from django import forms
from django.core.exceptions import ValidationError

# value就是input框中填写的值
def check_name(value):
    # 自定义校验规则
    # 如果校验合格, 什么都不做;
    # 如果校验不合格, 抛出异常(ValidationError)
    if 'alex' in value:
        raise ValidationError('不能包含alex,非法字符!')

class RegForm(forms.Form):
    user = forms.CharField(
        label="账号",
        min_length=6,
        # 自定义校验规则
        validators=[check_name]
        error_messages={
            'required': '不能为空!',
            'min_length':'至少是6位!'
        }
    )

2. 内置校验器

from django import forms
# RegexValidator是正则的内置校验器,还有很多其他的, 比如: 邮箱的,url的,ipv6的,...;可以点进去看
from django.core.validators import RegexValidator

class RegForm(forms.Form):
    phone = forms.Charfield(
        # RegexValidator()实例化一个RegexValidator的对象,第一个参数是正则表达式; 第二个参数是错误信息;
        # 可以点进去看看, 还有其他的,一般这两个就够了
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式不正确')]
    )

3. 局部钩子

class RegForm(forms.Form):
    user = forms.CharField(
        label="账号",
        min_length=6,
        error_messages={
            'required': '不能为空!',
            'min_length':'至少是6位!'
        }
    )
    
    def clean_user(self):
        # 局部钩子 clean_字段名
        # 如果校验成功, 返回当前字段的值;
        # 如果校验不成功, 抛出异常;
        if 'alex' in self.cleaned_data.get('user'):
            raise ValidationError('不能包含alex,非法字符!')
        return self.cleaned_data.get('user')

4. 全局钩子

class RegForm(forms.Form):
    pwd = forms.CharField(label="密码", widget=forms.PasswordInput)
    re_pwd = forms.CharField(label="密码", widget=forms.PasswordInput)
    ...
    
    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:
            # 这样错误信息就在re_pwd后面显示了,不写的话只会在所有字段的所有错误中出现;
            self.add_error('re_pwd','两次密码不一致!!!')
            raise ValidationError('两次密码不一致!')
  • 如果要定义的校验规则只针对于一个字段使用 __> 局部钩子 ;
  • 如果要定义的校验规则针对 一个Form中的两个字段合起来做校验( 如密码和确认密码 ) __> 全局钩子 ;
  • 如果要定义的校验规则适用于多个字段 __> 写函数或者内置校验器 , 可以只写一次函数 , 然后把函数名写到每个字段的validators中 ;
posted @ 2020-10-12 19:38  richard_A  阅读(102)  评论(0编辑  收藏  举报