• 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类型
  • 相关阅读:
    Proof of Stake-股权证明 系列3
    共识算法的比较:Casper vs Tendermint
    我的友情链接
    我的友情链接
    我的友情链接
    我的友情链接
    我的友情链接
    我的友情链接
    我的友情链接
    我的友情链接
  • 原文地址:https://www.cnblogs.com/songguoyou/p/11883372.html
Copyright © 2020-2023  润新知