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'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f'

    # 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')

  

 

posted @ 2019-03-03 10:29  -零  阅读(308)  评论(0编辑  收藏  举报