Tornado框架01-入門總概

咱們首先來談談web框架. web框架的本質其實就是socket服務端再加上業務邏輯處理, 好比像是Tornado這樣的框架. 有一些框架則只包含業務邏輯處理, 例如Django, bottle, flask這些框架, 它們的使用須要依賴包含socket的第三方模塊(即 wsgiref)來運行
在python中常見的web框架構建模式有如下兩種: css

  • MVC框架:
    • 數據庫相關操做的Models
    • 視圖文件的Views
    • 業務邏輯的Controllers
  • MTV框架:
    • 數據庫相關操做的Models
    • 模板文件Templates
    • 業務邏輯的Views

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

在使用Tornado框架前, 咱們先使用wsgiref再加上本身寫的業務邏輯自定義一個web框架python

#!/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) 這裏建立socket服務端, 並傳入業務邏輯功能函數RunServer(rq, rp)
  • http.serve_forever() 啓動服務端, 阻塞進程等待客戶端訪問, 一旦有訪問則執行RunServer(rq, rp)方法
  • RunServer(rq, rp) 該方法中rq封裝了請求信息, rp封裝了響應信息
    • url = rq['PATH_INFO'] 獲取請求的url鏈接地址
    • ret = URLS[url]() 根據請求的url執行對應的函數
  • 當咱們將執行的index()news()功能函數放進Controllers業務邏輯處理模塊, 將返回結果ret改成文件讀寫後的內容, 並將該文件放置到Views或者Template模塊中, 就造成了最基礎版本的MVCMTV框架

接下來咱們使用Tornado實現一個簡陋的任務表功能demoweb

目錄結構

commons.css文件內容: 數據庫

.body {
    margin: 0;
    background-color: cornflowerblue;
}複製代碼

index.html文件內容: flask

<!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>內容展現</h1>
<ul>
    {% for item in contents %}
        <li>{{item}}</li>
    {% end %}
</ul>
</body>
</html>複製代碼

index.py文件內容: 瀏覽器

#!/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 = [] 爲存放的是輸入框輸入的內容
  • settings字典表示的是配置文件
    • 'template_path': 'template' 模板文件的存放位置
    • 'static_path': 'static' 靜態文件的存放位置, 靜態文件必須聲明, 不然瀏覽器沒法找到靜態文件
    • 'static_url_prefix': 'static/' 靜態文件前綴, 減小每一個文件引入都要加前綴的麻煩
  • application = tornado.web.Application([
         (r"/index", MyHandle)
     ], **settings)複製代碼
    根據瀏覽器的url肯定其對應的處理類並生成該類的對象
  • application.listen(80) 設置服務端的監聽端口
  • tornado.ioloop.IOLoop.instance().start() 阻塞服務端進程, 等待客戶端的訪問
  • 客戶端第一次訪問調用的是MyHandle類中的get(self, *args, **kwargs)方法, 服務端向客戶端返回index.html文件
  • 客戶端瀏覽器接受到index.html文件以後, 在輸入框中輸入內容並提交以後會調用post(self, *args, **kwargs), 並將輸入的內容追加到
  • self.get_argument('name') 獲取指定參數的內容
    CONTENTS_LIST中, 服務端返回index.html, 返回過程當中Toranado
    會將CONTENTS_LIST 的內容渲染到index.html以後纔會發給客戶端瀏覽器

python中的模板引擎本質上是將html文件轉換成一段python函數字符串, 再經過compileexec將該函數執行, 以此來進行模板渲染緩存

如今咱們介紹一下模板引擎的使用: cookie

項目目錄

uimethod.py文件以下: session

#!/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>內容展現</h1>
<ul>
    {% for item in contents %}
    <li>{{item}}</li>
    {% end %}
</ul>
<hr>
</body>
</html>複製代碼

咱們看看客戶端訪問的結果:

訪問結果

  • 模板引擎中的{{key}}表示取key對應的值, 當key爲函數時候執行該函數並取該函數結果. 例如index.html文件中的<h1>{{ag}}</h1> 實際上取得是index.pyself.render("index.html", ag="this is ag", contents=CONTENTS_LIST)中的參數ag的值
  • <h1>{{test_uimethod()}}</h1> 這裏執行的是自定義函數, 咱們將這個自定義函數寫在uimethod.py文件中, 而且在index.py文件中導入, 而後將index.py文件中的settings配置增長一行'ui_methods': ut, 該行內容表示模板引擎可執行自定義函數
  • 模板引擎中的{%%}可用於循環語句和條件語言以及自定義類的執行, {% for item in contents %}此處正是用於循環遍歷contents中的內容
  • <h1>{%module MyClass()%}</h1>此處表示模板引擎執行自定義類, 該類的文件對應的是uimodule.py文件, 咱們須要在index.pysettings中增長一行'ui_modules': ud, 改行表示模板引擎可以使用自定義類
  • 注意, 咱們將index.html文件引入css的方式改成了<link rel="stylesheet" href='{{static_url("commons.css")}}'>, static_url()是模板引擎內置的自定義函數, 用該函數引入css文件時候, 僅當css文件內容發生變化時候, 瀏覽器纔會從新緩存該css文件

考慮到篇幅太長不容易閱讀, 筆者這裏將關於Tornado框架的cookie知識, 自定義session的使用 路由系統,以及模板引擎高級部分放在後期文章分篇共享

相關文章
相關標籤/搜索