構(gòu)建一個Web應(yīng)用:利用search4letters這個函數(shù)奢入,讓人們都可以在web上訪問這個函數(shù)
區(qū)分好web請求與web響應(yīng):
1、用戶在瀏覽器輸入一個web地址后單擊超鏈接航夺,
2蕉朵、瀏覽器會將用戶的動作轉(zhuǎn)換為一個web請求,通過互聯(lián)網(wǎng)發(fā)送到一個web服務(wù)器阳掐。
3始衅、web服務(wù)器接收到web請求后會做兩件事:
如果請求知識請求一個靜態(tài)內(nèi)容(HTML文件或圖像等),web服務(wù)器就會找到這個資源并將它作為一個web響應(yīng)返回去給web瀏覽器缭保;
如果請求的是動態(tài)內(nèi)容(搜索結(jié)果或購物車等)汛闸,web服務(wù)器就會運行一些代碼來生成web響應(yīng)再返回去給web瀏覽器。
4艺骂、web服務(wù)器通過互聯(lián)網(wǎng)江響應(yīng)發(fā)回給正在等待的web瀏覽器
5诸老、瀏覽器接收到web響應(yīng)并顯示在用戶屏幕上
分析search4letters:
def search4letters(phrase:str,letters:str='aeiou') -> set:
這個函數(shù)需要至少1個但不能超過2個參數(shù),phrase和letters(要在phrase中搜索letters)钳恕。且letter參數(shù)是可選的(默認為aeiou)
Web應(yīng)用框架flask
安裝Flask:
windows:
打開命令行提示窗口别伏,作為管理員運行(右鍵點擊鼠標選擇作為管理員運行),執(zhí)行命令
c:\>py -3 -m pip install flask
回車后跑完會出現(xiàn)
Successfully installed Jinja-版本號 Markupsafe-版本號 Werkzeug-版本號 flask-版本號
Flsak 依賴的4個模塊 Jinja-版本號 Markupsafe-版本號 Werkzeug-版本號 flask-版本號
輕量級規(guī)模小易使用是Flask模塊的特性
啟動服務(wù)器:
需要復(fù)習(xí)掌握常用命令行
第一種方法
使用win+R可以調(diào)出cmd苞尝,或者在目標文件的文件夾里面按住shift同時單擊鼠標右鍵選擇Open command window here
>d:(變動位置)
>cd (通過文件屬性來查看文件的所屬位置)(win10以上可以直接復(fù)制粘貼ctrl+c/v畸肆,win10以下只能右鍵復(fù)制粘貼)
>cd 文件位置 >python(空格) 文件名.py(如untitled.py) 啟動python文件,如果沒有配置python文件啟動運行環(huán)境,就需要去以管理員身份更改PATH配置環(huán)境將python文件移動到pyrhon.exe所處的指定的根目錄之下
第二種方法
使用Anoconda Prompt
>cd 位置粘貼(與第一種方法一樣)
檢查是否已經(jīng)安裝好flask框架
>flask
回車后代碼跑起來結(jié)束就是已經(jīng)安裝好宙址,如果沒有的話就需要使用
pip install flask
從現(xiàn)在開始都會由Flask接管轴脐,只要內(nèi)置Web服務(wù)器完成任何操作,都會在屏幕上顯示狀態(tài)校系抡砂。啟動之后大咱,F(xiàn)lask Web服務(wù)器會立即確認它已經(jīng)啟動,開始運行并在Flask測試Web地址(127.0.0.1)和協(xié)議端口(5000)上等待為Web請求提供服務(wù)注益。
啟動服務(wù)器
>cd (進入目錄路徑) >python(空格)hello-flask.py(啟動文件兩種方法:第一種是將文件位置復(fù)制粘貼碴巾,第二種是將文件直接拖進命令行里面)
接著就會出現(xiàn)
*Running on http://127.0.0.1:5000/(Press CTRL+C to quit)(IP地址)
但是會報錯
5000是端口號,網(wǎng)頁默認是80不需要寫出來
flask若在單機上是找不到服務(wù)器的
如果IP輸入5000/dothiswork.html 丑搔,服務(wù)器就會多出一行404報錯厦瓢,因為沒有5000的話用戶就會找不到服務(wù)器
我們把IP地址輸入打開也是可以跳轉(zhuǎn)到網(wǎng)頁的,因為已經(jīng)Running起來了
將IP地址(URL)在瀏覽器上面輸入并回車就會跳轉(zhuǎn)到相應(yīng)的web請求后返回的web響應(yīng)頁面啤月,服務(wù)器就已經(jīng)啟動成功了煮仇。這就是Web瀏覽器和Web服務(wù)器交互。接著終端窗口會出現(xiàn)新的狀態(tài)消息
200-
接下來我們編寫一下代碼文件
將代碼輸進去來獲得第一個hello_flask.py文件
from flask import Flask
app = Flask (__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
app.run()
不能在IDLE中運行這個Flask代碼谎仲,IDLE不能很好完成這種大的代碼段浙垫,最好在系統(tǒng)的命令行上直接通過解釋器運行代碼。服務(wù)器啟動流程看上面。
分析代碼行
第一行:導(dǎo)入flask模塊的Flask類
from flask import Flask
也可以寫成
import flask
flask.Flask
第二行:創(chuàng)建一個Flask類型的對象夹姥,把它賦給app變量杉武。
app = Flask (__name__)
Flask使用一個奇怪的參數(shù) __ name __(雙下劃線),設(shè)置為當(dāng)前活動模塊的名字辙售。創(chuàng)建一個新的Flask對象時轻抱,F(xiàn)lask類需要知道 __ name __的當(dāng)前值,必須作為一個參數(shù)傳遞這個值旦部。在這里需要注意”dunder name“的使用”雙下劃線十拣,name,雙下劃線“
定制對象是app也就是實例志鹃,flask是變量類型代表網(wǎng)頁
這里沒有調(diào)用hello函數(shù),并不是往服務(wù)器上放代碼泽西,而是@修飾符幫我們做了這一步驟
第三行:修飾符(decorator)可以調(diào)整一個現(xiàn)有函數(shù)的行為曹铃,而無需修改這個函數(shù)的代碼(函數(shù)得到修飾,允許你根據(jù)需要為已有的一些代碼增加額外的行為)
@app.route('/')
修飾符route前面有@符號前綴捧杉,可以調(diào)整一個已有函數(shù)的行為
后面(‘/’)是URL:127.0.0.1:5000
本行是通過app變量使用Flask的route修飾符陕见。route修飾符允許你江一個URL Web 路徑與一個已有的python函數(shù)關(guān)聯(lián)。URL"/"與下一行代碼中定義的函數(shù)關(guān)聯(lián)味抖,函數(shù)命名為hello评甜,當(dāng)一個只想“/”URL的請求到達服務(wù)器時route修飾符會安排Flask web服務(wù)器調(diào)用這個函數(shù)。route修飾符會等待所修飾的函數(shù)生成的輸出仔涩,再將輸出返回給服務(wù)器忍坷,服務(wù)器再將輸出返回給正在等待的Web瀏覽器。
記兹壑:Flask能為你完成所有這些工作佩研,我們需要做的就是寫一個函數(shù)生成我們想要的輸出。Flask和route修飾符會負責(zé)所有具體細節(jié)霞揉。
注:@修飾符為上下文做了做了關(guān)聯(lián)旬薯,當(dāng)執(zhí)行5000時,前面有了@自動幫你執(zhí)行后面的函數(shù)适秩,返回了Hello world(自動默認執(zhí)行)
第四行:定義route修飾符修飾的函數(shù)绊序,返回字符串 ->str
調(diào)用hello函數(shù)時返回消息“Hello world from Flask!”
def hello() -> str:
return 'Hello world from Flask!'
第五行:通過調(diào)用run來實現(xiàn)得到賦給app變量的Flask對象后,讓Flask開始運行它的web服務(wù)器
app.run()
可以看到服務(wù)器返回了url秽荞,run后面的()骤公。在服務(wù)器上跑起來,跑的是代碼蚂会。請求的是一個str淋样,返回值也是一個str。
這時胁住,F(xiàn)lask會啟動內(nèi)置Web服務(wù)器趁猴,并在服務(wù)器中運行Web應(yīng)用代碼刊咳。Web服務(wù)器接收到指向“/”URL的任何請求時,會響應(yīng)“Hello worldfrom Flask!”消息儡司,而指向其他URL請求會得到404“Resourse not found”錯誤消息娱挨。
輸入http://127.0.0.1:5000/doesthiswork.html,是沒有頁面并且服務(wù)器會同步報錯404
瀏覽器顯示“Not Found”,終端窗口運行的Web應(yīng)用也會用一個適當(dāng)?shù)南⒏聽顟B(tài)
在這里Flask為你做了什么:
他提供了一種機制捕犬,利用這種機制我們可以執(zhí)行任何已有的python函數(shù)跷坝,并在一個Web瀏覽器中顯示他的輸出
為了向Web應(yīng)用中增加更多功能,所要做的只是要確定希望將函數(shù)與哪個URL關(guān)聯(lián)碉碉,然后在完成具體工作的函數(shù)上面編寫一個適當(dāng)?shù)腀app.route修飾符行
我們將使用上一章節(jié)的search4letters函數(shù)
我們現(xiàn)在來修改hello_flask.py來包含第二個URL: /search4柴钻。將這個URL與一個名為do_search的函數(shù)關(guān)聯(lián),它會從vsearch模塊調(diào)用search4letters函數(shù)垢粮,讓do_search函數(shù)返回搜索時確定的結(jié)果:在短語”life,the universe,and everything“中搜索字符串‘eiru,!’
注意:search4letters返回的結(jié)果是一個pytho集合纵装,向等待的Web瀏覽器返回任何結(jié)果之前职车,一定要通過調(diào)用str內(nèi)置函數(shù)(BIF)將結(jié)果強制轉(zhuǎn)換為一個字符串尖奔。因為瀏覽器希望得到文本數(shù)據(jù)而不是一個python集合
修改后的
hello_flask2.py
from flask import Flask
from vsearch import search4letters
app = Flask (__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life,the universe,and everything','eiru,'))
app.run()
增加一到第二行:
from vsearch import search4letters
在調(diào)用之前征绎,需要從"vsearch"模塊導(dǎo)入"search4letters"函數(shù)
增加二:
@app.route('/search4')
第二個修飾符建立"/search4"URL
增加三:
def do_search() -> str:
return str(search4letters('life,the universe,and everything','eiru,'))
”do_search“函數(shù)調(diào)用"search4letters",然后將結(jié)果作為字符串返回
想要測試新功能需要重啟 Flask Web 應(yīng)用昔善,因為現(xiàn)在運行的是老版本的代碼
返回到終端窗口元潘,同時按下”Ctrl + c“,Web應(yīng)用會停止君仆,回到操作系統(tǒng)提示符翩概,按向上箭頭找到前一個命令(之前啟動hello_flask.py的命令),回車
再次顯示初始的Flask狀態(tài)消息袖订,確認更新后的Web應(yīng)用在等待請求
輸入http://127.0.0.1:5000正常
輸入http://127.0.0.1:5000/search4正常
這是因為沒有修改與默認‘/’URL關(guān)聯(lián)的代碼氮帐,所以這個功能仍能正常工作,會顯示"Hello world from Flask!"消息——http://127.0.0.1:5000
如果在瀏覽器的地址欄輸入”http://127.0.0.1:5000/search4“洛姑,就會看到調(diào)用了search4letters的結(jié)果
調(diào)用"search4letters"的結(jié)果上沐,但是確實證明了使用"/search4"URL會調(diào)用函數(shù)并返回結(jié)果
set對象沒有被調(diào)用,return返回字符串楞艾,強制為字符串参咙,是一種集合類型的字符串
函數(shù)只會執(zhí)行相近數(shù),所以服務(wù)器會有多個頁面硫眯,通過“/”反斜杠(默認IP地址)為它指定一個名字蕴侧,我們在服務(wù)器上面搭建了兩個東西分別是“/”,“/search4”
顯示"search4"是"get"
200是正常
500服務(wù)器過載
404網(wǎng)頁找不到
函數(shù)的修飾符只能夠找到函數(shù)
團隊的項目是將其他同學(xué)的作為一個模塊導(dǎo)進來:
將py文件打包導(dǎo)出為模塊两入,用主的py文件來做操作净宵,基本上一個函數(shù)一個頁面,注冊信息是主界面,其他是分界面择葡,每個同學(xué)都有頁面前端和后端紧武,項目都部署在碼云里面并且要活躍該項目。但是必須要弄清楚主程序的入口和項目邏輯在哪里敏储?
url解釋:
用來訪問Web 應(yīng)用中的URL中的127.0.0.1和:5000是什么意思
為什么請求的是返回值而不是網(wǎng)頁呢阻星?Web應(yīng)用需要一個Web頁面接收輸入,還需要一個Web頁面顯示結(jié)果(將輸入提供給search4letters函數(shù)得到的結(jié)果)
關(guān)鍵是這兩段的代碼分別響應(yīng)了兩個網(wǎng)頁
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life,the universe,and everything','eiru,'))
這就要用到兩個基模板了已添,在用基模板之前需要先修改hello函數(shù)來返回HTML表單妥箕,再修改do_search函數(shù)接收這個表單的輸入,再調(diào)用search4letters函數(shù)更舞,最后由do_search將結(jié)果作為另一個Web頁面返回
利用模板引擎畦幢,可以應(yīng)用面向?qū)ο蟮睦^承和重用概念來生成文本數(shù)據(jù),Web頁面也是其中之一缆蝉。
兩個基模板(網(wǎng)站的外觀可以在一個頂層HTML模板中定義呛讲,這稱為基模板,其它HTML頁面繼承這個模板返奉。如果對基模板做了某個修改,這個修改就會在繼承該模板的所有HTML頁面中體現(xiàn))
Flask提供的模板引擎為Jinja2吗氏。
基模板 base.html
注意標注出來的{{和}}之間芽偏,{%和%}包圍是針對Jinja2模板引擎的
<!doctype html>
<html>
<head>
<title>{{ the_title }}</title>
<link rel="stylesheet" href="static/hf.css" />
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
特別注意
<!doctype html> #標準HTML5標記
{{ the_title }} #這是一個Jinja2指令,指示將在呈現(xiàn)之前提供的一個值(可以把它想象成是模板的一個參數(shù))
<link rel="stylesheet" href="static/hf.css" /> #樣式表定義了所有Web頁面的外觀
{% block body %} #Jinja2指令指示要在呈現(xiàn)之前替換這里的HTML塊弦讽,這要由繼承這個模板的頁面來提供
{% endblock %} #Jinja2指令指示要在呈現(xiàn)之前替換這里的HTML塊污尉,這要由繼承這個模板的頁面來提供
有了基模板后,可以使用Jinja2的extends指令繼承這個模板往产。這樣繼承模板的HTML文件只需要提供基模板中命名塊的HTML被碗。在這里我們只有一個命名塊:body
第一個頁面標記:entry.html
實現(xiàn)用戶與這個HTML表單交互來提供Web應(yīng)用需要的phrase和letters的值
這個文件中沒有重復(fù)基模板中的樣板HTML,因為extends指令已經(jīng)為我們包含了這些標記仿村。我們需要提供這個文件特定的HTML锐朴,所以要在名為body的Jinja2塊中提供標記
{% extends 'base.html' %} #這個模板繼承了基模板,為名為"body"的塊提供了一個替代塊
{% block body %}
<h2>{{ the_title }}</h2>
<form method='POST' action='/search4'>
<table>
<p>Use this form to submit a search request:</p>
<tr><td>Phrase:</td><td><input name='phrase' type='TEXT' width='60'></td>
</tr>
<tr><td>Letters:</td><td><input name='letters' type='TEXT' value='aeiou'></td>
</tr>
</table>
<p>When you're ready, click this button:</p>
<p><input value='Do it!' type='SUBMIT'></p>
</form>
{% endblock %}
特別注意:
{% extends 'base.html' %}
{% block body %}
{{ the_title }}
{% endblock %}
第一個頁面標記:results.html
實現(xiàn)呈現(xiàn)搜索的結(jié)果
{% extends 'base.html' %} #與entry.html類似蔼囊,這個模板也繼承了基模板焚志,另外為名為"body"的塊提供了一個替代塊
{% block body %}
<h2>{{ the_title }}</h2>
<p>You submitted the following data:</p>
<table>
<tr><td>Phrase:</td><td>{{ the_phrase }}</td></tr>
<tr><td>Letters:</td><td>{{ the_letters }}</td></tr>
</table>
#注意the_phrase,the_letters,the_results 這些額外的參數(shù)值,在呈現(xiàn)之前是需要賦值給他們的畏鼓。
<p>When "{{the_phrase }}" is searched for "{{ the_letters }}", the following
results are returned:</p>
<h3>{{ the_results }}</h3>
{% endblock %}
特別注意:
{% extends 'base.html' %}
{% block body %}
{{ the_title }}
{{ the_phrase }}
{{ the_letters }}
{{the_phrase }}
{{ the_letters }}"
{{ the_results }}
{% endblock %}
Web應(yīng)用需要呈現(xiàn)兩個Web頁面酱酬,現(xiàn)在已經(jīng)有了兩個模板。這兩個模板都繼承自基模板云矫,因此繼承了基模板的外觀膳沽,現(xiàn)在就是要呈現(xiàn)這些頁面。兩個頁面的標題將在呈現(xiàn)時提供標題值來取代{{ the_title }}指令√羯纾可以把雙大括號中的各個名字想成是模板的一個參數(shù) P216
新增一個Flask的函數(shù) render_template 的函數(shù):如果指定一個模板名和所需的參數(shù)陨界,調(diào)用這個函數(shù)時會返回一個HTML串,為此需要將這個函數(shù)名增加到從flask模塊導(dǎo)入的函數(shù)列表中滔灶,再根據(jù)需要進行調(diào)用
將hello_flask.py文件的名字改為vsearch4web.py
#這是hello_flask.py里的代碼
from flask import Flask
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life, the universe, and everything', 'eiru,!'))
app.run()
為了呈現(xiàn)entry.html模板中的HTML表單普碎,修改vsearch4web.py
#這是vsearch4web.py里的代碼
from flask import Flask, render_template
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4')
def do_search() -> str:
return str(search4letters('life, the universe, and everything', 'eiru,!'))
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run()
特別注意:
修改1:導(dǎo)入render_template函數(shù)
將“render_template”增加到從“flask”模塊導(dǎo)入的函數(shù)列表
from flask import Flask, render_template
修改2:創(chuàng)建一個新的URL,這里就是/entry
每次你的Flask web應(yīng)用中需要一個新的URL時录平,都要增加一個新的@app.route行麻车。我們會在do_search函數(shù)之后,app.run()代碼行前面增加這一行斗这,為Web應(yīng)用增加一個新URL
@app.route('/entry')
修改3:創(chuàng)建一個函數(shù)返回正確呈現(xiàn)的HTML
將這個函數(shù)增加到新“@app.route”行下面
有了@app.route行之后动猬,可以為新增的URL關(guān)聯(lián)代碼,為此要創(chuàng)建一個完成具體工作的函數(shù)表箭。這個函數(shù)要調(diào)用render_template函數(shù)(并返回它的輸出)赁咙,這里要傳入模板文件名(這里是entry.html)以及模板所需的參數(shù)值(在這里需要為the_title提供一個值)
entry.html 提供要呈現(xiàn)的模板名
the_title='Welcome to search4letters on the web! 提供一個值與“the_title”參數(shù)關(guān)聯(lián)
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
現(xiàn)在暫時還不能夠運行∶庾辏基模板引用一個名為hf.css的樣式表彼水,這個樣式表要放在一個名為static的文件夾中,也就是說hf.css文件必須存在必須放在static文件夾中static文件夾必須放在webapp文件夾中极舔,在基模板中有看到hf.css文件的路徑
<link rel="stylesheet" href="static/hf.css" />
并且還要將基模板和兩個模板(base.html凤覆、entry.html、results.html)都存儲在templates文件夾中拆魏,templaes文件夾也在webapp文件夾中.
所以到現(xiàn)在有一個webapp文件夾盯桦,有5個文件(vsearch4web.py、hf.css渤刃、base.html拥峦、entry.html、results.html)和2個文件夾(static卖子、templates)
放置好文件夾就可以運行了略号,先ctrl+c退出服務(wù)器停止web應(yīng)用,再按向上箭頭回到上一步輸入文件名后按回車洋闽,出現(xiàn)running就是新代碼開始運行璃哟,等待為請求提供服務(wù)。但是出了點錯誤
這段代碼仍然支持 / 和 /search4 URL喊递,如果使用一個瀏覽器請求這些URL随闪,會得到相同的響應(yīng),但是如果輸入
http://127.0.0.1:5000/entry
瀏覽器中顯示的響應(yīng)將是所呈現(xiàn)的HTML表單
命令行提示窗口會顯示另外兩個狀態(tài)欄:
一個對應(yīng)/entry請求(請求HTML表單)
另一個與瀏覽器對hf.css樣式表的請求有關(guān)(請求樣式表)
但是如果輸入一個短語并調(diào)整要查找的字母值骚勘,點擊do it 按鈕時會出錯
看到命令提示符我們需要區(qū)分get和post的不同之處铐伴,首先要了解http狀態(tài)碼
當(dāng)web應(yīng)用出現(xiàn)問題撮奏,web服務(wù)器就會響應(yīng)一個http狀態(tài)碼并發(fā)送到瀏覽器中,http是允許web瀏覽器和服務(wù)器通信的協(xié)議当宴,實際上畜吊,每個web請求都會生成一個http狀態(tài)碼響應(yīng) P222
100類-信息消息
200類-成功消息
300類-重定向消息
400類-客戶端錯誤消息
500類-服務(wù)器錯誤消息
這里的405狀態(tài)碼指示客戶端(瀏覽器)使用了這個服務(wù)器不允許的一個http方法來發(fā)送請求。http方法我們需要掌握2種:GET和POST
GET方法:
瀏覽器通常使用這個方法從web服務(wù)器請求一個資源户矢,目前web應(yīng)用中所有URL都支持GET玲献,這是Flask默認的http方法
POST方法:
允許web瀏覽器向服務(wù)器通過http發(fā)送數(shù)據(jù),這與HTML<form>標記緊密關(guān)聯(lián)梯浪,可以讓Flask Web 應(yīng)用從瀏覽器接收提交的數(shù)據(jù)捌年,為此需要在@app.route行上提供一個額外的參數(shù)
再次修改vsearch4web.py,調(diào)整與Web應(yīng)用/search4 URL 對應(yīng)的@app.route行挂洛,來接收所提交的數(shù)據(jù)
@app.route修飾符除了接收URL作為第一個參數(shù)礼预,還接收其他可選的參數(shù)。其中有methods參數(shù)虏劲,這會列出URL支持的http方法托酸。Flask默認對所有的URL都支持GET方法,但是柒巫,如果methods參數(shù)賦值為一個要支持的http方法列表励堡,就會覆蓋這個默認行為
@app.route('/search4') #這里沒有指定要支持的http方法,所以Flask默認為GET
要讓/search4 URL 支持POST堡掏,需要為這個修飾符增加methods參數(shù)念秧,并為它賦一個http方法列表,也就是希望這個URL支持的所有http方法布疼。
@app.route('/search4',methods=['POST']) #指出/search4URL現(xiàn)在只支持POST方法(意味著不再支持GET方法)
服務(wù)器就不會再顯示“Method Not Allowed”,現(xiàn)在與html表單關(guān)聯(lián)的POST與@app.route代碼行上的POST一致
在entry.html里面有寫到<form method='POST' action='/search4'>
在vsearch4web.py里面寫到@app.route('/search4',methods=['POST'])
但是要注意币狠,html使用的是"method"(單數(shù))游两,而Flask使用的是"methods"(復(fù)數(shù))
如果你想要URL既支持GET方法又支持POST方法,只需要把要支持的http方法名增加到賦給methods參數(shù)的列表中
為/search4 URL增加GET和POST
@app.route('/search4',methods=['GET','POST'])
修改后的代碼
#這是vsearch4web.py里的代碼
from flask import Flask, render_template
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4',methods=['POST'])
def do_search() -> str:
return str(search4letters('life, the universe, and everything', 'eiru,!'))
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run()
為了提高修改過程中服務(wù)器上線和下線的效率漩绵,F(xiàn)lask允許在調(diào)試模式下運行Web應(yīng)用贱案,每次Flask注意到代碼已經(jīng)改變時(通常是做了修改并且已經(jīng)保存),就會自動重啟你的web應(yīng)用
打開調(diào)試模式需要在vsearch4web.py的最后一行代碼修改如下
app.run(debug=True) #打開調(diào)試模式
在停止web應(yīng)用后再次打開服務(wù)器上線止吐,不會再顯示“Running on ...”宝踪,F(xiàn)lask會顯示3個狀態(tài)行
如果代碼改變,Web應(yīng)用會自動重啟
*Restarting with stat
*Debugger is active!
*Debugger pin code:(調(diào)試器pin碼不同機器不一樣)
再一次輸入http://127.0.0.1:5000/entry進行與Web應(yīng)用交互碍扔,“Method Not Allowed”沒有了瘩燥,出現(xiàn)了返回的頁面,但是發(fā)現(xiàn)在嘗試多次輸入任何不同的短語不同,每次顯示返回的結(jié)果都是一樣的厉膀,無論輸入什么樣的單詞放回去的結(jié)果都是一樣的
返回總是返回相同的字符集“u,e,逗號,i,r”溶耘,回頭查看請求/seaarch4 URL時執(zhí)行的代碼,問題就在于phrase和letters的值硬編碼寫在函數(shù)中
@app.route('/search4',methods=['POST'])
def do_search() -> str:
return str(search4letters('life, the universe, and everything', 'eiru,!'))
無論在html表單中鍵入什么服鹅,這個代碼都總是使用這些硬編碼的值
html表單將數(shù)據(jù)提交到web服務(wù)器凳兵,需要用Flask提供的內(nèi)置對象request來訪問所提交的數(shù)據(jù)。request對象中的from字典屬性可以訪問從瀏覽器提交的html表單數(shù)據(jù)企软,form同樣支持中括號記法:要訪問表單中的一個數(shù)據(jù)庐扫,可以把表單元素的名字放在中括號中。
#訪問表單元素數(shù)據(jù)
request.form['phrase'] #訪問輸入到html表單的phrase
request.form['letters'] #訪問輸入到html表單的letters
同樣在vsearch4web.py中需要導(dǎo)入request對象仗哨,根據(jù)需要從request.form訪問數(shù)據(jù)形庭,并且把do_search函數(shù)的硬編碼的數(shù)據(jù)值替換為表單數(shù)據(jù),這樣就確保了在每次html表單中使用不同的phrase和letters值時藻治,從web應(yīng)用返回的結(jié)果會相應(yīng)地調(diào)整
#這是vsearch4web.py里的代碼
from flask import Flask, render_template,request
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4',methods=['POST'])
def do_search() -> str:
phrase = request.form['phrase'] #創(chuàng)建兩個新變量“phrase”碘勉,“l(fā)etters”
letters = request.form['letters'] #并把HTML表單的數(shù)據(jù)賦至新創(chuàng)建的變量
return str(search4letters(phrase, letters)) #然后在"search4letters"調(diào)用中使用這些變量
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run()
保存好vsearch4web.py后,在命令行提示窗口可以看到web應(yīng)用生成的狀態(tài)消息
Flask調(diào)試器已經(jīng)發(fā)現(xiàn)代碼有修改桩卵,重啟了web應(yīng)用验靡。但是只有正確完成了代碼修改,才會自動重新加載雏节。如果代碼有錯誤web應(yīng)用就會轉(zhuǎn)到命令行提示窗口胜嗓。要想再次運行就需要修正代碼錯誤并且手動重啟web應(yīng)用(按上箭頭再按回車)
命令行自動更新?很遺憾沒有出現(xiàn)重新加載钩乍,我需要手動加載辞州,手動加載后就已經(jīng)可以輸入單詞顯示正常了
但是有時候會出現(xiàn)空集合顯示為set(),這是因為尋找的字母都沒有出現(xiàn)過
現(xiàn)在任何web瀏覽器都可以提交一個phrase/letters組合寥粹,web應(yīng)用會代表我們調(diào)用search4letters并返回結(jié)果变过。
但是返回的結(jié)果生成的輸出只是一個空白的頁面上有字母而已還不是一個完整的html web頁面,它還只是一個原始的數(shù)據(jù)涝涤,作為文本返回給正在等待的瀏覽器(它會將這個結(jié)果顯示在屏幕上)
現(xiàn)在entry.html已經(jīng)生成表單html頁面媚狰,但是results.html還沒有生成html頁面,只是江結(jié)果顯示為原始數(shù)據(jù)
回憶前面的Jinja2模板技術(shù)時阔拳,提供了兩個html崭孤。第一個是entry.html用于生成表單;第二個是results.html用來顯示結(jié)果
下面就用resluts.html模板將原始數(shù)據(jù)輸出轉(zhuǎn)換為html
回顧results.html模板內(nèi)容
{% extends 'base.html' %}
{% block body %}
<h2>{{ the_title }}</h2>
<p>You submitted the following data:</p>
<table>
<tr><td>Phrase:</td><td>{{ the_phrase }}</td></tr>
<tr><td>Letters:</td><td>{{ the_letters }}</td></tr>
</table>
<p>When "{{the_phrase }}" is searched for "{{ the_letters }}", the following
results are returned:</p>
<h3>{{ the_results }}</h3>
{% endblock %}
需要特別注意雙大括號包圍的名字就是Jinja2變量糊肠,能夠從python代碼中的相應(yīng)變量得到值辨宠,這里有4個變量:
the_title
the_phrase
the_letters
the_results
但是在vsearch4web.py中的do_search只有與之相對應(yīng)的2個變量:phrase和letters,所以我們需要再添加對應(yīng)的the_title和the_results這兩個變量货裹,這樣一來函數(shù)才能夠滿足呈現(xiàn)這個模板中所需的4個變量
將"Here are your results:"字符串賦給the_title
將search4letters調(diào)用賦給the_results
這樣一來在呈現(xiàn)模板之前所有4個變量都能作為參數(shù)傳入模板中
下面再來修改vsearch4web.py
from flask import Flask, render_template, request
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> str:
return 'Hello world from Flask!'
@app.route('/search4', methods=['POST'])
def do_search() -> 'html': #修改注解嗤形,指示這個函數(shù)現(xiàn)在返回HTML,而不是像前一個版本返回str(一個純文本的字符串)
phrase = request.form['phrase']
letters = request.form['letters']
#創(chuàng)建一個python變量弧圆,名為title派殷,并為title賦一個字符串
title = 'Here are your results:'
#創(chuàng)建一個python變量还最,名為results,將“search4letters”的調(diào)用結(jié)果賦給"results“
results = str(search4letters(phrase, letters))
#results.html模板需要4個參數(shù)值,最后的results,這個逗號是可選的,有沒有都可以毡惜。
#呈現(xiàn)result.html模板拓轻,這個模板需要4個參數(shù)值
return render_template('results.html',
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,) #不要忘記這個結(jié)束函數(shù)調(diào)用的結(jié)束小括號
#各個python變量賦給相應(yīng)的Jinja參數(shù),程序代碼的數(shù)據(jù)會傳遞到模板中
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run(debug=True)
記得保存文件经伙,確保Flask自動地重新加載Web應(yīng)用
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
entry為生成表單扶叉,results為顯示結(jié)果。添加完4個變量也就是4個參數(shù)值后頁面已經(jīng)正常顯示了帕膜,但是還是需要注意 render_template 調(diào)用中最后還包括一個逗號(上圖有)枣氧,不過這在python中是被允許的,是可選的
現(xiàn)在Web應(yīng)用支持3個URL:/垮刹,/search4达吞。/entry。現(xiàn)在不需要"/"url想要同時將hello函數(shù)去掉荒典,需要讓Flask把對/URL的所有請求重定向到/entry URL酪劫,否則當(dāng)Web瀏覽器與這個Web應(yīng)用交互時倘若請求/URL(這是大多數(shù)Web應(yīng)用和網(wǎng)站的默認URL),就會得到一個404"Not Found"錯誤·寺董。
為此要調(diào)整hello函數(shù)覆糟,讓它向所有請求/URL的Web瀏覽器返回一個HTML redirect,就能夠?qū)⒅赶?的請求替換為/entry
修改vsearch4web.py
在from flask導(dǎo)入行上增加rediect
from flask import Flask, render_template, request,redirect #在導(dǎo)入列表中增加redirect
from vsearch import search4letters
app = Flask(__name__)
@app.route('/')
def hello() -> '302': #調(diào)整注解遮咖,指出該函數(shù)將返回什么滩字,300-399范圍內(nèi)的http狀態(tài)碼是重定向,302是調(diào)用redirect時Flask向瀏覽器發(fā)回的狀態(tài)碼
return redirect('/entry') #調(diào)用Flask的redirect函數(shù)御吞,指示瀏覽器請求另外一個URL(這里變成了/entry)
@app.route('/search4', methods=['POST'])
#修改注解麦箍,指示這個函數(shù)現(xiàn)在返回HTML,而不是像前一個版本返回str(一個純文本的字符串)
def do_search() -> 'html':
phrase = request.form['phrase']
letters = request.form['letters']
#創(chuàng)建一個python變量陶珠,名為title
title = 'Here are your results:'
#創(chuàng)建一個python變量挟裂,名為results,將“search4letters”的調(diào)用結(jié)果賦給"results“
results = str(search4letters(phrase, letters))
#results.html模板需要4個參數(shù)值,最后的results,這個逗號是可選的,有沒有都可以背率。
return render_template('results.html',
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,)
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run(debug=True)
編輯完成后保存就可以確保Web應(yīng)用的用戶請求/entry或/URL時將看到html表單
在服務(wù)器后臺可以看到,重定向頁面修改后不再返回5000嫩与,而是5000/entry了
注意后臺返回的302寝姿,但是1個請求會變成2個請求,函數(shù)是可以有多個URL
“GET /entry HTTP/1.1” 200 - #請求指向/entryURL划滋,可以立即得到服務(wù)饵筑。200-299范圍內(nèi)的狀態(tài)碼是成功消息:服務(wù)器已經(jīng)接收、理解和處理客戶端的請求
“GET / HTTP/1.1” 302 -
“GET /entry HTTP/1.1” 200 - #如果一個請求指向/URL处坪,Web應(yīng)用首先響應(yīng)一個302重定向根资,接著Web瀏覽器會發(fā)送另一個請求指向/entryURL架专,這會成功地得到Web應(yīng)用的服務(wù) 200狀態(tài)碼
這里的重定向似乎有點浪費,每次指向/URL的一個請求都會變成兩個請求玄帕,現(xiàn)在需要Flask將多個URL與一個給定的函數(shù)關(guān)聯(lián)部脚,就無需重定向了
所以如果一個函數(shù)有多個關(guān)聯(lián)的URL,F(xiàn)lask會嘗試依次與各個URL匹配裤纹,找到一個匹配就會執(zhí)行這個函數(shù)
修改vsearch4web.py
從from flask 導(dǎo)入行刪除redirect委刘,因為我們不再需要這個函數(shù)
剪切 @app.route('/') 并粘到 @app.route('/entry')的上面,刪除hellp函數(shù)的兩行代碼鹰椒,因為Web不再需要這些代碼
from flask import Flask, render_template, request
from vsearch import search4letters
app = Flask(__name__)
@app.route('/search4', methods=['POST'])
def do_search() -> 'html':
phrase = request.form['phrase']
letters = request.form['letters']
title = 'Here are your results:'
results = str(search4letters(phrase, letters))
return render_template('results.html',
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,)
@app.route('/') #entry_page函數(shù)現(xiàn)在有兩個關(guān)聯(lián)的URL
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
app.run(debug=True)
上面的run那里前面是沒有if的锡移,可以刪除,加上回去是為了pythonanywhere
更新了后臺后就可以看到只有一個請求一個反應(yīng)了漆际,奇怪的是我只看到了post淆珊,沒有看到get一定是哪里有弄錯了,但是我把最后一行的if給刪掉了也沒有變化奸汇,其實是我自己理解錯了施符。打開網(wǎng)址是get,是正確的茫蛹。輸入返回是post得到的返回值操刀,所以是一個get一個post
現(xiàn)在訪問/URL,會出現(xiàn)html表單婴洼,在查看Web應(yīng)用的狀態(tài)消息骨坑,可以確認現(xiàn)在處理/時只會有一個請求,而不再是有兩個請求柬采。輸入并且按Do it 就會出現(xiàn)返回的響應(yīng)欢唾。所以到現(xiàn)在就已經(jīng)完成了Web應(yīng)用一個請求一個返回狀態(tài),可以獨立與用戶進行交互了
完成到這里需要注意兩個點:
@符號標識是一個修飾符粉捻。利用修飾符可以改變一個已有函數(shù)的行為而無需修改這個函數(shù)的代碼礁遣。在Web應(yīng)用中,使用Flask的@app.route修飾符為python函數(shù)關(guān)聯(lián)URL肩刃。一個函數(shù)可以修飾多次(do_search函數(shù)關(guān)聯(lián)了多個URL)
使用Jinja2文本模板引擎在Web應(yīng)用中呈現(xiàn)html頁面
將Web應(yīng)用部署到云
在pythonanywhere上面部署我們的Web應(yīng)用進行托管
pythonanywhere喜歡控制Web應(yīng)用的啟動祟霍,認為由它負責(zé)調(diào)用app.run(),也就是說不再需要在代碼中調(diào)用app.run()盈包。如果偏要在代碼中運行app.run()沸呐,pythonanywhere會拒絕運行Web運用
代碼最后一行run會與pythonanywhere產(chǎn)生沖突兩者不兼容,云只是用來部署而不是用來開發(fā)呢燥,所以可以用if那一行來開頭化解沖突
所以最后一行修改為下面run()
if __name__ == '__main__': #現(xiàn)在只有當(dāng)直接由python執(zhí)行時才會運行"app.run()"代碼行
app.run(debug=True)
if__name__=='main' 被稱為'dunder name dunder main' P239
最終版本
from flask import Flask, render_template, request
from vsearch import search4letters
app = Flask(__name__)
@app.route('/search4', methods=['POST'])
def do_search() -> 'html':
phrase = request.form['phrase']
letters = request.form['letters']
title = 'Here are your results:'
results = str(search4letters(phrase, letters))
return render_template('results.html',
the_title=title,
the_phrase=phrase,
the_letters=letters,
the_results=results,)
@app.route('/')
@app.route('/entry')
def entry_page() -> 'html':
return render_template('entry.html',
the_title='Welcome to search4letters on the web!')
if __name__ == '__main__':
app.run(debug=True)
處理好后崭添,接下來就可以直接部署在云上面了,使用pythonanywhere
到現(xiàn)在需要準備好想要部署在云端的文件夾叛氨,并命名為webapp呼渣,文件夾包括了vsearch4web.py棘伴、在static文件夾中的hf.py,在templates文件夾中的base.html屁置、entry.html和results.html焊夸,webapp文件夾中中一共包括了5個文件,這樣子才是準備好的缰犁。接著把webapp壓縮成zip文件而不是rar文件淳地,因為需要用到命令行
出現(xiàn)了一些問題,在按步驟弄好后就可以使用命令行來處理
因為我們已經(jīng)有了vsearch.py在webapp.zip中了就不需要再去弄vsearch.py的壓縮包帅容,直接跳出書本中的第一步
在主界面
將文件上傳云
找到Files中的Upload a file 上傳壓縮文件
但是我之前壓縮錯了導(dǎo)致后面用命令行解壓不出來颇象,記得一定是zip文件其他的都不行
open bash是打開命令行的控制臺,我壓縮錯誤沒辦法解壓只能夠重新壓縮一遍
輸入命令行upzip 解壓縮找不到文件一直提示我錯誤遣钳,我重新又試了好幾遍但是結(jié)果顯示的錯誤都是一樣的,我定睛一看麦乞,是命令行輸入錯誤蕴茴!
先是 unzip webapp.zip
不是upzip 因為看錯我做了一個早上在循環(huán)簡直在浪費時間。代碼一定要細心看姐直,別馬大哈
在單擊頁面右上角的Open a bash console here 鏈接倦淀,打開終端窗口(基于瀏覽器的Linux控制臺-命令提示窗口)來解壓縮和安裝
先來解壓縮(解開web應(yīng)用代碼),使用命令行
unzip webapp.zip
安裝Web應(yīng)用代碼声畏,將它安裝到mysite文件夾中(我們可以先在儀表板建好mysite文件夾也可以現(xiàn)在退出命令行操作新建文件夾撞叽,命令行會一直在后臺開著如果你不結(jié)束的話)
把代碼移至mysite文件夾,使用命令行
mv webapp/* mysite
弄好了mv后返回儀表板選擇web標簽頁插龄,只能創(chuàng)建一個web項目愿棋,但是要想創(chuàng)建兩個以上應(yīng)用必須要付費。單擊"Add a new web app"來創(chuàng)建應(yīng)用
建好后千萬不要按綠色大按鈕均牢,因為我們還沒有告訴pythonanywhere代碼是多少糠雨,暫時不要運行
往下翻頁找到Code下面的WSGI configuration file 標簽右邊的長鏈接徘跪,其它所有代碼行都不理甘邀,單擊這個長連接鏈接,這個長連接會把你新創(chuàng)建的Flask web 應(yīng)用的配置文件加載到pythonanywhere的web文本編輯器中垮庐,它和上文中提及的run()調(diào)用密切相關(guān)松邪。
pythonanywhere會在調(diào)用app.run()之前導(dǎo)入web應(yīng)用的代碼,是因為這個配置文件支持了這種行為突硝。但是要讓它引用我們的代碼就需要來編輯修改這個文件的最后一行:
將原文件的 from flask_app import app as application 修改為
from vsearch4web import app as application
修改這個文件最后一行是為了能夠引用vsearch4web模塊
也就是可以說 從......當(dāng)中導(dǎo)進來作為app的應(yīng)用
這里的......就是vsearch4web.py
修改完成配置文件后测摔,記得保存Save
接著就可以點擊綠色大按鈕了置济,并且點擊網(wǎng)址就可以跳轉(zhuǎn)到網(wǎng)頁上解恰,云部署已經(jīng)成功了锋八。網(wǎng)頁會顯示正常,現(xiàn)在的網(wǎng)頁不僅僅能夠在本地運行护盈,任何人只要連入互聯(lián)網(wǎng)并且有一個Web瀏覽器就可以使用這個應(yīng)用
任何人都可以通過使用這個Web地址與Web應(yīng)用進行交互
現(xiàn)在要返回儀表板并且進行注銷挟纱,注意,盡管你已經(jīng)注銷腐宋,但是Web應(yīng)用還會在云中繼續(xù)運行紊服,除非告訴它停止運行