[TOC]
### 引入
了解了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框架來做。
由于用Python開發一個Web框架十分容易,所以Python有上百個開源的Web框架。這里我們先不討論各種Web框架的優缺點,直接選擇一個比較流行的Web框架——`Flask`來使用。
### 安裝 Flask
用`Flask`編寫Web App比WSGI接口簡單(這不是廢話么,要是比WSGI還復雜,用框架干嘛?),我們先用`pip`安裝`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`上監聽:
~~~
$ python app.py
* Running on http://127.0.0.1:5000/
~~~
打開瀏覽器,輸入首頁地址http://localhost:5000/ :

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

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

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

實際的Web App應該拿到用戶名和口令后,去數據庫查詢再比對,來判斷用戶是否能登錄成功。
### 其他框架
除了Flask,常見的Python Web框架還有:
- [Django](https://www.djangoproject.com/):全能型Web框架;
- [web.py](http://webpy.org/):一個小巧的Web框架;
- [Bottle](http://bottlepy.org/):和Flask類似的Web框架;
- [Tornado](http://www.tornadoweb.org/en/stable/):Facebook的開源異步Web框架。
當然了,因為開發Python的Web框架也不是什么難事,我們后面也會講到開發Web框架的內容。
### 小結
- 有了Web框架,我們在編寫Web應用時,注意力就從WSGI處理函數轉移到URL+對應的處理函數,這樣,編寫Web App就更加簡單了。
- 在編寫URL處理函數時,除了配置URL外,從HTTP請求拿到用戶數據也是非常重要的。Web框架都提供了自己的API來實現這些功能。Flask通過request.form['name']來獲取表單的內容。
- Python教程
- Python簡介
- 安裝Python
- Python解釋器
- 第一個 Python 程序
- 使用文本編輯器
- Python代碼運行助手
- 輸入和輸出
- 源碼
- learning.py
- Python基礎
- 數據類型和變量
- 字符串和編碼
- 使用list和tuple
- 條件判斷
- 循環
- 使用dict和set
- 函數
- 調用函數
- 定義函數
- 函數的參數
- 遞歸函數
- 高級特性
- 切片
- 迭代
- 列表生成式
- 生成器
- 迭代器
- 函數式編程
- 高階函數
- map/reduce
- filter
- sorted
- 返回函數
- 匿名函數
- 裝飾器
- 偏函數
- Python函數式編程——偏函數(來自博客)
- 模塊
- 使用模塊
- 安裝第三方模塊
- 面向對象編程
- 類和實例
- 訪問限制
- 繼承和多態
- 獲取對象信息
- 實例屬性和類屬性
- 面向對象高級編程
- 使用__slots__
- 使用@property
- 多重繼承
- 定制類
- 使用枚舉類
- 使用元類
- 錯誤、調試和測試
- 錯誤處理
- 調試
- 單元測試
- 文檔測試
- IO編程
- 文件讀寫
- StringIO和BytesIO
- 操作文件和目錄
- 序列化
- 進程和線程
- 多進程
- 多線程
- ThreadLocal
- 進程 vs. 線程
- 分布式進程
- 正則表達式
- 常用內建模塊
- datetime
- collections
- base64
- struct
- hashlib
- itertools
- contextlib
- XML
- HTMLParser
- urllib
- 常用第三方模塊
- PIL
- virtualenv
- 圖形界面
- 網絡編程
- TCP/IP簡介
- TCP編程
- UDP編程
- 電子郵件
- SMTP發送郵件
- POP3收取郵件
- 訪問數據庫
- 使用SQLite
- 使用MySQL
- 使用SQLAlchemy
- Web開發
- HTTP協議簡介
- HTML簡介
- WSGI接口
- 使用Web框架
- 使用模板
- 異步IO
- 協程
- asyncio
- async/await
- aiohttp
- 實戰
- Day 1 - 搭建開發環境
- Day 2 - 編寫Web App骨架
- Day 3 - 編寫ORM
- Day 4 - 編寫Model
- Day 5 - 編寫Web框架
- Day 6 - 編寫配置文件
- Day 7 - 編寫MVC
- Day 8 - 構建前端
- Day 9 - 編寫API
- Day 10 - 用戶注冊和登錄
- Day 11 - 編寫日志創建頁
- Day 12 - 編寫日志列表頁
- Day 13 - 提升開發效率
- Day 14 - 完成Web App
- Day 15 - 部署Web App
- Day 16 - 編寫移動App
- FAQ
- 期末總結