1. 程式人生 > >Django 框架篇(九): Django中的Form 組件

Django 框架篇(九): Django中的Form 組件

oct return per generic from bsp 路徑 auth 選擇

Django中的Form組件,幫我們處理了 form表單中的校驗, 和錯誤提示的處理:

主要功能:

  • 生成頁面可用的HTML標簽
  • 對用戶提交的數據進行校驗
  • 保留上次輸入內容

使用form組件實現註冊功能

1. 定義一個類, 繼承django中的 forms.Form

代碼實例:

from django import forms

# 按照Django form組件的要求自己寫一個類
class RegForm(forms.Form):
    name = forms.CharField(label="用戶名")
    pwd = forms.CharField(label="密碼")

2. 在視圖函數中, 實例化上面的類, 並且將實例化的對象直接發送到HTML模板中

def register2(request):
    form_obj = RegForm()
    return render(request, "register2.html", {"form_obj": form_obj})

# 這樣在html中只要接受 "form_obj" 就可直接在模板中將 input 組件顯示出來.

HTML模板的代碼:

技術分享圖片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊2</title>
</head>
<body>
    <form action="/reg2/" method="post" novalidate autocomplete="off">
        {% csrf_token %}
        <div>
            <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
            {{ form_obj.name }} {{ form_obj.name.errors.0 }}
        </div>
        <div>
            <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
            {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
        </div>
        <div>
            <input type="submit" class="btn btn-success" value="註冊">
        </div>
    </form>
</body>
</html>
技術分享圖片

3. form表單中的信息 由POST請求發送過來, 然後在視圖中 補充POST請求的處理邏輯:

技術分享圖片
# 使用form組件實現註冊方式
def register2(request):
    form_obj = RegForm()
    if request.method == "POST":
        # 實例化form對象的時候,把post提交過來的數據直接傳進去
        form_obj = RegForm(request.POST)
        # 調用form_obj校驗數據的方法
        if form_obj.is_valid():
            return HttpResponse("註冊成功")
    return render(request, "register2.html", {"form_obj": form_obj})
技術分享圖片

一個簡單的 註冊就已經完成了,

但是可以看到 頁面中的密碼是明文的, 而不是密文, 如果想更改這個, 在正常的頁面中, 直接更改 input 標簽中的 type 就可以了, 但是在django 中沒有提供 type這個字段.

不過不用急, 雖然沒有提供type的字段, 但是django中提供了另外的一個插件 "widgets" . 該插件在 "forms" 裏面, 可以之間用. 裏面有很多不同的類型.

現在, 先來總結一下,Form中的常用字段:

initial

初始值,input框裏面的初始值。

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三"  # 設置默認值
    )
    pwd = forms.CharField(min_length=6, label="密碼")
技術分享圖片 技術分享圖片

error_messages

重寫錯誤信息。

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")
技術分享圖片 技術分享圖片

password

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密碼",
        widget=forms.widgets.PasswordInput(attrs={‘class‘: ‘c1‘}, render_value=True)  # 這裏用到的是插件 widgets 來更改的input中的type 參數
    )
技術分享圖片 技術分享圖片

radioSelect

單radio值為字符串

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用戶名",
        initial="張三",
        error_messages={
            "required": "不能為空",
            "invalid": "格式錯誤",
            "min_length": "用戶名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密碼")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性別",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )
技術分享圖片 技術分享圖片

單選Select

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    ...
    hobby = forms.fields.ChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=3,
        widget=forms.widgets.Select()
    )
技術分享圖片 技術分享圖片

多選Select

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"), ),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )
技術分享圖片 技術分享圖片

單選checkbox

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    ...
    keep = forms.fields.ChoiceField(
        label="是否記住密碼",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )
技術分享圖片 技術分享圖片

多選checkbox

技術分享圖片 技術分享圖片
class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "籃球"), (2, "足球"), (3, "雙色球"),),
        label="愛好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )
技術分享圖片 技術分享圖片

關於choice的註意事項:

在使用選擇標簽時,需要註意choices的選項可以從數據庫中獲取,但是由於是靜態字段 ***獲取的值無法實時更新***,那麽需要自定義構造方法從而達到此目的。

方式一:

技術分享圖片 技術分享圖片
from django.forms import Form
from django.forms import widgets
from django.forms import fields

 
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‘].choices = ((1, ‘上海‘), (2, ‘北京‘),)
        # 或
        self.fields[‘user‘].choices = models.Classes.objects.all().values_list(‘id‘,‘caption‘)
技術分享圖片 技術分享圖片

方式二:

技術分享圖片 技術分享圖片
from django import forms
from django.forms import fields
from django.forms import models as form_model

 
class FInfo(forms.Form):
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多選
    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 單選
技術分享圖片 技術分享圖片

Form中所有的內置字段:

技術分享圖片
 1 Field
  2     required=True,               是否允許為空
  3     widget=None,                 HTML插件
  4     label=None,                  用於生成Label標簽或顯示內容
  5     initial=None,                初始值
  6     help_text=‘‘,                幫助信息(在標簽旁邊顯示)
  7     error_messages=None,         錯誤信息 {‘required‘: ‘不能為空‘, ‘invalid‘: ‘格式錯誤‘}
  8     validators=[],               自定義驗證規則
  9     localize=False,              是否支持本地化
 10     disabled=False,              是否可以編輯
 11     label_suffix=None            Label內容後綴
 12  
 13  
 14 CharField(Field)
 15     max_length=None,             最大長度
 16     min_length=None,             最小長度
 17     strip=True                   是否移除用戶輸入空白
 18  
 19 IntegerField(Field)
 20     max_value=None,              最大值
 21     min_value=None,              最小值
 22  
 23 FloatField(IntegerField)
 24     ...
 25  
 26 DecimalField(IntegerField)
 27     max_value=None,              最大值
 28     min_value=None,              最小值
 29     max_digits=None,             總長度
 30     decimal_places=None,         小數位長度
 31  
 32 BaseTemporalField(Field)
 33     input_formats=None          時間格式化   
 34  
 35 DateField(BaseTemporalField)    格式:2015-09-01
 36 TimeField(BaseTemporalField)    格式:11:12
 37 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 38  
 39 DurationField(Field)            時間間隔:%d %H:%M:%S.%f
 40     ...
 41  
 42 RegexField(CharField)
 43     regex,                      自定制正則表達式
 44     max_length=None,            最大長度
 45     min_length=None,            最小長度
 46     error_message=None,         忽略,錯誤信息使用 error_messages={‘invalid‘: ‘...‘}
 47  
 48 EmailField(CharField)      
 49     ...
 50  
 51 FileField(Field)
 52     allow_empty_file=False     是否允許空文件
 53  
 54 ImageField(FileField)      
 55     ...
 56     註:需要PIL模塊,pip3 install Pillow
 57     以上兩個字典使用時,需要註意兩點:
 58         - form表單中 enctype="multipart/form-data"
 59         - view函數中 obj = MyForm(request.POST, request.FILES)
 60  
 61 URLField(Field)
 62     ...
 63  
 64  
 65 BooleanField(Field)  
 66     ...
 67  
 68 NullBooleanField(BooleanField)
 69     ...
 70  
 71 ChoiceField(Field)
 72     ...
 73     choices=(),                選項,如:choices = ((0,‘上海‘),(1,‘北京‘),)
 74     required=True,             是否必填
 75     widget=None,               插件,默認select插件
 76     label=None,                Label內容
 77     initial=None,              初始值
 78     help_text=‘‘,              幫助提示
 79  
 80  
 81 ModelChoiceField(ChoiceField)
 82     ...                        django.forms.models.ModelChoiceField
 83     queryset,                  # 查詢數據庫中的數據
 84     empty_label="---------",   # 默認空顯示內容
 85     to_field_name=None,        # HTML中value的值對應的字段
 86     limit_choices_to=None      # ModelForm中對queryset二次篩選
 87      
 88 ModelMultipleChoiceField(ModelChoiceField)
 89     ...                        django.forms.models.ModelMultipleChoiceField
 90  
 91  
 92      
 93 TypedChoiceField(ChoiceField)
 94     coerce = lambda val: val   對選中的值進行一次轉換
 95     empty_value= ‘‘            空值的默認值
 96  
 97 MultipleChoiceField(ChoiceField)
 98     ...
 99  
100 TypedMultipleChoiceField(MultipleChoiceField)
101     coerce = lambda val: val   對選中的每一個值進行一次轉換
102     empty_value= ‘‘            空值的默認值
103  
104 ComboField(Field)
105     fields=()                  使用多個驗證,如下:即驗證最大長度20,又驗證郵箱格式
106                                fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
107  
108 MultiValueField(Field)
109     PS: 抽象類,子類中可以實現聚合多個字典去匹配一個值,要配合MultiWidget使用
110  
111 SplitDateTimeField(MultiValueField)
112     input_date_formats=None,   格式列表:[‘%Y--%m--%d‘, ‘%m%d/%Y‘, ‘%m/%d/%y‘]
113     input_time_formats=None    格式列表:[‘%H:%M:%S‘, ‘%H:%M:%S.%f‘, ‘%H:%M‘]
114  
115 FilePathField(ChoiceField)     文件選項,目錄下文件顯示在頁面中
116     path,                      文件夾路徑
117     match=None,                正則匹配
118     recursive=False,           遞歸下面的文件夾
119     allow_files=True,          允許文件
120     allow_folders=False,       允許文件夾
121     required=True,
122     widget=None,
123     label=None,
124     initial=None,
125     help_text=‘‘
126  
127 GenericIPAddressField
128     protocol=‘both‘,           both,ipv4,ipv6支持的IP格式
129     unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1時候,可解析為192.0.2.1, PS:protocol必須為both才能啟用
130  
131 SlugField(CharField)           數字,字母,下劃線,減號(連字符)
132     ...
133  
134 UUIDField(CharField)           uuid類型
Form中所有的內置字段:

Form中的校驗:

方式一:

技術分享圖片 技術分享圖片
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開頭‘)],
    )
技術分享圖片 技術分享圖片

方式二:

技術分享圖片 技術分享圖片
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‘郵箱‘}))
技術分享圖片 技術分享圖片

Django 框架篇(九): Django中的Form 組件