Tornado框架01-入門總概

我們首先來談?wù)剋eb框架. web框架的本質(zhì)其實就是socket服務(wù)端再加上業(yè)務(wù)邏輯處理, 比如像是Tornado這樣的框架. 有一些框架則只包含業(yè)務(wù)邏輯處理, 例如Django, bottle, flask這些框架, 它們的使用需要依賴包含socket的第三方模塊(即 wsgiref)來運行
在python中常見的web框架構(gòu)建模式有以下兩種:

  • *MVC框架: *
  • 數(shù)據(jù)庫相關(guān)操作的Models
  • 視圖文件的Views
  • 業(yè)務(wù)邏輯的Controllers
  • MTV框架:
  • 數(shù)據(jù)庫相關(guān)操作的Models
  • 模板文件Templates
  • 業(yè)務(wù)邏輯的Views

以上兩種只是命名不同, 所遵循的的思想也只是大同小異

在使用Tornado框架前, 我們先使用wsgiref再加上自己寫的業(yè)務(wù)邏輯自定義一個web框架

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from wsgiref.simple_server import make_server


def index():
    return "This is index "


def news():
    return "welcome to news "


URLS = {
    '/index': index,
    '/news': news,
}


def RunServer(rq, rp):
    rp('200 OK', [('Content-Type', 'text/html')])
    url = rq['PATH_INFO']
    if url in URLS.keys():
        ret = URLS[url]()
    else:
        ret = '404'
    return ret


if __name__ == '__main__':
    http = make_server('', 8000, RunServer)
    http.serve_forever()
  • wsgiref在py2中運行正常, 在py3中會報錯
  • http = make_server('', 8000, RunServer) 這里創(chuàng)建socket服務(wù)端, 并傳入業(yè)務(wù)邏輯功能函數(shù)RunServer(rq, rp)
  • http.serve_forever() 啟動服務(wù)端, 阻塞進(jìn)程等待客戶端訪問, 一旦有訪問則執(zhí)行RunServer(rq, rp)方法
  • RunServer(rq, rp) 該方法中rq封裝了請求信息, rp封裝了響應(yīng)信息
  • url = rq['PATH_INFO'] 獲取請求的url連接地址
  • ret = URLS[url]() 根據(jù)請求的url執(zhí)行對應(yīng)的函數(shù)
  • 當(dāng)我們將執(zhí)行的index()news()功能函數(shù)放進(jìn)Controllers業(yè)務(wù)邏輯處理模塊, 將返回結(jié)果ret改為文件讀寫后的內(nèi)容, 并將該文件放置到Views或者Template模塊中, 就形成了最基礎(chǔ)版本的MVCMTV框架

接下來我們使用Tornado實現(xiàn)一個簡陋的任務(wù)表功能demo

目錄結(jié)構(gòu)

**commons.css文件內(nèi)容: **

.body {
    margin: 0;
    background-color: cornflowerblue;
}

**index.html文件內(nèi)容: **

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>S1</title>
    <link rel="stylesheet" href="../static/commons.css">
</head>
<body>
<form method="post">
    <input type="text" name="name">
    <input type="submit" value="提交">
</form>
<h1>內(nèi)容展示</h1>
<ul>
    {% for item in contents %}
        <li>{{item}}</li>
    {% end %}
</ul>
</body>
</html>

**index.py文件內(nèi)容: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.web, tornado.ioloop


class MyHandle(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.render("index.html", contents=CONTENTS_LIST)

    def post(self, *args, **kwargs):
        CONTENTS_LIST.append(self.get_argument('name'))
        self.render('index.html', contents=CONTENTS_LIST)


if __name__ == '__main__':
    CONTENTS_LIST = []
    settings = {
        'template_path': 'template',
        'static_path': 'static',
        'static_url_prefix': 'static/',
    }

    application = tornado.web.Application([
        (r"/index", MyHandle)
    ], **settings)
    application.listen(80)
    tornado.ioloop.IOLoop.instance().start()
客戶端第一次訪問
第一次輸入提交
  • CONTENTS_LIST = [] 為存放的是輸入框輸入的內(nèi)容
  • settings字典表示的是配置文件
  • 'template_path': 'template' 模板文件的存放位置
  • 'static_path': 'static' 靜態(tài)文件的存放位置, 靜態(tài)文件必須聲明, 否則瀏覽器無法找到靜態(tài)文件
  • 'static_url_prefix': 'static/' 靜態(tài)文件前綴, 減少每個文件引入都要加前綴的麻煩

application = tornado.web.Application([
(r"/index", MyHandle)
], **settings)

根據(jù)瀏覽器的url確定其對應(yīng)的處理類并生成該類的對象
-  `application.listen(80)` 設(shè)置服務(wù)端的監(jiān)聽端口
- `tornado.ioloop.IOLoop.instance().start()` 阻塞服務(wù)端進(jìn)程, 等待客戶端的訪問
- 客戶端第一次訪問調(diào)用的是`MyHandle`類中的`get(self, *args, **kwargs)`方法, 服務(wù)端向客戶端返回`index.html`文件
- 客戶端瀏覽器接受到`index.html`文件之后, 在輸入框中輸入內(nèi)容并提交之后會調(diào)用`post(self, *args, **kwargs)`, 并將輸入的內(nèi)容追加到
- `self.get_argument('name')` 獲取指定參數(shù)的內(nèi)容
`CONTENTS_LIST`中, 服務(wù)端返回`index.html`, 返回過程中`Toranado`
會將`CONTENTS_LIST` 的內(nèi)容渲染到`index.html`之后才會發(fā)給客戶端瀏覽器

**python中的模板引擎本質(zhì)上是將`html`文件轉(zhuǎn)換成一段`python`函數(shù)字符串, 再通過`compile`和`exec`將該函數(shù)執(zhí)行, 以此來進(jìn)行模板渲染**

*現(xiàn)在我們介紹一下模板引擎的使用: *


![項目目錄](http://upload-images.jianshu.io/upload_images/4241702-f0b7d9c757a0d228.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

**`uimethod.py`文件如下: **
```python
#!/usr/bin/env python
# -*- coding:utf-8 -*-

def test_uimethod(self):
    return "uimethod"

**uimodule.py文件如下: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from tornado.web import UIModule

class MyClass(UIModule):
    def render(self, *args, **kwargs):
        return "uimodule"

**index.py文件如下: **

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.web, tornado.ioloop
import uimethod as ut
import uimodule as ud


class MyHandle(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.render("index.html", ag="this is ag", contents=CONTENTS_LIST)

    def post(self, *args, **kwargs):
        CONTENTS_LIST.append(self.get_argument('name'))
        self.render('index.html', contents=CONTENTS_LIST)


if __name__ == '__main__':
    CONTENTS_LIST = []
    settings = {
        'template_path': 'template',
        'static_path': 'static',
        'static_url_prefix': 'static/',
        'ui_methods': ut,
        'ui_modules': ud
    }

    application = tornado.web.Application([
        (r"/index", MyHandle)
    ], **settings)
    application.listen(80)
    tornado.ioloop.IOLoop.instance().start()

**index.html文件如下: **

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>S1</title>
    <link rel="stylesheet" href='{{static_url("commons.css")}}'>
</head>
<body>
<h1>{{ag}}</h1>
<h1>{{test_uimethod()}}</h1>
<h1>{%module MyClass()%}</h1>
<form method="post">
    <input type="text" name="name">
    <input type="submit" value="提交">
</form>
<h1>內(nèi)容展示</h1>
<ul>
    {% for item in contents %}
    <li>{{item}}</li>
    {% end %}
</ul>
<hr>
</body>
</html>

*我們看看客戶端訪問的結(jié)果: *

訪問結(jié)果
  • 模板引擎中的{{key}}表示取key對應(yīng)的值, 當(dāng)key為函數(shù)時候執(zhí)行該函數(shù)并取該函數(shù)結(jié)果. 例如index.html文件中的<h1>{{ag}}</h1> 實際上取得是index.pyself.render("index.html", ag="this is ag", contents=CONTENTS_LIST)中的參數(shù)ag的值
  • <h1>{{test_uimethod()}}</h1> 這里執(zhí)行的是自定義函數(shù), 我們將這個自定義函數(shù)寫在uimethod.py文件中, 并且在index.py文件中導(dǎo)入, 然后將index.py文件中的settings配置增加一行'ui_methods': ut, 該行內(nèi)容表示模板引擎可執(zhí)行自定義函數(shù)
  • 模板引擎中的{%%}可用于循環(huán)語句和條件語言以及自定義類的執(zhí)行, {% for item in contents %}此處正是用于循環(huán)遍歷contents中的內(nèi)容
  • <h1>{%module MyClass()%}</h1>此處表示模板引擎執(zhí)行自定義類, 該類的文件對應(yīng)的是uimodule.py文件, 我們需要在index.pysettings中增加一行'ui_modules': ud, 改行表示模板引擎可使用自定義類
  • 注意, 我們將index.html文件引入css的方式改為了<link rel="stylesheet" href='{{static_url("commons.css")}}'>, static_url()是模板引擎內(nèi)置的自定義函數(shù), 用該函數(shù)引入css文件時候, 僅當(dāng)css文件內(nèi)容發(fā)生變化時候, 瀏覽器才會重新緩存該css文件

考慮到篇幅太長不容易閱讀, 筆者這里將關(guān)于Tornado框架的cookie知識, 自定義session的使用 路由系統(tǒng),以及模板引擎高級部分放在后期文章分篇共享

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市豁鲤,隨后出現(xiàn)的幾起案子或链,更是在濱河造成了極大的恐慌惫恼,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澳盐,死亡現(xiàn)場離奇詭異祈纯,居然都是意外死亡,警方通過查閱死者的電腦和手機叼耙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門腕窥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筛婉,你說我怎么就攤上這事簇爆。” “怎么了爽撒?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵入蛆,是天一觀的道長。 經(jīng)常有香客問我硕勿,道長哨毁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任源武,我火速辦了婚禮扼褪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粱栖。我一直安慰自己迎捺,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布查排。 她就那樣靜靜地躺著凳枝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上岖瑰,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天叛买,我揣著相機與錄音,去河邊找鬼蹋订。 笑死率挣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的露戒。 我是一名探鬼主播椒功,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼智什!你這毒婦竟也來了动漾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤荠锭,失蹤者是張志新(化名)和其女友劉穎旱眯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體证九,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡删豺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了愧怜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呀页。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拥坛,靈堂內(nèi)的尸體忽然破棺而出蓬蝶,到底是詐尸還是另有隱情,我是刑警寧澤渴逻,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布疾党,位于F島的核電站音诫,受9級特大地震影響惨奕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜竭钝,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一梨撞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧香罐,春花似錦卧波、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春查坪,著一層夾襖步出監(jiān)牢的瞬間寸宏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工偿曙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留氮凝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓望忆,卻偏偏與公主長得像罩阵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子启摄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355

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

  • tornado框架是一款相較于其他web framework處理服務(wù)器性能問題更加強健的輕量級的強大的Pytho...
    惡人未滿閱讀 7,127評論 3 10
  • # Python 資源大全中文版 我想很多程序員應(yīng)該記得 GitHub 上有一個 Awesome - XXX 系列...
    aimaile閱讀 26,491評論 6 427
  • 22年12月更新:個人網(wǎng)站關(guān)停稿壁,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,184評論 22 257
  • 提綱: 1 什么是感情? 之前認(rèn)為的感情是兩個人長相廝守鞋仍,一起體驗生活的美常摧,太平到老,就是幸福的感情了威创。 現(xiàn)在落午,覺...
    zhoul_m閱讀 817評論 0 1