Django教程(三)- Django表單Form

目錄:

1.Form 基本使用

django中的Form組件有以下幾個(gè)功能:

  1. 生成HTML標(biāo)簽
  1. 驗(yàn)證用戶數(shù)據(jù)(顯示錯(cuò)誤信息)
  2. HTML Form提交保留上次提交數(shù)據(jù)
  3. 初始化頁面顯示內(nèi)容

2.Form中字段及插件

創(chuàng)建Form類時(shí)灸蟆,主要涉及到 【字段】 和 【插件】杉编,字段用于對用戶請求數(shù)據(jù)的驗(yàn)證镀琉,插件用于自動(dòng)生成HTML;

1.Django內(nèi)置字段如下:

  • Field:
required=True,               是否允許為空
widget=None,                 HTML插件
label=None,                  用于生成Label標(biāo)簽或顯示內(nèi)容
initial=None,                初始值
help_text='',                幫助信息(在標(biāo)簽旁邊顯示)
error_messages=None,         錯(cuò)誤信息 {'required': '不能為空', 'invalid': '格式錯(cuò)誤'}
show_hidden_initial=False,   是否在當(dāng)前插件后面再加一個(gè)隱藏的且具有默認(rèn)值的插件(可用于檢驗(yàn)兩次輸入是否一直)
validators=[],               自定義驗(yàn)證規(guī)則
localize=False,              是否支持本地化(根據(jù)不同語言地區(qū)訪問用戶顯示不同語言)
disabled=False,              是否可以編輯
label_suffix=None            Label內(nèi)容后綴
  • CharField(Field)
max_length=None,             最大長度
min_length=None,             最小長度
strip=True                   是否移除用戶輸入空白
  • IntegerField(Field), FloatField(IntegerField)
max_value=None,              最大值
min_value=None,              最小值
  • DecimalField(IntegerField) 小數(shù)蛋哭,舉例胁出,涉及金錢計(jì)算保留小數(shù)點(diǎn)后兩位
max_value=None,              最大值
min_value=None,              最小值
max_digits=None,             總長度
decimal_places=None,         小數(shù)位長度

  • BaseTemporalField(Field)
input_formats=None          時(shí)間格式化
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field)            時(shí)間間隔:%d %H:%M:%S.%f
  • RegexField(CharField)
regex,                      自定制正則表達(dá)式
max_length=None,            最大長度
min_length=None,            最小長度
error_message=None,         忽略焙压,錯(cuò)誤信息使用 error_messages={'invalid': '...'}

EmailField(CharField) ...

  • FileField(Field)
allow_empty_file=False     是否允許空文件
  • ImageField(FileField)
...
注:需要PIL模塊,pip install Pillow
以上兩個(gè)字典使用時(shí)庵芭,需要注意兩點(diǎn):
- form表單中 enctype="multipart/form-data"
- view函數(shù)中 obj = MyForm(request.POST, request.FILES)

URLField(Field)...
BooleanField(Field)...
NullBooleanField(BooleanField)...

  • ChoiceField(Field)
choices=(),                選項(xiàng)妹懒,如:choices = ((0,'上海'),(1,'北京'),)
required=True,             是否必填
widget=None,               插件,默認(rèn)select插件
label=None,                Label內(nèi)容
initial=None,              初始值
help_text='',              幫助提示
  • TypedChoiceField(ChoiceField)
coerce = lambda val: val   對選中的值進(jìn)行一次轉(zhuǎn)換双吆,通過lambda函數(shù)實(shí)現(xiàn)
empty_value= ''            空值的默認(rèn)值
  • MultipleChoiceField(ChoiceField)多選框...

  • TypedMultipleChoiceField(MultipleChoiceField)

coerce = lambda val: val   對選中的每一個(gè)值進(jìn)行一次轉(zhuǎn)換
empty_value= ''            空值的默認(rèn)值
  • ComboField(Field)
fields=()                  使用多個(gè)驗(yàn)證眨唬,如下:即驗(yàn)證最大長度20,又驗(yàn)證郵箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
  • MultiValueField(Field): 抽象類好乐,子類中可以實(shí)現(xiàn)聚合多個(gè)字典去匹配一個(gè)值匾竿,要配合MultiWidget使用,提供接口蔚万,需要自己實(shí)現(xiàn)

  • 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) 文件選項(xiàng)岭妖,目錄下文件顯示在頁面中
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時(shí)候反璃,可解析為192.0.2.1昵慌, PS:protocol必須為both才能啟用
  • SlugField(CharField) :數(shù)字,字母淮蜈,下劃線废离,減號(連字符)

  • UUIDField(CharField) :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')
  • Django內(nèi)置插件:
TextInput(Input)  #input type="text"
NumberInput(TextInput)  # 數(shù)字輸入框
EmailInput(TextInput)  # 郵箱輸入框
URLInput(TextInput)  # url輸入框
PasswordInput(TextInput)  # 密碼輸入框
HiddenInput(TextInput)  # 隱藏輸入框
Textarea(Widget)  # textarea文本區(qū)
DateInput(DateTimeBaseInput)  # 日期輸入框
DateTimeInput(DateTimeBaseInput)  # 日期時(shí)間輸入框
TimeInput(DateTimeBaseInput)  # 時(shí)間輸入框
CheckboxInput  # 多選框
Select  # 下拉框
NullBooleanSelect  # 非空布爾值下拉框
SelectMultiple  # 多選下拉框
RadioSelect  # 單選框
CheckboxSelectMultiple  # 多選checkbox ?礁芦??
FileInput  # 文件上傳
ClearableFileInput
MultipleHiddenInput  # 多隱藏輸入框
SplitDateTimeWidget  # 時(shí)間分割框(兩個(gè)input框)
SplitHiddenDateTimeWidget
SelectDateWidget
  • 常用的選擇插件
# 單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
# )

Django模版加減乘除:

Django模版加法:
{{ value|add:10}}
value=5,則返回15 Django模版減法:
{{value|add:-10}}
value=5析桥,則返回-5司草,這個(gè)比較好理解艰垂,減法就是加一個(gè)負(fù)數(shù) Django模版乘法:
{%  widthratio 5 1 100 %}
上面的代碼表示:5/1 *100,返回500埋虹,widthratio需要三個(gè)參數(shù)猜憎,它會(huì)使用 參數(shù)1/參數(shù)2*參數(shù)3,所以要進(jìn)行乘法的話搔课,就將參數(shù)2=1即可 Django模版除法
view sourceprint?
{%  widthratio 5 100 1 %}
上面的代碼表示:5/100*1胰柑,返回0.05,只需要將第三個(gè)參數(shù)設(shè)置為1即可 

3.通過Django表單Form來完成需求

1.根據(jù)用戶填寫表單的不同跳往不同的頁面

1.先創(chuàng)建app項(xiàng)目名:djangoform


樹形圖

2.app下創(chuàng)建文件夾djangoform,并建立表單form1.py

# -*- coding:utf8 -*-
from django.forms import Form
from django.forms import widgets  # 插件
from django.forms import fields # 字段

class webpage(Form):
    page = fields.CharField()

3.app下創(chuàng)建templates文件夾爬泥,并創(chuàng)建不同的html網(wǎng)頁

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
</head>
<body>

    <form action="" method="post">
        {% csrf_token %}

        請選擇要進(jìn)入的頁面:{{ web.page }}
        <input type="submit" value="提交">

    </form>

</body>
</html>
  • page1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>page1</title>
</head>
<body>


        Page1:一顰一笑一傷悲,一生癡迷一世醉.


</body>
</html>
  • page2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>page2</title>
</head>
<body>

        Page2:一嗟一嘆一輪回,一寸相思一寸灰.


</body>
</html>

其他幾個(gè)網(wǎng)頁類似
4.建立視圖views.py

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render,redirect
from django.http import HttpResponse
from djangoform import form1

# Create your views here.


def indexPage(request):
    if request.method == "GET":
        webPage=form1.webpage()
        return render(request,'index.html',{'web':webPage})

    elif request.method == "POST":
        webPage = form1.webpage(request.POST,request.FILES)
        if webPage.is_valid():
            values = webPage.clean()
            print(values)
            if values['page'] == '1':
                return render(request, 'page1.html', {'web': webPage})
            elif values['page']== '2':
                return render(request, 'page2.html', {'web': webPage})
            elif values['page']== '3':
                return render(request, 'page3.html', {'web': webPage})
        else:
            errors = webPage.errors
            print(errors)
        return render(request, 'index.html', {'web': webPage})
    else:
        return redirect('http://www.baidu.com')




def index(request):
    if request.method == "GET":
        obj = forms.MyForm()  # 沒有值柬讨,在頁面上渲染form中的標(biāo)簽
        return render(request, 'index.html', {'form': obj})

    elif request.method == "POST":
        obj = forms.MyForm(request.POST, request.FILES)  # 將post提交過來的數(shù)據(jù)作為參數(shù)傳遞給自定義的Form類
        if obj.is_valid():  # obj.is_valid()返回一個(gè)bool值,如果檢查通過返回True袍啡,否則返回False
            values = obj.clean()  # 拿到處理后的所有數(shù)據(jù)踩官,鍵值對的形式
            print(values)
        else:
            errors = obj.errors  # 拿到未通過的錯(cuò)誤信息,里面封裝的都是對象
            print(errors)
        return render(request, 'index.html', {'form': obj})
    else:
        return redirect('http://www.baidu.com')

5.定義視圖函數(shù)相關(guān)的·urls.py·

from django.conf.urls import include, url
from django.contrib import admin
from . import views

urlpatterns = [
    url(r'^page/',views.indexPage,),
]

6.把我們新定義的app加到settings.py中的INSTALL_APPS中和urls中境输,詳情見Django教程(一)- Django視圖與網(wǎng)址

效果展示:

首頁index

輸入數(shù)字1跳轉(zhuǎn)的頁面
輸入數(shù)字2跳轉(zhuǎn)的頁面

2.在網(wǎng)頁上打印9*9乘法表

  • home.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>九九乘法表</title>
</head>
<body>
    {% for i in list %}
        {% for j in list %}
            {% if j <= i %}
                {{i}}*{{j}}={% widthratio j 1 i %}
            {% endif %}
        {% endfor %}<br>
    {% endfor %}



</body>
</html>
  • views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render

# Create your views here.

def home(request):
    list= [1,2,3,4,5,6,7,8,9,]
    return render(request,'home.html',{'list':list})
  • urls.py
from django.conf.urls import url
from . import views

urlpatterns=[
    url(r'^home/$',views.home,name='home',)
]

效果展示:

九九乘法表

3.在網(wǎng)頁上打印1-100之間的偶數(shù)

先了解下python中map函數(shù)

>>> map(str, range(5))           #對range(5)各項(xiàng)進(jìn)行str操作
['0', '1', '2', '3', '4']        #返回列表
>>> def add(n):return n+n
... 
>>> map(add, range(5))           #對range(5)各項(xiàng)進(jìn)行add操作
[0, 2, 4, 6, 8]
>>> map(lambda x:x+x,range(5))   #lambda 函數(shù)蔗牡,各項(xiàng)+本身
[0, 2, 4, 6, 8]
>>> map(lambda x:x+1,range(10))  #lambda 函數(shù),各項(xiàng)+1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> map(add,'zhoujy')            
['zz', 'hh', 'oo', 'uu', 'jj', 'yy']

#想要輸入多個(gè)序列畴嘶,需要支持多個(gè)參數(shù)的函數(shù)蛋逾,注意的是各序列的長度必須一樣,否則報(bào)錯(cuò):
>>> def add(x,y):return x+y
... 
>>> map(add,'zhoujy','Python')
['zP', 'hy', 'ot', 'uh', 'jo', 'yn']
>>> def add(x,y,z):return x+y+z
... 
>>> map(add,'zhoujy','Python','test')     #'test'的長度比其他2個(gè)小
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes exactly 2 arguments (3 given)

>>> map(add,'zhoujy','Python','testop')
['zPt', 'hye', 'ots', 'uht', 'joo', 'ynp']
  • views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render

# Create your views here.

def even(request):
    list = map(str,range(100))  #對range(100)各項(xiàng)進(jìn)行str操作
    return render(request,'even.html',{'list':list})
  • urls.py
from django.conf.urls import url
from . import views

urlpatterns=[
    url(r'^even/$',views.even,name='even',)
]

  • even.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>1-100之間的偶數(shù)</title>
</head>
<body>
    {% for item in list %}
    {% if forloop.counter|divisibleby:2 %}{{forloop.counter}} {% if not forloop.last %},{% endif %} {% endif %}
    {% endfor %}



</body>
</html>

效果如下:

在網(wǎng)頁上打印1-100之間的偶數(shù)

4.自定義驗(yàn)證驗(yàn)證規(guī)則

  • 方式1:在字段中自定義validators設(shè)計(jì)正則匹配
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]+$', '請輸入數(shù)字'), RegexValidator(r'^159[0-9]+$', '數(shù)字必須以159開頭')],
    )
  • 方式2:自定義規(guī)則函數(shù)處理數(shù)據(jù)
import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError


# 自定義驗(yàn)證規(guī)則
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('手機(jī)號碼格式錯(cuò)誤')


class PublishForm(Form):


    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': '標(biāo)題不能為空',
                                            'min_length': '標(biāo)題最少為5個(gè)字符',
                                            'max_length': '標(biāo)題最多為20個(gè)字符'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': '標(biāo)題5-20個(gè)字符'}))


    # 使用自定義驗(yàn)證規(guī)則
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={'required': '手機(jī)不能為空'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手機(jī)號碼'}))

    email = fields.EmailField(required=False,
                            error_messages={'required': u'郵箱不能為空','invalid': u'郵箱格式錯(cuò)誤'},
                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'}))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末窗悯,一起剝皮案震驚了整個(gè)濱河市区匣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蒋院,老刑警劉巖亏钩,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異欺旧,居然都是意外死亡姑丑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門辞友,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栅哀,“玉大人,你說我怎么就攤上這事称龙×羰埃” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵鲫尊,是天一觀的道長痴柔。 經(jīng)常有香客問我,道長疫向,這世上最難降的妖魔是什么咳蔚? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任豪嚎,我火速辦了婚禮,結(jié)果婚禮上谈火,老公的妹妹穿的比我還像新娘侈询。我一直安慰自己,他們只是感情好堆巧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布妄荔。 她就那樣靜靜地躺著,像睡著了一般谍肤。 火紅的嫁衣襯著肌膚如雪啦租。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天荒揣,我揣著相機(jī)與錄音篷角,去河邊找鬼。 笑死系任,一個(gè)胖子當(dāng)著我的面吹牛恳蹲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俩滥,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼嘉蕾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了霜旧?” 一聲冷哼從身側(cè)響起错忱,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挂据,沒想到半個(gè)月后以清,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡崎逃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年掷倔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片个绍。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡勒葱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巴柿,到底是詐尸還是另有隱情错森,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布篮洁,位于F島的核電站,受9級特大地震影響殃姓,放射性物質(zhì)發(fā)生泄漏袁波。R本人自食惡果不足惜瓦阐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望篷牌。 院中可真熱鬧睡蟋,春花似錦、人聲如沸枷颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夭苗。三九已至信卡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間题造,已是汗流浹背傍菇。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留界赔,地道東北人丢习。 一個(gè)月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像淮悼,于是被迫代替她去往敵國和親咐低。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容