• Django之Form组件(一)


    Django之Form组件(一)

     

    Django的Form主要具有一下几大功能:
    
    生成HTML标签
    验证用户数据(显示错误信息)
    HTML Form提交保留上次提交数据
    初始化页面显示内容
    

      

    基本操作:字段验证并显示错误信息,渲染标签(生成HTML标签),保留上次提交数据

     1 from django.shortcuts import render,HttpResponse,redirect
     2 from django import forms  #引入模块
     3 from django.forms import fields
     4 
     5 
     6 class FiForm(forms.Form): #必须继承forms.Form
    7 user=fields.CharField(max_length=12,min_length=6,required=True, 8 error_messages={ 9 'required': '用户名不能为空', 10 'max_length': '用户名最大12位', 11 'min_length':'用户名最少6位', 12 }) 13 14 pwd=fields.CharField(min_length=12,required=True, 15 error_messages={ 16 'required': '密码不能为空', 17 'min_length': '密码最少12位', 18 19 }) 20 age=fields.IntegerField(required=True, 21 error_messages={ 22 'required': '年龄不能为空', 23 }) 24 email=fields.EmailField(required=True, 25 error_messages={ 26 'required':'邮箱格式不对' 27 }) 28 29 def login1(request): 30 31 if request.method =='GET': 32 obj=FiForm()#第一次生成FiForm对象,没有传参,生成HTML代码 33 return render(request,"login1.html",{'obj':obj}) 34 else: 35 u=request.POST.get('user') #不能为空,长度6-12 36 p=request.POST.get('passwd') #不能为空,长度12 37 e = request.POST.get('email')#不能为空,邮箱格式 38 a = request.POST.get('age')#不能为空,数字类型 39 print(u,p,e,a) 40 #检查是否为空 41 #检查格式 42 obj=FiForm(request.POST) #传入数据进行字段验证,form表单的name属性值应该与forms组件的字段名称一致,不一致的键值不会去做校验。 43 #是否全部验证成功,返回true或false 44 if obj.is_valid(): 45 经过验证后得到的的数据 46 print('验证成功',obj.cleaned_data) 47 else: 48 print('验证失败',obj.errors) # 字段不符合要求的对应的键作为键,错误信息作为值   <ul class="errorlist"><li>r_pwd<ul class="errorlist">... 49 return render(request,"login1.html",{'obj':obj}) #传入obj对象

     分析:

    (1)引入模块

    from django import forms  
    from django.forms import fields
     

     (2)生成验证类

    class FiForm(forms.Form):
        user=fields.CharField(max_length=12,min_length=6,required=True,
                              error_messages={
                                  'required': '用户名不能为空',
                                  'max_length': '用户名最大12位',
                                  'min_length':'用户名最少6位',
                              })
    
        pwd=fields.CharField(min_length=12,required=True,
                             error_messages={
                                 'required': '密码不能为空',
                                 'min_length': '密码最少12位',
    
                             })
        age=fields.IntegerField(required=True,
                             error_messages={
                            'required': '年龄不能为空',
        })
        email=fields.EmailField(required=True,
                               error_messages={
                            'required':'邮箱格式不对'
                               })

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

    例:form = UserForm({"name": "yuan", "email": "123@qq.com", "xxx":"alex"})
    obj=FiForm(request.POST)
    注意:form表单的name属性值应该与forms组件的字段名称一致,不一致的键值不会去做校验
    

      

    (4)

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

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

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

    form.errors.get("pwd") #在后端取
    
    {{ obj.errors.user.0 }} #在前端取,obj为传过去的对象。
    

      

    (5)去掉浏览器的验证机制

    如果你的表单包含URLField``EmailField 或其它整数字段类型,Django 将使用number、url和 email 这样的HTML5 输入类型。 默认情况下,浏览器可能会对这些字段进行它们自身的验证,这些验证可能比Django 的验证更严格。 如果你想禁用这个行为,请设置form 标签的novalidate属性,
    或者指定一个不同的字段,如TextInput

      

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 <form action="/login1/" method="POST">
     9     {% csrf_token %}
    10         <!--<p>用户名:<input type="text" name="user">{{ obj.errors.user.0 }}</p>-->
    11         <!--<p>密码:<input type="password"  name="passwd">{{ obj.errors.pwd.0 }}</p>-->
    12         <!--<p>邮箱:<input type="text" name="email">{{ obj.errors.email.0 }}</p>-->
    13         <!--<p>年龄:<input type="text"  name="age">{{ obj.errors.age.0 }}</p>-->
    14         <p>用户名:{{ obj.user }}{{ obj.errors.user.0 }}</p>
    15         <p>密码:{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
    16         <p>邮箱:{{ obj.email }}{{ obj.errors.email.0 }}</p>
    17         <p>年龄:{{ obj.age }}{{ obj.errors.age.0 }}</p>
    18         <p><input type="submit" value="提交"></p>
    19 
    20 </form>
    21 
    22 </body>
    23 </html>

     渲染

     第一种渲染方式

    form = UserForm()
    注意:任何一个Field都有两个功能:验证和插件。

    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())
    

      

    <h3>form组件渲染方式1</h3>
    <form action="" method="post">
        {% csrf_token %}
        <p>{{ form.name.label }}
            {{ form.name }}
        </p>
        <p>{{ form.pwd.label }}
            {{ form.pwd }}
        </p>
        <p>{{ form.r_pwd.label }}
            {{ form.r_pwd }}
        </p>
        <p>{{ form.email.label }}
            {{ form.email }}
        </p>
        <p>{{ form.tel.label }}
            {{ form.tel }}
        </p>
        <input type="submit">
    </form>
    

      

    第二种渲染方式

    调用form对象的组件,即完成渲染。缺点是结构固定

    {{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
    {{ form.as_p }} 将它们渲染在<p> 标签中
    {{ form.as_ul }} 将它们渲染在<li> 标签中
    
    <hr>
    <h3>form组件渲染方式2</h3>
    <form action="" method="post">
        {% csrf_token %}
        {{ form.as_p }}
    </form>
    

      

     

    初始化数据

     在Web应用程序中开发编写功能时,时常用到获取数据库中的数据并将值初始化在HTML中的标签上。

    if request.method =='GET':
    
       values = { 'username': 'root', 'pwd': '123123', 'email': 'aaa@163.com', 'age':12, }
    
        obj=FiForm(initial=values)
    

      

    Form组件归类

    全部字段

      1 每一个Field都有一个正则表达式和默认插件
      2 
      3 
      4 
      5 
      6 
      7 
      8 创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
      9 
     10 Field
     11     required=True,               是否允许为空
     12     widget=None,                 HTML插件
     13     label=None,                  用于生成Label标签或显示内容
     14     initial=None,                初始值
     15     help_text='',                帮助信息(在标签旁边显示)
     16     error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
     17     show_hidden_initial=False,   是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
     18     validators=[],               自定义验证规则
     19     localize=False,              是否支持本地化
     20     disabled=False,              是否可以编辑
     21     label_suffix=None            Label内容后缀
     22  
     23  
     24 CharField(Field)
     25     max_length=None,             最大长度
     26     min_length=None,             最小长度
     27     strip=True                   是否移除用户输入空白
     28  
     29 IntegerField(Field)
     30     max_value=None,              最大值
     31     min_value=None,              最小值
     32  
     33 FloatField(IntegerField)
     34     ...
     35  
     36 DecimalField(IntegerField)
     37     max_value=None,              最大值
     38     min_value=None,              最小值
     39     max_digits=None,             总长度
     40     decimal_places=None,         小数位长度
     41  
     42 BaseTemporalField(Field)
     43     input_formats=None          时间格式化   
     44  
     45 DateField(BaseTemporalField)    格式:2015-09-01
     46 TimeField(BaseTemporalField)    格式:11:12
     47 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
     48  
     49 DurationField(Field)            时间间隔:%d %H:%M:%S.%f
     50     ...
     51  
     52 RegexField(CharField)
     53     regex,                      自定制正则表达式
     54     max_length=None,            最大长度
     55     min_length=None,            最小长度
     56     error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
     57  
     58 EmailField(CharField)      
     59     ...
     60  
     61 FileField(Field)
     62     allow_empty_file=False     是否允许空文件
     63  
     64 ImageField(FileField)      
     65     ...
     66     注:需要PIL模块,pip3 install Pillow
     67     以上两个字典使用时,需要注意两点:
     68         - form表单中 enctype="multipart/form-data"
     69         - view函数中 obj = MyForm(request.POST, request.FILES)
     70  
     71 URLField(Field)
     72     ...
     73  
     74  
     75 BooleanField(Field)  
     76     ...
     77  
     78 NullBooleanField(BooleanField)
     79     ...
     80  
     81 ChoiceField(Field)
     82     ...
     83     choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
     84     required=True,             是否必填
     85     widget=None,               插件,默认select插件
     86     label=None,                Label内容
     87     initial=None,              初始值
     88     help_text='',              帮助提示
     89  
     90  
     91 ModelChoiceField(ChoiceField)
     92     ...                        django.forms.models.ModelChoiceField
     93     queryset,                  # 查询数据库中的数据
     94     empty_label="---------",   # 默认空显示内容
     95     to_field_name=None,        # HTML中value的值对应的字段
     96     limit_choices_to=None      # ModelForm中对queryset二次筛选
     97      
     98 ModelMultipleChoiceField(ModelChoiceField)
     99     ...                        django.forms.models.ModelMultipleChoiceField
    100  
    101  
    102      
    103 TypedChoiceField(ChoiceField)
    104     coerce = lambda val: val   对选中的值进行一次转换
    105     empty_value= ''            空值的默认值
    106  
    107 MultipleChoiceField(ChoiceField)
    108     ...
    109  
    110 TypedMultipleChoiceField(MultipleChoiceField)
    111     coerce = lambda val: val   对选中的每一个值进行一次转换
    112     empty_value= ''            空值的默认值
    113  
    114 ComboField(Field)
    115     fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
    116                                fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
    117  
    118 MultiValueField(Field)
    119     PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
    120  
    121 SplitDateTimeField(MultiValueField)
    122     input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    123     input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
    124  
    125 FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    126     path,                      文件夹路径
    127     match=None,                正则匹配
    128     recursive=False,           递归下面的文件夹
    129     allow_files=True,          允许文件
    130     allow_folders=False,       允许文件夹
    131     required=True,
    132     widget=None,
    133     label=None,
    134     initial=None,
    135     help_text=''
    136  
    137 GenericIPAddressField
    138     protocol='both',           both,ipv4,ipv6支持的IP格式
    139     unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
    140  
    141 SlugField(CharField)           数字,字母,下划线,减号(连字符)
    142     ...
    143  
    144 UUIDField(CharField)           uuid类型
    145     ...
    View Code

    补充:UUID

    >>> import uuid
    
        # make a UUID based on the host ID and current time
        >>> uuid.uuid1()    # doctest: +SKIP
        UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
    
        # make a UUID using an MD5 hash of a namespace UUID and a name
        >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
        UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
    
        # make a random UUID
        >>> uuid.uuid4()    # doctest: +SKIP
        UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
    
        # make a UUID using a SHA-1 hash of a namespace UUID and a name
        >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
        UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
    
        # make a UUID from a string of hex digits (braces and hyphens ignored)
        >>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}')
    
        # convert a UUID to a string of hex digits in standard form
        >>> str(x)
        '00010203-0405-0607-0809-0a0b0c0d0e0f'
    
        # get the raw 16 bytes of the UUID
        >>> x.bytes
        b'x00x01x02x03x04x05x06x07x08	
    x0bx0c
    x0ex0f'
    
        # make a UUID from a 16-byte string
        >>> uuid.UUID(bytes=x.bytes)
        UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')
    View Code

    全部插件

     1 TextInput(Input)
     2 NumberInput(TextInput)
     3 EmailInput(TextInput)
     4 URLInput(TextInput)
     5 PasswordInput(TextInput)
     6 HiddenInput(TextInput)
     7 Textarea(Widget)
     8 DateInput(DateTimeBaseInput)
     9 DateTimeInput(DateTimeBaseInput)
    10 TimeInput(DateTimeBaseInput)
    11 CheckboxInput
    12 Select
    13 NullBooleanSelect
    14 SelectMultiple
    15 RadioSelect
    16 CheckboxSelectMultiple
    17 FileInput
    18 ClearableFileInput
    19 MultipleHiddenInput
    20 SplitDateTimeWidget
    21 SplitHiddenDateTimeWidget
    22 SelectDateWidget
    View Code

    常用选择插件

     1 # 单radio,值为字符串
     2 # user = fields.CharField(
     3 #     initial=2,
     4 #     widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
     5 # )
     6   
     7 # 单radio,值为字符串
     8 # user = fields.ChoiceField(
     9 #     choices=((1, '上海'), (2, '北京'),),
    10 #     initial=2,
    11 #     widget=widgets.RadioSelect
    12 # )
    13   
    14 # 单select,值为字符串
    15 # user = fields.CharField(
    16 #     initial=2,
    17 #     widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
    18 # )
    19   
    20 # 单select,值为字符串
    21 # user = fields.ChoiceField(
    22 #     choices=((1, '上海'), (2, '北京'),),
    23 #     initial=2,
    24 #     widget=widgets.Select
    25 # )
    26   
    27 # 多选select,值为列表
    28 # user = fields.MultipleChoiceField(
    29 #     choices=((1,'上海'),(2,'北京'),),
    30 #     initial=[1,],
    31 #     widget=widgets.SelectMultiple
    32 # )
    33   
    34   
    35 # 单checkbox
    36 # user = fields.CharField(
    37 #     widget=widgets.CheckboxInput()
    38 # )
    39   
    40   
    41 # 多选checkbox,值为列表
    42 # user = fields.MultipleChoiceField(
    43 #     initial=[2, ],
    44 #     choices=((1, '上海'), (2, '北京'),),
    45 #     widget=widgets.CheckboxSelectMultiple
    46 # )
    View Code

    补充:特殊的单选多选时,数据源如何实时更新

    from django.forms import fields
    from django.forms import widgets
    from app01 import models
    class Form(forms.Form):
        user=fields.CharField()
        passwd=fields.CharField(
            widget=widgets.PasswordInput()
        )
        city_id=fields.IntegerField(
            widget=widgets.Select()
        )
    #每次实例化类的时候都会执行,每次访问网页都会获取数据库里的最新信息 def __init__(self,*args,**kwargs): super(Form,self).__init__(*args,**kwargs) self.fields['city_id'].widget.choices=models.test.objects.values_list('id','city')

      

  • 相关阅读:
    freemark生成静态网页乱码问题
    使用JedisCluster出现异常:java.lang.NumberFormatException
    [程序员代码面试指南]第9章-一种消息接收并打印的结构(链表)
    [程序员代码面试指南]字符串问题-最小包含子串的长度
    [程序员代码面试指南]二叉树问题-判断t1树是否包含t2树的全部拓扑结构、[LeetCode]572. 另一个树的子树
    [程序员代码面试指南]二叉树问题-在二叉树中找到两个节点的最近公共祖先、[LeetCode]235. 二叉搜索树的最近公共祖先(BST)(非递归)
    [Codeforces1174B]Ehab Is an Odd Person
    [CF571B]Minimization(贪心+DP)
    [HDU2577]How to Type(DP)
    [POJ1050]To the Max(最大子段和)
  • 原文地址:https://www.cnblogs.com/-wenli/p/10464213.html
Copyright © 2020-2023  润新知