史上最簡單的 Python Flask 框架搭建抵赢,手把手教你如何裝逼

構(gòu)建一個Web應(yīng)用:利用search4letters這個函數(shù)奢入,讓人們都可以在web上訪問這個函數(shù)

Python Flask.jpg

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

開始-prompt.jpg
>cd 位置粘貼(與第一種方法一樣)

檢查是否已經(jīng)安裝好flask框架

>flask 
輸入flask.jpg

驗證已安裝.jpg

回車后代碼跑起來結(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地址)

但是會報錯

第一遍報錯.jpg

第一遍報錯翻譯.jpg

第二次跑.jpg

5000是端口號,網(wǎng)頁默認是80不需要寫出來
flask若在單機上是找不到服務(wù)器的
如果IP輸入5000/dothiswork.html 丑搔,服務(wù)器就會多出一行404報錯厦瓢,因為沒有5000的話用戶就會找不到服務(wù)器

我們把IP地址輸入打開也是可以跳轉(zhuǎn)到網(wǎng)頁的,因為已經(jīng)Running起來了

打開網(wǎng)頁.jpg

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

第三次刷新.jpg

這時胁住,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”錯誤消息娱挨。

第四次加網(wǎng)頁404.jpg

輸入http://127.0.0.1:5000/doesthiswork.html,是沒有頁面并且服務(wù)器會同步報錯404
瀏覽器顯示“Not Found”,終端窗口運行的Web應(yīng)用也會用一個適當(dāng)?shù)南⒏聽顟B(tài)

第四次服務(wù)器同步.jpg

在這里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é)果

search4網(wǎng)頁顯示.png
search文件夾自動添加文件.jpg

調(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ù)。但是出了點錯誤

運行報錯.jpg
運行成功.jpg

這段代碼仍然支持 / 和 /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)(請求樣式表)

entry網(wǎng)頁.jpg

但是如果輸入一個短語并調(diào)整要查找的字母值骚勘,點擊do it 按鈕時會出錯

do it 出錯.jpg
do it 405.jpg

看到命令提示符我們需要區(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()
修改了post后重新提交.jpg

為了提高修改過程中服務(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é)果都是一樣的

修改post重新提交網(wǎng)頁.jpg
修改post重新提交do it網(wǎng)頁變?yōu)閟earch4.jpg
輸入不同單詞返回結(jié)果一樣1.jpg
輸入不同單詞返回結(jié)果都是一樣的2.jpg

返回總是返回相同的字符集“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)可以輸入單詞顯示正常了

沒有重新加載需要手動加載.jpg
手動加載后嘗試成功.jpg
手動加載嘗試成功2.jpg
加載后嘗試成功運行后臺變化.jpg

但是有時候會出現(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)
修改完添加的返回頁面.jpg
添加返回的頁面2.jpg
添加返回的頁面后臺.jpg

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

重定向修改后頁面entry.jpg
重定向頁面.jpg
重定向頁面2.jpg
重定向后臺注意302.jpg

在服務(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

?修改好url后自動更新了.jpg
更新后就是一個gethepost了.jpg

現(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文件淳地,因為需要用到命令行

將webapp壓縮成7zip文件.jpg
打開pythonanywhere.jpg
0.jpg
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg

出現(xiàn)了一些問題,在按步驟弄好后就可以使用命令行來處理
因為我們已經(jīng)有了vsearch.py在webapp.zip中了就不需要再去弄vsearch.py的壓縮包帅容,直接跳出書本中的第一步

在主界面

dashboard.jpg

將文件上傳云
找到Files中的Upload a file 上傳壓縮文件

files update.jpg

但是我之前壓縮錯了導(dǎo)致后面用命令行解壓不出來颇象,記得一定是zip文件其他的都不行

上傳錯了.jpg
open bash.jpg

open bash是打開命令行的控制臺,我壓縮錯誤沒辦法解壓只能夠重新壓縮一遍

將webapp壓縮成zip文件并徘,前面錯了.jpg.jpg
上傳成功.jpg
打開控制臺.jpg
upzip webapp 沒有找到.jpg

輸入命令行upzip 解壓縮找不到文件一直提示我錯誤遣钳,我重新又試了好幾遍但是結(jié)果顯示的錯誤都是一樣的,我定睛一看麦乞,是命令行輸入錯誤蕴茴!

先是 unzip webapp.zip
不是upzip 因為看錯我做了一個早上在循環(huán)簡直在浪費時間。代碼一定要細心看姐直,別馬大哈

在單擊頁面右上角的Open a bash console here 鏈接倦淀,打開終端窗口(基于瀏覽器的Linux控制臺-命令提示窗口)來解壓縮和安裝

先來解壓縮(解開web應(yīng)用代碼),使用命令行

unzip webapp.zip
顯示前界面.jpg
unzip webapp.zip.jpg
unzip webapp.zip2.jpg

安裝Web應(yīng)用代碼声畏,將它安裝到mysite文件夾中(我們可以先在儀表板建好mysite文件夾也可以現(xiàn)在退出命令行操作新建文件夾撞叽,命令行會一直在后臺開著如果你不結(jié)束的話)

新建mysite文件夾.jpg
建好mysite文件夾后.jpg

把代碼移至mysite文件夾,使用命令行

mv webapp/* mysite
mv mysite命令.jpg
mv 移動完成.jpg

弄好了mv后返回儀表板選擇web標簽頁插龄,只能創(chuàng)建一個web項目愿棋,但是要想創(chuàng)建兩個以上應(yīng)用必須要付費。單擊"Add a new web app"來創(chuàng)建應(yīng)用

返回web并新建.jpg
新建1.jpg
新建2.jpg
選擇flask1.jpg
選擇flask2.jpg
選擇3.6.jpg
選擇3.6python版本.jpg
選擇路徑1.jpg
選擇路徑2.jpg

建好后千萬不要按綠色大按鈕均牢,因為我們還沒有告訴pythonanywhere代碼是多少糠雨,暫時不要運行

建web成功,千萬不要按綠色按鈕.jpg

往下翻頁找到Code下面的WSGI configuration file 標簽右邊的長鏈接徘跪,其它所有代碼行都不理甘邀,單擊這個長連接鏈接,這個長連接會把你新創(chuàng)建的Flask web 應(yīng)用的配置文件加載到pythonanywhere的web文本編輯器中垮庐,它和上文中提及的run()調(diào)用密切相關(guān)松邪。

找到code.jpg
找到code2.jpg

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

點擊wsgi.py.jpg
打開sdgi編輯16行.jpg
16行修改為vsearch4web.jpg

修改完成配置文件后测摔,記得保存Save

可以點擊綠色按鈕了.jpg

保存.jpg

接著就可以點擊綠色大按鈕了置济,并且點擊網(wǎng)址就可以跳轉(zhuǎn)到網(wǎng)頁上解恰,云部署已經(jīng)成功了锋八。網(wǎng)頁會顯示正常,現(xiàn)在的網(wǎng)頁不僅僅能夠在本地運行护盈,任何人只要連入互聯(lián)網(wǎng)并且有一個Web瀏覽器就可以使用這個應(yīng)用

返回可以點擊綠色按鈕了.jpg
點擊網(wǎng)址.jpg
點擊網(wǎng)址會自動跳轉(zhuǎn).jpg

任何人都可以通過使用這個Web地址與Web應(yīng)用進行交互

網(wǎng)頁.jpg
網(wǎng)頁1.jpg
網(wǎng)頁2.jpg

現(xiàn)在要返回儀表板并且進行注銷挟纱,注意,盡管你已經(jīng)注銷腐宋,但是Web應(yīng)用還會在云中繼續(xù)運行紊服,除非告訴它停止運行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市胸竞,隨后出現(xiàn)的幾起案子欺嗤,更是在濱河造成了極大的恐慌,老刑警劉巖卫枝,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煎饼,死亡現(xiàn)場離奇詭異黑滴,居然都是意外死亡辅柴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門置侍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來马篮,“玉大人沾乘,你說我怎么就攤上這事』氩猓” “怎么了翅阵?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長尽爆。 經(jīng)常有香客問我怎顾,道長,這世上最難降的妖魔是什么漱贱? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任槐雾,我火速辦了婚禮,結(jié)果婚禮上幅狮,老公的妹妹穿的比我還像新娘募强。我一直安慰自己,他們只是感情好崇摄,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布擎值。 她就那樣靜靜地躺著,像睡著了一般逐抑。 火紅的嫁衣襯著肌膚如雪鸠儿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音进每,去河邊找鬼汹粤。 笑死,一個胖子當(dāng)著我的面吹牛田晚,可吹牛的內(nèi)容都是我干的嘱兼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼贤徒,長吁一口氣:“原來是場噩夢啊……” “哼芹壕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起接奈,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤踢涌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后斯嚎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡挨厚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年堡僻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疫剃。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡钉疫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巢价,到底是詐尸還是另有隱情牲阁,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布壤躲,位于F島的核電站城菊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碉克。R本人自食惡果不足惜凌唬,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望漏麦。 院中可真熱鬧客税,春花似錦、人聲如沸撕贞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捏膨。三九已至秧均,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背目胡。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工疙描, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讶隐。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像久又,于是被迫代替她去往敵國和親巫延。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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