Python開發【第十五篇】:Web框架之Tornado

概述

Tornado 是 FriendFeed 使用的可擴展的非阻塞式 web 服務器及其相關工具的開源版本。這個 Web 框架看起來有些像web.py 或者 Google 的 webapp,不過爲了能有效利用非阻塞式服務器環境,這個 Web 框架還包含了一些相關的有用工具 和優化。javascript

Tornado 和如今的主流 Web 服務器框架(包括大多數 Python 的框架)有着明顯的區別:它是非阻塞式服務器,並且速度至關快。得利於其 非阻塞的方式和對 epoll 的運用,Tornado 每秒能夠處理數以千計的鏈接,這意味着對於實時 Web 服務來講,Tornado 是一個理想的 Web 框架。咱們開發這個 Web 服務器的主要目的就是爲了處理 FriendFeed 的實時功能 ——在 FriendFeed 的應用裏每個活動用戶都會保持着一個服務器鏈接。(關於如何擴容 服務器,以處理數以千計的客戶端的鏈接的問題,請參閱 C10K problem。)html

下載安裝:java

1
2
3
4
pip3 install tornado
 
源碼安裝
https: / / pypi.python.org / packages / source / t / tornado / tornado - 4.3 .tar.gz

框架使用

1、快速上手python

執行過程:jquery

  • 第一步:執行腳本,監聽 8888 端口
  • 第二步:瀏覽器客戶端訪問 /index  -->  http://127.0.0.1:8888/index
  • 第三步:服務器接受請求,並交由對應的類處理該請求
  • 第四步:類接受到請求以後,根據請求方式(post / get / delete ...)的不一樣調用並執行相應的方法
  • 第五步:方法返回值的字符串內容發送瀏覽器
  異步非阻塞示例

2、路由系統git

路由系統其實就是 url 和 類 的對應關係,這裏不一樣於其餘框架,其餘不少框架均是 url 對應 函數,Tornado中每一個url對應的是一個類。github

Tornado中原生支持二級域名的路由,如:web

 

3、模板引擎算法

Tornao中的模板語言和django中相似,模板引擎將模板文件載入內存,而後將數據嵌入其中,最終獲取到一個完整的字符串,再將字符串返回給請求者。django

Tornado 的模板支持「控制語句」和「表達語句」,控制語句是使用 {% 和 %} 包起來的 例如 {% if len(items) > 2 %}。表達語句是使用 {{ 和 }} 包起來的,例如 {{ items[0] }}

控制語句和對應的 Python 語句的格式基本徹底相同。咱們支持 ifforwhile 和 try,這些語句邏輯結束的位置須要用 {% end %} 作標記。還經過 extends 和 block 語句實現了模板繼承。這些在 template 模塊 的代碼文檔中有着詳細的描述。

注:在使用模板前須要在setting中設置模板路徑:"template_path" : "tpl"

一、基本使用

  app.py
  index.html
  其餘方法

二、母版

  layout.html
  index.html

三、導入

  header.html
  index.html

四、自定義UIMethod以UIModule

a. 定義

  uimethods.py
  uimodules.py

b. 註冊

  View Code

c. 使用

  View Code

4、靜態文件

對於靜態文件,能夠配置靜態文件的目錄和前段使用時的前綴,而且Tornaodo還支持靜態文件緩存。

  app.py
  index.html

注:靜態文件緩存的實現

  View Code

5、cookie

Tornado中能夠對cookie進行操做,而且還能夠對cookie進行簽名以放置僞造。

一、基本操做

  View Code

二、加密cookie(簽名)

Cookie 很容易被惡意的客戶端僞造。加入你想在 cookie 中保存當前登錄用戶的 id 之類的信息,你須要對 cookie 做簽名以防止僞造。Tornado 經過 set_secure_cookie 和 get_secure_cookie 方法直接支持了這種功能。 要使用這些方法,你須要在建立應用時提供一個密鑰,名字爲 cookie_secret。 你能夠把它做爲一個關鍵詞參數傳入應用的設置中:

  View Code
  內部算法

簽名Cookie的本質是:

寫cookie過程:

  • 將值進行base64加密
  • 對除值之外的內容進行簽名,哈希算法(沒法逆向解析)
  • 拼接 簽名 + 加密值

讀cookie過程:

  • 讀取 簽名 + 加密值
  • 對簽名進行驗證
  • base64解密,獲取值內容

注:許多API驗證機制和安全cookie的實現機制相同。

  基於Cookie實現用戶驗證-Demo
  基於簽名Cookie實現用戶驗證-Demo

三、JavaScript操做Cookie

因爲Cookie保存在瀏覽器端,因此在瀏覽器端也可使用JavaScript來操做Cookie。

1
2
3
4
5
6
7
8
9
/*
設置cookie,指定秒數過時
  */
function  setCookie(name,value,expires){
     var  temp = [];
     var  current_date =  new  Date();
     current_date.setSeconds(current_date.getSeconds() + 5);
     document.cookie = name +  "= " + value + ";expires="  + current_date.toUTCString();
}

對於參數:

  • domain   指定域名下的cookie
  • path       域名下指定url中的cookie
  • secure    https使用

注:jQuery中也有指定的插件 jQuery Cookie 專門用於操做cookie,猛擊這裏

6、CSRF

Tornado中的誇張請求僞造和Django中的類似,跨站僞造請求(Cross-site request forgery)

  配置
  使用 - 普通表單
  使用 - AJAX

注:Ajax使用時,本質上就是去獲取本地的cookie,攜帶cookie再來發送請求

7、上傳文件

一、Form表單上傳

  HTML
  Python

二、AJAX上傳

  HTML - XMLHttpRequest
  HTML - jQuery
  HTML - iframe
  Python
  擴展:基於iframe實現Ajax上傳示例
  View Code
  其餘

 

8、驗證碼

驗證碼原理在於後臺自動建立一張帶有隨機內容的圖片,而後將內容經過img標籤輸出到頁面。

安裝圖像處理模塊:

1
pip3 install pillow

示例截圖:

驗證碼Demo源碼下載:猛擊這裏

9、異步非阻塞

一、基本使用

裝飾器 + Future 從而實現Tornado的異步非阻塞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class  AsyncHandler(tornado.web.RequestHandler):
 
     @gen .coroutine
     def  get( self ):
         future  =  Future()
         future.add_done_callback( self .doing)
         yield  future
         # 或
         # tornado.ioloop.IOLoop.current().add_future(future,self.doing)
         # yield future
 
     def  doing( self , * args,  * * kwargs):
         self .write( 'async' )
         self .finish()

當發送GET請求時,因爲方法被@gen.coroutine裝飾且yield 一個 Future對象,那麼Tornado會等待,等待用戶向future對象中放置數據或者發送信號,若是獲取到數據或信號以後,就開始執行doing方法。

異步非阻塞體如今當在Tornaod等待用戶向future對象中放置數據時,還能夠處理其餘請求。

注意:在等待用戶向future對象中放置數據或信號時,此鏈接是不斷開的。

二、同步阻塞和異步非阻塞對比

  同步阻塞
  異步非阻塞

三、httpclient類庫

Tornado提供了httpclient類庫用於發送Http請求,其配合Tornado的異步非阻塞使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
 
import  tornado.web
from  tornado  import  gen
from  tornado  import  httpclient
 
# 方式一:
class  AsyncHandler(tornado.web.RequestHandler):
     @gen .coroutine
     def  get( self * args,  * * kwargs):
         print ( '進入' )
         http  =  httpclient.AsyncHTTPClient()
         data  =  yield  http.fetch( "http://www.google.com" )
         print ( '完事' ,data)
         self .finish( '6666' )
 
# 方式二:
# class AsyncHandler(tornado.web.RequestHandler):
#     @gen.coroutine
#     def get(self):
#         print('進入')
#         http = httpclient.AsyncHTTPClient()
#         yield http.fetch("http://www.google.com", self.done)
#
#     def done(self, response):
#         print('完事')
#         self.finish('666')
 
 
 
application  =  tornado.web.Application([
     (r "/async" , AsyncHandler),
])
 
if  __name__  = =  "__main__" :
     application.listen( 8888 )
     tornado.ioloop.IOLoop.instance().start() 
  基於異步非阻塞和Tornado-MySQL實現用戶登陸示例

自定義Web組件

1、Session

一、面向對象基礎

面向對象中經過索引的方式訪問對象,須要內部實現 __getitem__ 、__delitem__、__setitem__方法

二、Tornado擴展

Tornado框架中,默認執行Handler的get/post等方法以前默認會執行 initialize方法,因此能夠經過自定義的方式使得全部請求在處理前執行操做...

三、session

session其實就是定義在服務器端用於保存用戶回話的容器,其必須依賴cookie才能實現。

  自定義Session

四、分佈式Session

  一致性哈西
  session

2、表單驗證

在Web程序中每每包含大量的表單驗證的工做,如:判斷輸入是否爲空,是否符合規則。

  HTML
  Python

因爲驗證規則能夠代碼重用,因此能夠如此定義:

  View Code