Django之Form組件

https://www.cnblogs.com/wupeiqi/articles/6144178.htmlhtml

 

Django的Form主要具備一下幾大功能:python

  • 生成HTML標籤
  • 驗證用戶數據(顯示錯誤信息)
  • HTML Form提交保留上次提交數據
  • 初始化頁面顯示內容

小試牛刀

一、建立Form類git

二、View函數處理正則表達式

三、生成HTML數據庫

    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        
            {{ form.xxoo.label }}
            {{ form.xxoo.id_for_label }}
            {{ form.xxoo.label_tag }}
            {{ form.xxoo.errors }}
            <p>{{ form.user }} {{ form.user.errors }}</p>
            <input type="submit" />
    </form>
其餘標籤有

Form類

建立Form類時,主要涉及到 【字段】 和 【插件】,字段用於對用戶請求數據的驗證,插件用於自動生成HTML;django

一、Django內置字段以下:dom

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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類型
     ...

注:UUID是根據MAC以及當前時間等建立的不重複的隨機字符串ide

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

二、Django內置插件:函數

經常使用選擇插件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 單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
# )

在使用選擇標籤時,須要注意choices的選項能夠從數據庫中獲取,可是因爲是靜態字段 ***獲取的值沒法實時更新***,那麼須要自定義構造方法從而達到此目的。ui

方式一:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
 
     user = fields.ChoiceField(
         # choices=((1, '上海'), (2, '北京'),),
         initial = 2 ,
         widget = widgets.Select
     )
 
     def __init__( self , * args, * * kwargs):
         super (MyForm, self ).__init__( * args, * * kwargs)
         # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)
         # 或
         self .fields[ 'user' ].widget.choices = models.Classes.objects. all ().value_list( 'id' , 'caption' )

方式二:

使用django提供的ModelChoiceField和ModelMultipleChoiceField字段來實現

?
1
2
3
4
5
6
7
8
9
10
from django import forms
from django.forms import fields
from django.forms import widgets
from django.forms import models as form_model
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
 
class FInfo(forms.Form):
     authors = form_model.ModelMultipleChoiceField(queryset = models.NNewType.objects. all ())
     # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

自定義驗證規則

方式一:

?
1
2
3
4
5
6
7
8
9
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
     user = fields.CharField(
         validators = [RegexValidator(r '^[0-9]+$' , '請輸入數字' ), RegexValidator(r '^159[0-9]+$' , '數字必須以159開頭' )],
     )

方式二:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定義驗證規則
def mobile_validate(value):
     mobile_re = re. compile (r '^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$' )
     if not mobile_re.match(value):
         raise ValidationError( '手機號碼格式錯誤' )
 
 
class PublishForm(Form):
 
 
     title = fields.CharField(max_length = 20 ,
                             min_length = 5 ,
                             error_messages = { 'required' : '標題不能爲空' ,
                                             'min_length' : '標題最少爲5個字符' ,
                                             'max_length' : '標題最多爲20個字符' },
                             widget = widgets.TextInput(attrs = { 'class' : "form-control" ,
                                                           'placeholder' : '標題5-20個字符' }))
 
 
     # 使用自定義驗證規則
     phone = fields.CharField(validators = [mobile_validate, ],
                             error_messages = { 'required' : '手機不能爲空' },
                             widget = widgets.TextInput(attrs = { 'class' : "form-control" ,
                                                           'placeholder' : u '手機號碼' }))
 
     email = fields.EmailField(required = False ,
                             error_messages = { 'required' : u '郵箱不能爲空' , 'invalid' : u '郵箱格式錯誤' },
                             widget = widgets.TextInput(attrs = { 'class' : "form-control" , 'placeholder' : u '郵箱' }))

方法三:自定義方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from django import forms
     from django.forms import fields
     from django.forms import widgets
     from django.core.exceptions import ValidationError
     from django.core.validators import RegexValidator
 
     class FInfo(forms.Form):
         username = fields.CharField(max_length = 5 ,
                                     validators = [RegexValidator(r '^[0-9]+$' , 'Enter a valid extension.' , 'invalid' )], )
         email = fields.EmailField()
 
         def clean_username( self ):
             """
             Form中字段中定義的格式匹配完以後,執行此方法進行驗證
             :return:
             """
             value = self .cleaned_data[ 'username' ]
             if "666" in value:
                 raise ValidationError( '666已經被玩爛了...' , 'invalid' )
             return value

方式四:同時生成多個標籤進行驗證

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from django.forms import Form
from django.forms import widgets
from django.forms import fields
 
from django.core.validators import RegexValidator
 
 
############## 自定義字段 ##############
class PhoneField(fields.MultiValueField):
     def __init__( self , * args, * * kwargs):
         # Define one message for all fields.
         error_messages = {
             'incomplete' : 'Enter a country calling code and a phone number.' ,
         }
         # Or define a different message for each field.
         f = (
             fields.CharField(
                 error_messages = { 'incomplete' : 'Enter a country calling code.' },
                 validators = [
                     RegexValidator(r '^[0-9]+$' , 'Enter a valid country calling code.' ),
                 ],
             ),
             fields.CharField(
                 error_messages = { 'incomplete' : 'Enter a phone number.' },
                 validators = [RegexValidator(r '^[0-9]+$' , 'Enter a valid phone number.' )],
             ),
             fields.CharField(
                 validators = [RegexValidator(r '^[0-9]+$' , 'Enter a valid extension.' )],
                 required = False ,
             ),
         )
         super (PhoneField, self ).__init__(error_messages = error_messages, fields = f, require_all_fields = False , * args,
                                          * * kwargs)
 
     def compress( self , data_list):
         """
         當用戶驗證都經過後,該值返回給用戶
         :param data_list:
         :return:
         """
         return data_list
 
############## 自定義插件 ##############
class SplitPhoneWidget(widgets.MultiWidget):
     def __init__( self ):
         ws = (
             widgets.TextInput(),
             widgets.TextInput(),
             widgets.TextInput(),
         )
         super (SplitPhoneWidget, self ).__init__(ws)
 
     def decompress( self , value):
         """
         處理初始值,當初始值initial不是列表時,調用該方法
         :param value:
         :return:
         """
         if value:
             return value.split( ',' )
         return [ None , None , None ]

初始化數據

在Web應用程序中開發編寫功能時,時經常使用到獲取數據庫中的數據並將值初始化在HTML中的標籤上。

一、Form

二、Views

三、HTML

相關文章
相關標籤/搜索