python6---WSGI接口和web框架flask

WSGI接口定義非常簡單,它只要求Web開發者實現一個函數,就可以響應HTTP請求。我們來看一個最簡單的Web版本的“Hello, web!”:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']

上面的application()函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:

  • environ:一個包含所有HTTP請求信息的dict對象;

  • start_response:一個發送HTTP響應的函數。

start_response('200 OK', [('Content-Type', 'text/html')])發送了HTTP響應的Header,注意Header只能發送一次,也就是隻能調用一次start_response()函數。start_response()函數接收兩個參數,一個是HTTP響應碼,一個是一組list表示的HTTP Header,每個Header用一個包含兩個strtuple表示。

運行WSGI服務

我們先編寫hello.py,實現Web應用程序的WSGI處理函數:

# hello.py

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, web!</h1>']

然後,再編寫一個server.py,負責啓動WSGI服務器,加載application()函數:

# server.py
# 從wsgiref模塊導入:
from wsgiref.simple_server import make_server
# 導入我們自己編寫的application函數:
from hello import application

# 創建一個服務器,IP地址爲空,端口是8000,處理函數是application:
httpd = make_server('', 8000, application)
print('Serving HTTP on port 8000...')
# 開始監聽HTTP請求:
httpd.serve_forever()

確保以上兩個文件在同一個目錄下,然後在命令行輸入python server.py來啓動WSGI服務器,啓動成功後,打開瀏覽器,輸入http://localhost:8000/,就可以看到結果了:

如果你覺得這個Web應用太簡單了,可以稍微改造一下,從environ裏讀取PATH_INFO,這樣可以顯示更加動態的內容:

# hello.py

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'web')
    return [body.encode('utf-8')]

使用Web框架flask

瞭解了WSGI框架,我們發現:其實一個Web App,就是寫一個WSGI的處理函數,針對每個HTTP請求進行響應。

但是如何處理HTTP請求不是問題,問題是如何處理100個不同的URL。

每一個URL可以對應GET和POST請求,當然還有PUT、DELETE等請求,但是我們通常只考慮最常見的GET和POST請求。

一個最簡單的想法是從environ變量裏取出HTTP請求的信息,然後逐個判斷:

def application(environ, start_response):
    method = environ['REQUEST_METHOD']
    path = environ['PATH_INFO']
    if method=='GET' and path=='/':
        return handle_home(environ, start_response)
    if method=='POST' and path='/signin':
        return handle_signin(environ, start_response)
    ...

只是這麼寫下去代碼是肯定沒法維護了。

代碼這麼寫沒法維護的原因是因爲WSGI提供的接口雖然比HTTP接口高級了不少,但和Web App的處理邏輯比,還是比較低級,我們需要在WSGI接口之上能進一步抽象,讓我們專注於用一個函數處理一個URL,至於URL到函數的映射,就交給Web框架來做。

安裝Flask:

>>> pip install flask

然後寫一個app.py,處理3個URL,分別是:

  • GET /:首頁,返回Home

  • GET /signin:登錄頁,顯示登錄表單;

  • POST /signin:處理登錄表單,顯示登錄結果。

注意噢,同一個URL/signin分別有GET和POST兩種請求,映射到兩個處理函數中。Flask通過Python的裝飾器在內部自動地把URL和函數給關聯起來,所以,我們寫出來的代碼就像這樣:

from flask import Flask
from flask import request

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def home():
    return '<h1>Home</h1>'

@app.route('/signin', methods=['GET'])
def signin_form():
    return '''<form action="/signin" method="post">
              <p><input name="username"></p>
              <p><input name="password" type="password"></p>
              <p><button type="submit">Sign In</button></p>
              </form>'''

@app.route('/signin', methods=['POST'])
def signin():
    # 需要從request對象讀取表單內容:
    if request.form['username']=='admin' and request.form['password']=='password':
        return '<h3>Hello, admin!</h3>'
    return '<h3>Bad username or password.</h3>'

if __name__ == '__main__':
    app.run()

 運行python app.py,Flask自帶的Server在端口5000上監聽,打開瀏覽器,輸入首頁地址http://localhost:5000/

首頁顯示正確!再在瀏覽器地址欄輸入http://localhost:5000/signin,會顯示登錄表單:

輸入預設的用戶名admin和口令password,登錄成功:

輸入其他錯誤的用戶名和口令,登錄失敗:

實際的Web App應該拿到用戶名和口令後,去數據庫查詢再比對,來判斷用戶是否能登錄成功。

除了Flask,常見的Python Web框架還有:

  • Django:全能型Web框架;

  • web.py:一個小巧的Web框架;

  • Bottle:和Flask類似的Web框架;

  • Tornado:Facebook的開源異步Web框架。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章