zoukankan      html  css  js  c++  java
  • django forms

    目录

    一、校验字段功能
    1、模型:models.py
    2、模板:reg.html
    3、视图函数:views.py
    二、渲染标签功能
    1、渲染方式一:
    2、渲染方式二
    3、渲染方式三
    三、显示错误与重置输入信息功能
    四、forms组件的参数配置
    1、reg.html引入样式
    2、在视图层引入widgets模块,配置修改forms类参数
    五、局部钩子和全局钩子
    六、Forms组件归类及补充
    1、Django内置字段:
    2、Django内置插件
    3、常用选择插件
    4、扩展博客

    一、校验字段功能
      通过注册用户这个实例来学习校验字段功能。

    1、模型:models.py
    from django.db import models

    Create your models here.

    class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    email = models.EmailField()
    tel = models.CharField(max_length=32)

     修改配置后,完成数据库迁移操作,可以查看到UserInfo表已经创建完成。

    2、模板:reg.html

    Title
    {% csrf_token %}

    用户名

    密码

    确认密码

    邮箱

    手机号

    3、视图函数:views.py

    from django.shortcuts import render,HttpResponse

    Create your views here.

    from django import forms # 引入forms组件

    class UserForm(forms.Form): # 必须继承forms.Form
    name = forms.CharField(min_length=4)
    pwd = forms.CharField(min_length=4)
    r_pwd = forms.CharField(min_length=4)
    email = forms.EmailField()
    tel = forms.CharField()

    def reg(request):
    if request.method=="POST":
    print(request.POST)
    # 生成forms对象后,传入字典就可以做一个个值的校验
    # form = UserForm({"name": "yuan", "email": "123@qq.com", "xxx":"alex"})
    form = UserForm(request.POST) # form表单的name属性值应该与forms组件的字段名称一致,不一致的键值不会去做校验
    print(form.is_valid()) # 返回True/False
    # 帮忙校验
    if form.is_valid(): # 注意:form.is_valid是帮忙校验返回布尔值的,true或false(所有都通过才返回true)
    # 类定义的字段均符合要求,返回true,有多的字段直接忽略
    print(form.cleaned_data) # {'name': 'yuan', 'pwd': '1234', 'r_pwd': '1234', 'email': '1234@163.com', 'tel': '123123'}
    else:
    # 有正确也有错误信息也是返回false
    print(form.cleaned_data) # 字段值符合要求的放在cleaned_data {'name': 'yuan', 'pwd': '123456', 'tel': '123123'}
    print(form.errors) # 字段不符合要求的对应的键作为键,错误信息作为值

    • r_pwd
        ...
        print(type(form.errors)) # <class 'django.forms.utils.ErrorDict'> 还是一个字段类型
        print(form.errors.get("r_pwd")) #
        • This field is required.

        print(type(form.errors.get("r_pwd"))) # <class 'django.forms.utils.ErrorList'> 用列表存放错误信息
        print(form.errors.get("r_pwd")[0]) # 获取到报错信息:This field is required.
        """
        form.is_valid() 校验返回布尔值
        if 所有的字段校验成功,则form.cleaned_data:{"name": "yuan", "email": "123@qq.com"}
        如果校验失败,则form.errors放入所有错误的字段。
        """
        return HttpResponse("OK")
        return render(request, "reg.html")

        注意:

        (1)引入forms组件,定义的类必须继承forms.Form,forms类定义过的属性默认非空。

        from django import forms # 引入forms组件

        class UserForm(forms.Form): # 必须继承forms.Form
        name = forms.CharField(min_length=4)
        pwd = forms.CharField(min_length=4)
        r_pwd = forms.CharField(min_length=4)
        email = forms.EmailField()
        tel = forms.CharField()

        (2)生成forms对象,需要注意的是给对象传入字典就可以做一个个值的校验:

        1 form = UserForm({"name": "yuan", "email": "123@qq.com", "xxx":"alex"})
          但是我们需要的是form表单属性与forms组件字段的校验,因此需要把request.POST传入forms对象:

        1 form = UserForm(request.POST)
          form表单的name属性值应该与forms组件的字段名称一致,不一致的键值不会去做校验。

        (3)form.is_valid() :做校验返回布尔值的,所有都通过才返回True,否则返回False。与forms组件字段无关的键值不影响返回结果。

        if form.is_valid(): # 注意:form.is_valid是帮忙校验返回布尔值的,true或false(所有都通过才返回true)
        # 类定义的字段均符合要求,返回true,有多的字段直接忽略
        print(form.cleaned_data) # {'name': 'yuan', 'pwd': '1234', 'r_pwd': '1234', 'email': '1234@163.com', 'tel': '123123'}
        else:
        # 有正确也有错误信息也是返回false
        print(form.cleaned_data) # 字段值符合要求的放在cleaned_data {'name': 'yuan', 'pwd': '123456', 'tel': '123123'}
        print(form.errors) # 字段不符合要求的对应的键作为键,错误信息作为值

        • r_pwd
            ...

            (4)form.cleaned_data:字段值符合要求的放在cleaned_data中。字典数据类型。

            (5)form.errors:字段不符合要求的对应的键作为键,错误信息作为值。虽然返回结果比较复杂,但依然是字典数据类型,可以通过form.errors.get(“不符合的键”)来拿到键值,键值为列表数据类型。因此可以通过form.errors.get("不符合键")[0]拿到错误信息。

            二、渲染标签功能
            1、渲染方式一:
            视图函数:将forms空对象传给模板

            from django import forms # 引入forms组件

            class UserForm(forms.Form): # 必须继承forms.Form
            # forms.CharField和forms.EmailField会渲染为input标签
            name = forms.CharField(min_length=4) # 默认label是字段名
            pwd = forms.CharField(min_length=4, label="密码") # 如果需要中文label可以手动设置
            r_pwd = forms.CharField(min_length=4, label="确认密码")
            email = forms.EmailField(label="邮箱")
            tel = forms.CharField(label="手机")

            def reg(request):
            form = UserForm()
            return render(request, "reg.html", locals())

            模板:

            form组件渲染方式1

            {% csrf_token %}

            {{ form.name.label }} {{ form.name }}

            {{ form.pwd.label }} {{ form.pwd }}

            {{ form.r_pwd.label }} {{ form.r_pwd }}

            {{ form.email.label }} {{ form.email }}

            {{ form.tel.label }} {{ form.tel }}

            渲染效果:

            2、渲染方式二

            其他与方式一同理,但是用for循环获取forms对象内字段。

            forms组件渲染方式2

            {% csrf_token %} {% for field in form %}

            {{ field }}

            {% endfor %}

            3、渲染方式三
             调用form对象的组件:as_p,即完成渲染。缺点是结构固定。(还有一种是as_ul)


            forms组件渲染方式3

            {% csrf_token %} {{ form.as_p }}

            三、显示错误与重置输入信息功能

            1、视图
            def reg(request):
            if request.method=="POST":
            form = UserForm(request.POST) # 绑定数据的form表单
            print(form.is_valid()) # 返回True/False
            if form.is_valid():
            # 类定义的字段均符合要求,返回true,有多的字段直接忽略
            print(form.cleaned_data) #所有干净字段及对应的值
            else:
            # 有正确也有错误信息也是返回false
            print(form.cleaned_data)
            # print(form.errors) # ErrorDict : {"校验错误的字段":["错误信息",]}
            # print(form.errors.get("name")) # ErrorList ["错误信息",]
            return render(request, "reg.html", locals())

            form = UserForm()   # 未绑定数据的form表单
            return render(request, "reg.html", locals())
            

            2、模板

            显示错误与重置输入信息

            {% csrf_token %}

            {{ form.name.label }} {{ form.name }} {{ form.name.errors.0 }}

            {{ form.pwd.label }} {{ form.pwd }} {{ form.pwd.errors.0 }}

            {{ form.r_pwd.label }} {{ form.r_pwd }} {{ form.r_pwd.errors.0 }}

            {{ form.email.label }} {{ form.email }} {{ form.email.errors.0 }}

            {{ form.tel.label }} {{ form.tel }} {{ form.tel.errors.0 }}

            四、forms组件的参数配置
              上面完成的注册页面,显示效果比较糟糕。因此需要引入widgets模块来调整组件参数配置,优化小时效果。

            1、reg.html引入样式
              模板引入bootstrap,并仅保留渲染方式一生成的注册登录页面。


            form组件渲染方式1

            {% csrf_token %}

            {{ form.name.label }} {{ form.name }} {{ form.name.errors.0 }}

            {{ form.pwd.label }} {{ form.pwd }} {{ form.pwd.errors.0 }}

            {{ form.r_pwd.label }} {{ form.r_pwd }} {{ form.r_pwd.errors.0 }}

            {{ form.email.label }} {{ form.email }} {{ form.email.errors.0 }}

            {{ form.tel.label }} {{ form.tel }} {{ form.tel.errors.0 }}

            2、在视图层引入widgets模块,配置修改forms类参数

            from django.shortcuts import render,HttpResponse

            Create your views here.

            from django import forms # 引入forms组件
            from django.forms import widgets

            class UserForm(forms.Form): # 必须继承forms.Form
            # forms.CharField和forms.EmailField会渲染为input标签
            name = forms.CharField(min_length=4, label="用户名", error_messages={"requried": "该字段不能为空"},
            widget=widgets.TextInput(attrs={"class": "form-control"})
            )
            pwd = forms.CharField(min_length=4, label="密码", # 如果需要中文label可以手动设置
            widget=widgets.PasswordInput(attrs={"class": "form-control"}) # 生成密文文本输入框
            )
            r_pwd = forms.CharField(min_length=4, label="确认密码",
            widget=widgets.TextInput(attrs={"class": "form-control"}))
            email = forms.EmailField(label="邮箱", error_messages={"requried": "该字段不能为空", "invalid": "格式错误"},
            widget=widgets.EmailInput(attrs={"class": "form-control"})
            ) # invalid修改格式错误提示
            tel = forms.CharField(label="手机",error_messages={"requried": "该字段不能为空"},
            widget=widgets.TextInput(attrs={"class": "form-control"})

            注意:

              (1)在字段构造参数中设置"error_messages"修改字段错误提示消息:其中"requried"负责字段不能为空消息提示;"invalid"负责格式错误消息提示等。

              (2)在字段构造函数中配置input类型:设置为文本域、密码域、单选框、复选框等等类型。

            widget=widgets.TextInput()
            widget=widgets.PasswordInput()
            widget=widgets.EmailInput()

            (2)给字段构造函数中配置修改属性。比如给type="text"的input标签设置bootstrap样式,给input标签添加类"form-control"。

            显示效果:

            五、局部钩子和全局钩子
              为了将代码解耦可以选择自己创建一个文件比如app01/myform.py存放钩子。

            1、myform.py:

            forms组件

            from django.forms import widgets

            wid_01=widgets.TextInput(attrs={"class":"form-control"})
            wid_02=widgets.PasswordInput(attrs={"class":"form-control"})

            from django.core.exceptions import ValidationError
            class UserForm(forms.Form):
            name=forms.CharField(max_length=32,
            widget=wid_01
            )
            pwd=forms.CharField(max_length=32,widget=wid_02)
            r_pwd=forms.CharField(max_length=32,widget=wid_02)
            email=forms.EmailField(widget=wid_01)
            tel=forms.CharField(max_length=32,widget=wid_01)

            # 局部钩子
            def clean_name(self):
                val=self.cleaned_data.get("name")
                if not val.isdigit():
                    return val
                else:
                    raise ValidationError("用户名不能是纯数字!")
            
            # 全局钩子
            def clean(self):
                pwd=self.cleaned_data.get("pwd")
                r_pwd=self.cleaned_data.get("r_pwd")
            
                if pwd==r_pwd:
                    return self.cleaned_data
                else:
                    raise ValidationError('两次密码不一致!')
            

            views.py:

            from django.shortcuts import render,HttpResponse

            Create your views here.

            from app01.myforms import *

            def reg(request):
            if request.method=="POST":
            form = UserForm(request.POST) # 绑定数据的form表单
            if form.is_valid():
            # 类定义的字段均符合要求,返回true,有多的字段直接忽略
            print(form.cleaned_data)
            else:
            print(form.cleaned_data) # 字段值符合要求的放在cleaned_data {'name': 'yuan', 'pwd': '123456', 'tel': '123123'}

                    # 全局钩子错误
                    # print("error", form.errors.get("__all__")[0])
                    errors = form.errors.get("__all__")
            
                    return render(request, "reg.html", locals())
            
            form = UserForm()   # 未绑定数据的form表单
            return render(request, "reg.html", locals())
            

            reg.html:

            {% csrf_token %}
                    {% for field in form %}
                        <div>
                            <label for="">{{ field.label }}</label>
                            {{ field }}
                            <span class="pull-right" style="color: red">
                                  {% if field.label == 'R pwd' %}
                                  <span>{{ clean_error.0 }}</span>
                                  {% endif %}
                                  {{ field.errors.0 }}
                            </span>
                        </div>
                    {% endfor %}
                    <input type="submit" class="btn btn-default">
            
            六、Forms组件归类及补充 Django的Form主要具有一下几大功能:

            生成HTML标签
            验证用户数据(显示错误信息)
            HTML Form提交保留上次提交数据
            初始化页面显示内容

            1、Django内置字段:
            Field
            required=True, 是否允许为空
            widget=None, HTML插件
            label=None, 用于生成Label标签或显示内容
            initial=None, 初始值
            help_text='', 帮助信息(在标签旁边显示)
            error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
            show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
            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类型

            2、Django内置插件
            TextInput(Input)
            NumberInput(TextInput)
            EmailInput(TextInput)
            URLInput(TextInput)
            PasswordInput(TextInput)
            HiddenInput(TextInput)
            Textarea(Widget)
            DateInput(DateTimeBaseInput)
            DateTimeInput(DateTimeBaseInput)
            TimeInput(DateTimeBaseInput)
            CheckboxInput
            Select
            NullBooleanSelect
            SelectMultiple
            RadioSelect
            CheckboxSelectMultiple
            FileInput
            ClearableFileInput
            MultipleHiddenInput
            SplitDateTimeWidget
            SplitHiddenDateTimeWidget
            SelectDateWidget

            3.常用选择插件

            单radio,值为字符串

            user = fields.CharField(

            initial=2,

            widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))

            )

            单radio,值为字符串

            user = fields.ChoiceField(

            choices=((1, '上海'), (2, '北京'),),

            initial=2,

            widget=widgets.RadioSelect

            )

            单select,值为字符串

            user = fields.CharField(

            initial=2,

            widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))

            )

            单select,值为字符串

            user = fields.ChoiceField(

            choices=((1, '上海'), (2, '北京'),),

            initial=2,

            widget=widgets.Select

            )

            多选select,值为列表

            user = fields.MultipleChoiceField(

            choices=((1,'上海'),(2,'北京'),),

            initial=[1,],

            widget=widgets.SelectMultiple

            )

            单checkbox

            user = fields.CharField(

            widget=widgets.CheckboxInput()

            )

            多选checkbox,值为列表

            user = fields.MultipleChoiceField(

            initial=[2, ],

            choices=((1, '上海'), (2, '北京'),),

            widget=widgets.CheckboxSelectMultiple

            )

  • 相关阅读:
    通过url在两个页面之间传值
    $.ajax数据传输成功却执行失败的回调函数
    5.26小测
    洛谷——AC记
    7.2模拟赛
    6.30模拟赛
    洛谷——每日一题
    洛谷——动态规划
    致创营
    BSGS
  • 原文地址:https://www.cnblogs.com/lihuafeng/p/14647992.html
Copyright © 2011-2022 走看看