Django之Form组件

Form组件介绍

在HTML页面中form表单会把用户输入标签的数据包起来提交后端。大多数情况下需要对用户输入的数据做校验(比如长度和格式),如果数据有错误就需要在页面上输出相应的错误信息。

Django的Form组件就会很方便的校验,同时保留上次用户输入内容

HTML和Django的Form区别

HTML上Form

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
<form action="/register/" method="post">
    {% csrf_token %}
    <p>
        用户名:
        <input type="text" name="username">
        <span style="color: red">{{ arg_error.username }}</span>
    </p>
    <p>
        密  码:
        <input type="password" name="pwd">
        <span style="color: red">{{ arg_error.pwd }}</span>
    </p>
    <p>
        <input type="submit" value="提交">
    </p>
</form>
</body>
</html>

Django项目中views.py

## 注册页面信息提交的函数
def register(request):
    ## 定义返回错误信息
    arg_error = {"username": "", "pwd": ""}
    if request.method == "POST":
        ## 获取用户输入的数据到变量
        username = request.POST.get("username", None)
        pwd = request.POST.get("pwd", None)
        ## 校验
        if username:
            arg_error["username"] = "用户名不能为空!"
        if pwd:
            arg_error["pwd"] = "密码不能为空!"
        elif len(pwd) < 6:
            arg_error["pwd"] = "密码不能小于6位!"
        else:
            ## 把数据保存到数据库中
            models.UserInfo.objects.create(user=username, pwd=pwd)
            ## 返回用户信息
            return HttpResponse("注册成功!")
    return render(request, "arg.html", {'arg_error': arg_error})

Django上Form

Django项目中views.py

定义Form类

## 导入Form组件和widget渲染页面
from django import forms
from django.forms import widgets
## 定义类,继承Form类
class Argforms(forms.Form):
    ## 定义类变量(max_length最大值、label页面显示标签、error_messages返回的错误信息)
    username = forms.CharField(max_length=16, label="用户名", error_messages={
        "required": "用户名不能为空!",
    })
    ## widget定义页面input标签type为password
    pwd = forms.CharField(min_length=6, label="密码", error_messages={
        "min_length": "密码不能小于6位!",
        "required": "密码不能为空",
    },widget = widgets.PasswordInput)

注册页面信息提交的函数

def register2(request):
    ## 上面定义的类赋值到变量
    in_form = Argforms()
    ## 校验
    if request.method == "POST":
        in_form = Argforms(request.POST)
        ## 判断校验是否通过
        if in_form.is_valid():
            ## 把数据保存到数据库中
            models.UserInfo.objects.create(**in_form.cleaned_data)
            ## 返回用户信息
            return HttpResponse("注册成功!")
    return render(request, 'register2.html', {'in_form': in_form})

register2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>页面注册</title>
</head>
<body>
<form action="/register2/" method="post" novalidate>
    {% csrf_token %}
    <p>
        {{ in_form.username.label }}
        {{ in_form.username }}
        <span style="color: red">{{ in_form.username.errors.0 }}</span>
    </p>
    <p>
        {{ in_form.pwd.label }}
        {{ in_form.pwd }}
        <span style="color: red"> {{ in_form.pwd.errors.0 }}</span>
    </p>
    <p>
        {{ in_form.re_pwd.label }}
        {{ in_form.re_pwd }}
        <span style="color: red">{{ in_form.re_pwd.errors.0 }}</span>
    </p>
    <p>
        <input type="submit" value="提交">
    </p>
</form>
</body>
</html>

Form组件其他输入标签

邮箱

class Argforms(forms.Form):
    ···
    Email = forms.EmailField()

单选Select

class Argforms(forms.Form):
    ···
    city = forms.ChoiceField(
        label="所在城市",
        ## 所有选项
        choices=((1, '北京'), (2, '上海'), (3, '广州')),
        ## 默认选中
        initial=1,
    )

多选Select

class Argforms(forms.Form):
    ···
    gender = forms.MultipleChoiceField(
        label="爱好",
        choices=((1, '篮球'), (2, '足球'), (3, '台球'), (4, '保龄球')),
        initial=[1, 3],

单选Checkbox

class Argforms(forms.Form):
    ···
    gender = forms.ChoiceField(
        label="性别",
        choices=((1, '男'), (2, '女'), (3, '保密')),
        initial=3,
        widget= forms.widgets.RadioSelect
    )

多选Checkbox

class Argforms(forms.Form):
    ···
    gender = forms.MultipleChoiceField(
        label="爱好",
        choices=((1, '篮球'), (2, '足球'), (3, '台球'), (4, '保龄球')),
        initial=[1, 3],
        widget= forms.widgets.CheckboxSelectMultiple

给标签定义类,方便页面上的css、js对标签进行处理

class Argforms(forms.Form):
    username = forms.CharField(max_length=16, label="用户名", error_messages={
        "required": "用户名不能为空!",
    },                                         ## attrs设置属性,定义class为p1
                                                widget= forms.widgets.TextInput(attrs={'class': 'p1'}))

校验

Form组件中除了内置的校验(min_length最小值/max_length最大值/required是否为空)外,还是如下:

  • 使用正则校验
  • 自定义校验函数
  • 使用Form类中内置的 clean_字段名() 方法进行字段校验
  • 使用Form类中内置的 clean() 方法进行全局校验

正则校验

## 导入内置的正则
from django.core.validators import RegexValidator
class Argforms(forms.Form):
    ···
    phone = forms.CharField(
        label="手机",
        ## 自定义规则
        validators=[
            ## 使用正则匹配,匹配不上返回后面的错误信息
            RegexValidator(r'[0-9]+$', "手机号必须是数字!"),
            RegexValidator(r'^1[3-9][0-9]{9}$', "手机号格式不对!")
        ]
    ),

自定义校验函数

## 导入Python的正则模块
import re
## 导入Django错误格式
from django.core.exceptions import ValidationError
## 定义校验规则
def PhoneCheck(value):
    check = re.compile(r'^1[3-9][0-9]{9}$')
    if not check.match(value):
        raise ValidationError('手机号格式错误!')


class Argforms(forms.Form):
    ···
    phone = forms.CharField(
        label="手机",
        ## 引用自定义函数校验
        validators=[PhoneCheck, ],
    )

clean_字段名() 字段校验

## 导入Django错误格式
from django.core.exceptions import ValidationError

class Argforms(forms.Form):
    username = forms.CharField(max_length=16, label="用户名", error_messages={
        "required": "用户名不能为空!",
    },)

    ## 定义方法,用来校验username字段
    def clean_username(self):
        value = self.cleaned_data.get("username", None)
        if value in "***":
            raise ValidationError("禁止吐星星!")
        else:
            return value

clean() 进行全局校验

class Argforms(forms.Form):
    ···
    pwd = forms.CharField(min_length=6, label="密码", error_messages={
        "min_length": "密码不能小于6位!",
        "required": "密码不能为空",
    }, widget = widgets.PasswordInput)
    re_pwd = forms.CharField(min_length=6, label="确认密码", error_messages={
        "min_length": "密码不能小于6位!",
        "required": "密码不能为空",
    }, widget = widgets.PasswordInput)

    ## 定义方法,用来校验密码和确认密码是否一致
    def clean(self):
        pwd = self.cleaned_data.get("pwd", None)
        re_pwd = self.cleaned_data.get("re_pwd", None)
        if pwd != re_pwd:
            self.add_error("re_pwd", "两次密码不一致!")
        else:
            return self.cleaned_data
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 —— —— —— 最小值

FloatField(IntegerField)
    ...

DecimalField(IntegerField)
    max_value=None —— —— —— 最大值
    min_value=None —— —— —— 最小值
    max_digits=None —— —— —— 总长度
    decimal_places=None —— —— —— 小数位长度

BaseTemporalField(Field)
    input_formats=None —— —— —— 时间格式化   

DateField(BaseTemporalField) —— —— —— 格式:2015-09-01
TimeField(BaseTemporalField) —— —— —— 格式:11:12
DateTimeField(BaseTemporalField) —— —— —— 格式:2015-09-01 11:12

DurationField(Field) —— —— —— 时间间隔:%d %H:%M:%S.%f
    ...

RegexField(CharField)
    regex —— —— —— 自定制正则表达式
    max_length=None —— —— —— 最大长度
    min_length=None —— —— —— 最小长度
    error_message=None —— —— —— 忽略,错误信息使用 error_messages={'invalid': '...'}

EmailField(CharField)      
    ...

FileField(Field)
    allow_empty_file=False —— —— —— 是否允许空文件

ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)

URLField(Field)
    ...

BooleanField(Field)  
    ...

NullBooleanField(BooleanField)
    ...

ChoiceField(Field)
    ...
    choices=() —— —— —— 选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True —— —— —— 是否必填
    widget=None —— —— —— 插件,默认select插件
    label=None —— —— —— Label内容
    initial=None —— —— —— 初始值
    help_text='' —— —— —— 帮助提示


ModelChoiceField(ChoiceField)
    ... django.forms.models.ModelChoiceField
    queryset, —— —— —— 查询数据库中的数据
    empty_label="---------",  —— —— —— 默认空显示内容
    to_field_name=None, —— —— —— HTML中value的值对应的字段
    limit_choices_to=None —— —— —— ModelForm中对queryset二次筛选

ModelMultipleChoiceField(ModelChoiceField)
    ... django.forms.models.ModelMultipleChoiceField

TypedChoiceField(ChoiceField)
    coerce = lambda val: val —— —— —— 对选中的值进行一次转换
    empty_value= '' —— —— —— 空值的默认值

MultipleChoiceField(ChoiceField)
    ...

TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val —— —— —— 对选中的每一个值进行一次转换
    empty_value= '' —— —— —— 空值的默认值

ComboField(Field)
    fields=() —— —— —— 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])

MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用

SplitDateTimeField(MultiValueField)
    input_date_formats=None —— —— —— 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None —— —— —— 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']

FilePathField(ChoiceField) —— —— —— 文件选项,目录下文件显示在页面中
    path —— —— —— 文件夹路径
    match=None —— —— —— 正则匹配
    recursive=False —— —— —— 递归下面的文件夹
    allow_files=True —— —— —— 允许文件
    allow_folders=False —— —— —— 允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''

GenericIPAddressField
    protocol='both' —— —— —— both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False —— —— —— 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用

SlugField(CharField) —— —— —— 数字,字母,下划线,减号(连字符)
    ...

UUIDField(CharField) —— —— —— uuid类型
原文地址:https://www.cnblogs.com/songguoyou/p/11883372.html