欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Python的Flask框架中web表單的教程

系統(tǒng) 1806 0

?概要

在前面章節(jié)我們?yōu)橹黜?yè)定義了一個(gè)簡(jiǎn)單的模板,部分尚未實(shí)現(xiàn)的模塊如用戶或帖子等使用模擬的對(duì)象作為臨時(shí)占位。

本章我們將看到如何利用web表單填補(bǔ)這些空白。

web表單是web應(yīng)用中最基本的構(gòu)建要素,我們將通過表單來實(shí)現(xiàn)用戶發(fā)帖和應(yīng)用登錄功能。

完成本章內(nèi)容你需要基于前面章節(jié)完成的微博應(yīng)用代碼,請(qǐng)確認(rèn)這些代碼已安裝并能正常運(yùn)行。

配置

Flask-WTF是WTForms項(xiàng)目的Flask框架擴(kuò)展,我們將用他來幫助我們處理web表單。

大部分Flask擴(kuò)展都需要定義相關(guān)配置項(xiàng),所以我們先來在應(yīng)用根目錄下創(chuàng)建一個(gè)配置文件以備使用。我們先這樣創(chuàng)建 (fileconfig.py):
?

            
CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'

          

很簡(jiǎn)單吧,這是Flask-WTF需要用到的2個(gè)配置項(xiàng)。CSRF_ENABLED配置啟用了跨站請(qǐng)求攻擊保護(hù),大部分情況下你都需要開啟此功能,這能使你的應(yīng)用更安全。


SECRET_KEY設(shè)置當(dāng)CSRF啟用時(shí)有效,這將生成一個(gè)加密的token供表單驗(yàn)證使用,你要確保這個(gè)KEY足夠復(fù)雜不會(huì)被簡(jiǎn)單推測(cè)。

現(xiàn)在這個(gè)配置文件已經(jīng)基本可用了。項(xiàng)目創(chuàng)建完成我們可以創(chuàng)建如下文件并編輯(fileapp/__init__.py):
?

            
from flask import Flask
 
app = Flask(__name__)
app.config.from_object('config')
 
from app import views

          

用戶登錄表單

使用Flask-WTF創(chuàng)建的表單就像一個(gè)對(duì)象,需要從Form類繼承子類。然后在這個(gè)子類中定義一些類的屬性變量作為表單字段就可以了。

我們要?jiǎng)?chuàng)建一個(gè)登錄表單,用來進(jìn)行用戶身份識(shí)別。但跟平常需要驗(yàn)證用戶名和密碼的登錄方式不同,我們將使用 OpenId 來處理登錄過程。使用OpenId的好處就是我們不用管那些用戶名和密碼的認(rèn)證過程,交給 OpenId 去搞定,它會(huì)返回給我們用戶驗(yàn)證后的數(shù)據(jù)。這樣對(duì)于使用我們網(wǎng)站的用戶而言也更安全。


使用 OpenId 登錄只需要一個(gè)字符串,然后發(fā)送給 OpenId 服務(wù)器就行了。另外我們還需要在表單中加一個(gè)“記住我” 的選項(xiàng)框,這個(gè)是送給那些不想每次來我們網(wǎng)站都要進(jìn)行身份認(rèn)證的人。選擇這個(gè)選項(xiàng)后,首次登錄時(shí)會(huì)用cookie在他們的瀏覽器上記住他們的登錄信息,下次再進(jìn)入網(wǎng)站時(shí)就不需要進(jìn)行登錄操作。

開始我們的第一個(gè)表單吧 (fileapp/forms.py):
?

            
from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required
 
class LoginForm(Form):
  openid = TextField('openid', validators = [Required()])
  remember_me = BooleanField('remember_me', default = False)

          

欣賞一下這個(gè)類,多么的簡(jiǎn)潔,多么的一目了然。如此簡(jiǎn)單,但又十分的富有內(nèi)涵。我們引入了一個(gè) Form 類,然后繼承這個(gè)類,按需求還添加了 TextField 和 BooleanField 這兩個(gè)字段。

另外還引入了一個(gè)表單驗(yàn)證函數(shù) Required,這種驗(yàn)證函數(shù)可以附加在字段里面,在用戶提交表單時(shí)它們會(huì)用來檢查用戶填寫的數(shù)據(jù)。這個(gè) Required 函數(shù)是用來防止用戶提交空數(shù)據(jù)。Flask-WTF 中還有很多不同作用的表單驗(yàn)證函數(shù),我們將會(huì)在后面使用到它們。


表單模板

現(xiàn)在我們的問題就是需要一個(gè)顯示這個(gè)登錄表單的模板。好消息是我們剛剛創(chuàng)建的登錄表單類知道如何把字段轉(zhuǎn)換成HTML,所以我們只需要把注意力集中到頁(yè)面布局上。下面就是我們的登錄表單的模板 (fileapp/templates/login.html):
?

                        
{% extends "base.html" %}
 
{% block content %}

            

Sign In

{{form.hidden_tag()}}

Please enter your OpenID:
{{form.openid(size=80)}}

{{form.remember_me}} Remember Me

{% endblock %}

容我??嗦一下,在這個(gè)模板中,我們又一次使用了模板繼承的方式。使用 extends 語(yǔ)句從 base.html 繼承模板內(nèi)容。我們會(huì)在后面創(chuàng)建的模板中繼續(xù)使用這種方式,這樣可以使我們所有的頁(yè)面布局保持一致。


這個(gè)登錄模板跟普通的HTML表單有些明顯的區(qū)別,它使用模板參數(shù) {{ ... }} 來實(shí)例化表單字段,而表單字段又來源于我們剛剛定義的表單類,模板參數(shù)中使用了 form 這個(gè)名稱。當(dāng)我們使用視圖函數(shù)引用表單類并渲染到模板時(shí),我們要特別注意這個(gè)把表單類傳遞到模板的變量名。

我們?cè)谂渲弥虚_啟了CSRF(跨站偽造請(qǐng)求)功能,模板參數(shù) {{ form.hidden_tag() }} 會(huì)被替換成一個(gè)具有防止CSRF功能的隱藏表單字段。在開啟了CSRF功能后,所有模板的表單中都需要添加這個(gè)模板參數(shù)。


我們定義的表單對(duì)象中的字段同樣也能被模板渲染,只需要在模板合適的位置添加類似于 {{ form.field_name }} 這樣的模板參數(shù),相關(guān)字段就會(huì)在被定義的位置出現(xiàn)。另外還有一些字段是可以傳參數(shù),比如這個(gè) openid 字段,我們就添加了一個(gè)參數(shù)讓它顯示的寬度增加到80個(gè)字符。

由于我們沒有在表單中定義一個(gè)提交功能的按鈕,所以在這里只能以普通表單字段的方式來做了。不過說起來區(qū)區(qū)一個(gè)按鈕,在表單中跟任何數(shù)據(jù)都沒有關(guān)系,的確也沒有在表單類中定義的必要。

表單視圖

見證奇跡的時(shí)刻最后一步,我們馬上要來寫一個(gè)渲染登錄表單對(duì)象到模板的視圖函數(shù)。

這個(gè)函數(shù)相當(dāng)?shù)暮?jiǎn)單無趣,因?yàn)槲覀冎恍枰驯韱螌?duì)象傳遞給模板就行了。下面就是我們這個(gè)視圖函數(shù)的全部?jī)?nèi)容 (fileapp/views.py):
?

            
from flask import render_template, flash, redirect
from app import app
from forms import LoginForm
 
# index view function suppressed for brevity
 
@app.route('/login', methods = ['GET', 'POST'])
def login():
  form = LoginForm()
  return render_template('login.html',
    title = 'Sign In',
    form = form)

          

我們引入登錄表單類,然后把它實(shí)例化到一個(gè)變量,最后再把這個(gè)變量傳給模板。要渲染表單字段必須的事情也就這些。

上面的代碼中還引入了兩個(gè)新對(duì)象: falsh 和 redirect, 這個(gè)先甭理它們,稍后才用得上。


另外還做了一件事就是在路由裝飾器中添加一個(gè)新方法。讓 Flask 明白我們這個(gè)視圖函數(shù)支持 GET 和 POST 請(qǐng)求。否則這個(gè)視圖函數(shù)只會(huì)響應(yīng) GET 請(qǐng)求。我們需要得到用戶填寫表單后提交的數(shù)據(jù),這些數(shù)據(jù)是從 POST 請(qǐng)求中傳遞過來的。

你可以通過在瀏覽器中測(cè)試這個(gè)程序來了解上面所說的。 按照視圖函數(shù)關(guān)聯(lián)的路由,你應(yīng)該在瀏覽器中輸入 http://localhost:5000/login

由于我們還沒有寫任何接收數(shù)據(jù)的代碼,所以現(xiàn)在你在頁(yè)面中點(diǎn)提交按鈕還沒有任何效果。

從表單中接收數(shù)據(jù)

另外值得一提的是, Flask-WTF 對(duì)表單提交數(shù)據(jù)的處理使我們的接下來要做的事情變得簡(jiǎn)單了。下面就是我們這個(gè)登錄視圖函數(shù)的新版本, 加入了表單數(shù)據(jù)驗(yàn)證和處理 (fileapp/views.py):
?

            
@app.route('/login', methods = ['GET', 'POST'])
def login():
  form = LoginForm()
  if form.validate_on_submit():
    flash('Login requested for OpenID="' + form.openid.data + '", remember_me=' + str(form.remember_me.data))
    return redirect('/index')
  return render_template('login.html',
    title = 'Sign In',
    form = form)

          

validate_on_submit() 這個(gè)方法做了表單處理的所有工作。如果你在表單向用戶提供數(shù)據(jù)時(shí)(舉個(gè)栗子:用戶在它之前修改了一下提交的數(shù)據(jù)) 時(shí)調(diào)用此方法,它會(huì)返回 False。發(fā)生這樣的情況時(shí),你懂的。不懂?就是提交的數(shù)據(jù)驗(yàn)證不通過,你要繼續(xù)渲染模板。

在提交請(qǐng)求時(shí)調(diào)用了表單的 validate_on_submit() 方法后,它會(huì)從請(qǐng)求中獲取所有提交的數(shù)據(jù),然后使用表單字段中綁定的驗(yàn)證函數(shù)進(jìn)行數(shù)據(jù)驗(yàn)證。在所有的數(shù)據(jù)都驗(yàn)證通過時(shí)會(huì)返回 True. 這就意味著你可以放心的使用這些表單數(shù)據(jù)了。

只要有一個(gè)字段驗(yàn)證不通過,它都會(huì)返回 False. 這時(shí)就需要我們返回?cái)?shù)據(jù)給用戶,讓他們來糾正一下錯(cuò)誤數(shù)據(jù)。接下來我們將會(huì)看到在數(shù)據(jù)驗(yàn)證失敗時(shí),如何把錯(cuò)誤消息顯示給用戶。


當(dāng) validate_on_submit() 方法返回 True 的時(shí)候,我們的視圖函數(shù)又會(huì)調(diào)用兩個(gè)新的函數(shù)。它們都是從Flask 中引入的,flash 函數(shù)用來在下一個(gè)打開的頁(yè)面中顯示定義的消息。我們現(xiàn)在用它用來做調(diào)試。因?yàn)槲覀儸F(xiàn)在還沒有做用戶登錄模塊, 所以只需要把用戶提交上來的數(shù)據(jù)顯示一下就行了。flash 函數(shù)非常有用,比如為用戶的一些操作提供消息反饋。

flash 函數(shù)提供的消息不會(huì)自動(dòng)出現(xiàn)在我們的網(wǎng)站頁(yè)面中,所以我們需要做點(diǎn)事情讓它在頁(yè)面中顯示出來。為了讓我們所有頁(yè)面都能有這項(xiàng)激動(dòng)人心的功能,所以就把它添加到基礎(chǔ)模板中吧, 下面是更新后的基礎(chǔ)模板 (fileapp/templates/base.html):
?

            

 
  {% if title %}
  
            
              {{title}} - microblog
            
            
  {% else %}
  
            
              microblog
            
            
  {% endif %}
 
 
  
            
Microblog: Home

{% with messages = get_flashed_messages() %} {% if messages %}
    {% for message in messages %}
  • {{ message }}
  • {% endfor %}
{% endif %} {% endwith %} {% block content %}{% endblock %}

模板中顯示 flash 消息的功能希望你能明白。


在視圖函數(shù)中我們使用的另一個(gè)新函數(shù)就是 redirect. 這個(gè)函數(shù)會(huì)通知用戶的瀏覽器跳轉(zhuǎn)到指定的地址。在我們的視圖函數(shù)中,我們使用它跳轉(zhuǎn)到了首頁(yè)。注意跳轉(zhuǎn)結(jié)束后頁(yè)面上還會(huì)顯示 flash 函數(shù)傳遞的消息哦。

激動(dòng)人心的時(shí)刻到了,運(yùn)行我們的程序吧,看看表單是如何工作的吧。不要填寫表單中的 openid 字段,看看 Required 這個(gè)驗(yàn)證函數(shù)是如何發(fā)揮威力,把一切發(fā)起空數(shù)據(jù)的請(qǐng)求阻止在千里之外。

改善一下字段驗(yàn)證

我們程序目前狀況不錯(cuò),提交不合要求的數(shù)據(jù)會(huì)被阻止,還會(huì)返回表單讓用戶修改,基本滿足我們要求。

但似乎還少點(diǎn)什么。如果我們?cè)谟脩籼峤粩?shù)據(jù)失敗后給用戶點(diǎn)提示,讓他們知道什么原因引起的,豈不妙哉!太幸運(yùn)了,用 Flask-WTF 可以輕松解決這個(gè)問題。

當(dāng)表單字段驗(yàn)證失敗時(shí), Flask-WTF 會(huì)添加一個(gè)錯(cuò)誤消息到表單對(duì)象。這些消息在模板中也是可以使用的,所以我們只需要在模板中添加一點(diǎn)點(diǎn)東西就OK了。


這個(gè)就是我們添加了驗(yàn)證消息的登錄模板 (fileapp/templates/login.html):
?

                        
{% extends "base.html" %}
 
{% block content %}

            

Sign In

{{form.hidden_tag()}}

Please enter your OpenID:
{{form.openid(size=80)}}
{% for error in form.errors.openid %} [{{error}}] {% endfor %}

{{form.remember_me}} Remember Me

{% endblock %}

我們僅在 openid 字段的右邊添加了一個(gè)循環(huán)語(yǔ)句,它會(huì)把openid字段驗(yàn)證失敗的消息都顯示出來。不論你的表單有多少字段,所有表單字段驗(yàn)證失敗的錯(cuò)誤消息都可以用 form.errors.字段名 這種方式來使用。這個(gè)表單中我們的是 form.errors.openid。為了讓錯(cuò)誤消息引起用戶的注意,我們還給消息添加了顯示紅色的 css 樣式。
?
處理 OpenID 登錄

現(xiàn)實(shí)生活中,我們發(fā)現(xiàn)有很多人都不知道他們擁有一些公共賬號(hào)。一部分大牌的網(wǎng)站或服務(wù)商都會(huì)為他們的會(huì)員提供公共賬號(hào)的認(rèn)證。舉個(gè)栗子,如果你有一個(gè) google 賬號(hào),其實(shí)你就有了一個(gè)公共賬號(hào),類似的還有 Yahoo, AOL, Flickr 等。

為了方便我們的用戶能簡(jiǎn)單的使用他們的公共賬號(hào),我們將把這些公共賬號(hào)的鏈接添加到一個(gè)列表,這樣用戶就不用自手工輸入了。


我們要把一些提供給用戶的公共賬號(hào)服務(wù)商定義到一個(gè)列表里面,這個(gè)列表就放到配置文件中吧 (fileconfig.py):
?

            
CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'
 
OPENID_PROVIDERS = [
  { 'name': 'Google', 'url': 'https://www.google.com/accounts/o8/id' },
  { 'name': 'Yahoo', 'url': 'https://me.yahoo.com' },
  { 'name': 'AOL', 'url': 'http://openid.aol.com/
            
              ' },
  { 'name': 'Flickr', 'url': 'http://www.flickr.com/
              
                ' },
  { 'name': 'MyOpenID', 'url': 'https://www.myopenid.com' }]

              
            
          

接下來就是要在我們的登錄視圖函數(shù)中使用這個(gè)列表了:
?

            
@app.route('/login', methods = ['GET', 'POST'])
def login():
  form = LoginForm()
  if form.validate_on_submit():
    flash('Login requested for OpenID="' + form.openid.data + '", remember_me=' + str(form.remember_me.data))
    return redirect('/index')
  return render_template('login.html',
    title = 'Sign In',
    form = form,
    providers = app.config['OPENID_PROVIDERS'])

          

我們從 app.config 中引入了公共賬號(hào)服務(wù)商的配置列表,然后把它作為一個(gè)參數(shù)通過 render_template 函數(shù)引入到模板。


接下來要做的我想你也猜得到,我們需要在登錄模板中把這些服務(wù)商鏈接顯示出來。
?

                        
{% extends "base.html" %}
 
{% block content %}

            
            

Sign In

{{form.hidden_tag()}}

Please enter your OpenID, or select one of the providers below:
{{form.openid(size=80)}} {% for error in form.errors.openid %} [{{error}}] {% endfor %}
|{% for pr in providers %} {{pr.name}} | {% endfor %}

{{form.remember_me}} Remember Me

{% endblock %}

這次的模板添加的東西似乎有點(diǎn)多。一些公共賬號(hào)需要提供用戶名,為了解決這個(gè)我們用了點(diǎn) javascript。當(dāng)用戶點(diǎn)擊相關(guān)的公共賬號(hào)鏈接時(shí),需要用戶名的公共賬號(hào)會(huì)提示用戶輸入用戶名, javascript 會(huì)把用戶名處理成可用的公共賬號(hào),最后再插入到 openid 字段的文本框中。
?

下面這個(gè)是在登錄頁(yè)面點(diǎn)擊 google 鏈接后顯示的截圖:?

Python的Flask框架中web表單的教程_第1張圖片

?結(jié)束語(yǔ)

我們目前在用戶登錄表單中取得了一些進(jìn)展,但用戶登入這個(gè)網(wǎng)站還是啥事兒都不能干。目前我們還一直在登錄的界面上小打小鬧,是因?yàn)槲覀冞€沒有記錄一切的數(shù)據(jù)庫(kù)。

所以從下節(jié)開始,我們將會(huì)整一個(gè)數(shù)據(jù)庫(kù)起來,然后真正完成我們的登錄系統(tǒng)。不要走開,請(qǐng)繼續(xù)關(guān)注。


微博(microblog) 當(dāng)前版本源碼從下面地址下載:

下載地址:microblog-0.3.zip


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 久久国产精品99久久小说 | 色综合日韩 | 日韩中文一区二区三区 | 亚洲播播播 | 人人干人人模 | 日日干夜夜干 | 欧美性色生活片免费播放 | 国产综合在线视频 | 你下面好大好硬好想要 | 久操网址| 欧美精品一区二区三区在线 | 俄罗斯18videosex性 | 91社区影院 | 日日夜操 | 国产夜色福利院在线观看免费 | 人妖一区| 欧美成人综合在线 | 理论片91| 国产精品国产三级国产aⅴ入口 | 99久久99久久精品免费看蜜桃 | 91精品欧美成人 | 天堂久久久久久中文字幕 | 日韩精品成人 | 欧美一区二区三区在观看 | 日韩精品一区二区三区中文字幕 | 亚洲97 | 精品视频一区二区观看 | 黄片一级毛片 | 在线视频亚洲 | 99精品免费视频 | 91久久综合九色综合欧美亚洲 | 欧美激情久久久 | 2021最新国产成人精品视频 | 国产综合精品 | 最新亚洲视频 | 免费在线一区二区 | 久久成人18免费 | 福利视频区 | 国产一区二区久久 | 日韩视频在线一区 | 亚洲成人精品 |