WEB開發是如今程序必會的技能,由於大部分軟件都以Web形式提供,及時製做後臺開發,或者只作前臺開發,也須要了解Web開發的概念和特色。因爲Python是解釋性腳本語言,用來作Web開發很是適合,並且Python有上百種Web開發框架,以及成熟的模板技術,使得Web開發如虎添翼。今天借用Flask框架,快速學習一下Python的Web開發知識。html
Flask的設計易於使用和擴展。它的初衷是爲各類複雜的Web應用程序構建堅實的基礎。能夠自由地插入任何擴展。也能夠自由構建本身的模塊。Flask適合各類項目。它對原型設計特別有用。Flask依賴於兩個外部庫:Jinja2模板引擎和Werkzeug WSGI工具包。Flask是最精緻,功能最豐富的微框架之一。Flask還很年輕,擁有蓬勃發展的社區,一流的擴展和漂亮的API。Flask具備快速模板,強大的WSGI功能,在Web應用程序和庫級別的完整單元可測性,以及大量文檔等優勢。選用Flask框架也是由於它方便入手,結構簡單,零配置,是個學習Python Web開發的好工具。java
像其餘模塊同樣,Flask的安裝很簡單,下面經過pip包管理器來安裝python
pip install flask
檢查一下是否安裝正確 在命令行下輸入 python
進入命令行模式 引入flask模塊 回車數據庫
>>> import flask>>>
若是沒有錯誤提醒,就說明安裝成功了json
下面寫個最簡單的Web應用 hello.py
flask
from flask import Flask # 引入Flask模塊
app = Flask(__name__) # 建立一個應用
@app.route('/')def index(): # 定義根目錄處理器 return '<h1>Hello World!</h1>' if __name__ == '__main__': app.run() # 啓動服務
打開終端,跳轉到hello.py
文件所在的文件夾,進入python命令行模式,啓動服務瀏覽器
>>> python hello.py
若是一塊兒正常的話會有相似下面的反饋服務器
* Serving Flask app "hello" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
由於是經過
app.run()
啓動的服務,因此會有個錯誤提示,提醒不能將此Web應用部署在生產環境中,能夠暫時忽略session
此時,打開瀏覽器,輸入 127.0.0.1:5000/ 或者 localhost:5000/, 就能夠看到 Hello World!歡迎字樣。數據結構
路由是Web開發中一個很重要的概念,用來將不一樣的請求,映射到響應的處理方法上,這個方法被稱爲視圖函數。好比剛纔的Hello
應用,將根請求,映射到index
處理方法上,下面簡單瞭解下Flask對路由的支持 Flask經過修飾器(和Java的註解相似)來創建路由映射關係的,已經看到修飾器是app.rotue()
如 訪問 /hello
@app.route('/hello')def hello(): return 'Hello!'
如訪問 /user/bob
或者 /user/lily
都會映射到同一視圖函數上
@app.route('/user/<name>')def user(name): return '<h1>Hello, %s! </h1>' % name
動態域名中動態的部分能夠做爲視圖函數的參數,也支持多個動態參數,如訪問 /user/bob/23
@app.route('/user/<name>/<age>')def user(name, age): return "<h1> Hello, %s, you're %s years old" % (name, age)
還能夠指定動態部分的數據類型,如
@app.route('/post/<int:post_id>')def show_post(post_id): # show the post with the given id, the id is an integer return 'Post %d' % post_id
@app.route('/path/<path:subpath>')def show_subpath(subpath): # show the subpath after /path/ return 'Subpath %s' % escape(subpath)
支持的數據類型
類型 | 說明 |
---|---|
string | (默認值) 任何不包含斜槓的文本 |
int | 正整數 |
float | 正浮點數 |
path | 相似 string ,但能夠包含斜槓 |
uuid | 接受 UUID 字符串 |
HTTP協議,支持多種HTTP 方法,例如HEAD
、OPTIONS
,以及經常使用的GET
、POST
等,Flask自動處理了HEAD
和OPTIONS
,路由默認接受的方法是GET,若是要匹配其餘請求方法,能夠在路由方法的methods
參數來指定
@app.route('/login', methods=['GET', 'POST'])def login(): if request.method == 'POST': return do_the_login() else: return show_the_login_form()
也能夠將多個路由規則,用於一個視圖函數, 如訪問/job/
和訪問 /work/
效果是同樣的
@app.route('/job/')@app.route('/work/')def show_works(): return 'This is works page'
再複雜一點的例子
@app.route('/users/', defaults={'page': 1})@app.route('/users/page/<int:page>')def show_users(page): pass
上面的代碼表示,當訪問/user/
或者 /user/page/<pageindex>
時,都會有show_users
視圖函數來處理, 並且還爲/user/
提供了默認值,即訪問/user/
至關於訪問 /user/page/1
Web應用,最重要的事情就是處理接收到的請求,並返回響應。Flask框架也同樣,它提供了請求對象request
和響應對象response
,能夠方便的在視圖函數中使用。
Flask將客戶端發送的HTTP請求封裝成了request
請求對象,而且使用上下文(context)臨時將request
變爲全局可訪問的,因而在視圖仍是中,就能夠直接使用了。
注意:
request
並不是真正的全局變量!試想,在多線程服務器中,多個線程同時處理不一樣客戶端發送的不一樣請求時,每一個線程看到的request
對象必然不一樣。Falsk使用上下文讓特定的變量在一個線程中全局可訪問,與此同時卻不會干擾其餘線程。
Flask有兩種上下文,分別爲程序上下文和請求上下文,各自對應的全局變量以下表:
變量名 | 上下文類型 | 備註 |
---|---|---|
current_app | 程序上下文 | 表示當前運行的程序實例 |
g | 程序上下文 | 處理請求時用做臨時存儲對象,每次請求都會從新設值 |
request | 請求上下文 | 客戶端發來的request請求對象 |
session | 請求上下文 | 請求攜帶的會話信息 |
使用request
對象前,須要先引入
from flash import request
request
對象提供了豐富的屬性和方法,這裏舉個例子:經過使用 method
屬性能夠操做當前請求方法,經過使用 form
屬性處理表單數據(在 POST
或者 PUT
請求 中傳輸的數據)。如下是使用上述兩個屬性的例子:
@app.route('/login', methods=['POST', 'GET'])def login(): error = None if request.method == 'POST': if valid_login(request.form['username'], request.form['password']): return log_the_user_in(request.form['username']) else: error = 'Invalid username/password' # the code below is executed if the request method # was GET or the credentials were invalid return render_template('login.html', error=error)
注意:當 form 屬性中不存在這個鍵時會發生什麼?會引起一個 KeyError 。若是不處理這個錯誤 ,就會顯示一個 HTTP 400 Bad Request 錯誤頁面。
若是要操做 URL (如 ?key=value )中提交的參數可使用 args 屬性,如 : searchword = request.args.get('key', '')
有時在處理請求以前或以後執行代碼會頗有用。例如,在請求開始時,可能須要建立數據庫鏈接或者認證發起請求的用戶。爲了不在每一個視圖函數中都使用重複的代碼,Flask提供了註冊通用函數的功能,註冊的函數可在請求被分發到視圖函數以前或以後調用。請求鉤子使用修飾器實現。Flask支持如下4種鉤子:
before_first_request
:註冊一個函數,在處理第一個請求以前運行。
before_request
:註冊一個函數,在每次請求以前運行。
after_request
:註冊一個函數,若是沒有未處理的異常拋出,在每次請求以後運行。
teardown_request
:註冊一個函數,即便有未處理的異常拋出,也在每次請求以後運行。
示例: 在接受到第一個請求是,打印一句話:
@app.before_first_requestdef first_quest(): print("run before first request")
在請求鉤子函數和視圖函數之間共享數據通常使用上下文全局變量g。例如,before_request處理程序能夠從數據庫中加載已登陸用戶,並將其保存到g.user中。隨後調用視圖函數時,視圖函數再使用g.user獲取用戶。
響應是Web服務器對請求的一個迴應,在Flask中,有多種形式的響應。視圖函數的返回值會自動轉換爲一個響應對象。若是返回值是一個字符串,那麼會被 轉換爲一個包含做爲響應體的字符串、一個 200 OK 出錯代碼 和一個 text/html
類型的響應對象。若是返回值是一個字典,那麼會調用 jsonify()
來產生一個響應。如下是轉換的規則:
若是視圖返回的是一個響應對象,那麼就直接返回它。
若是返回的是一個字符串,那麼根據這個字符串和缺省參數生成一個用於返回的 響應對象。
若是返回的是一個字典,那麼調用 jsonify
建立一個響應對象。
若是返回的是一個元組,那麼元組中的項目能夠提供額外的信息。元組中必須至少 包含一個項目,且項目應當由 (response, status)
、 (response, headers)
或者 (response, status, headers)
組成。 status
的值會重載狀態代碼, headers
是一個由額外頭部值組成的列表 或字典。
若是以上都不是,那麼 Flask 會假定返回值是一個有效的 WSGI 應用並把它轉換爲 一個響應對象。
除此以外,還能夠經過 make_response()
函數,建立能夠響應對象,作更個性的事情。
使用make_response()
前,須要先引入
from flask import make_response
示例:
響應有元組構成
@app.errorhandler(404)def not_found(error): return render_template('error.html'), 404
@app.errorhandler 修飾符,會將一個響應代碼映射到一個視圖函數上,這裏是將404(找不到頁面)碼,處理成一個個性的錯誤頁面 另外,
render_template
是Flask的模板函數,簡單理解就是格式化一個動態的html字符串,關於模板的詳細用法,會在模板章節描述
使用 make_response() 包裹返回表達式,得到響應對象,並對該對象 進行修改,而後再返回:
@app.errorhandler(404)def not_found(error): resp = make_response(render_template('error.html'), 404) resp.headers['X-Something'] = 'A value' return resp
本文藉助Flask框架,簡要介紹了下Python Web開發的基本知識和技術,但願能幫助您快速入門,在Python學習的道路上走的更順暢。後續還會將就Web開發的話題,對模板、數據庫 以及擴展功能等進行講解,敬請期待!
圖書: Flask Web開發[1]
Flask快速上手[2]
Flask入門到精通(二)[3]
Web服務器網關接口[4]
圖書: Flask Web開發: https://item.jd.com/12418677.html
[2]Flask快速上手: https://dormousehole.readthedocs.io/en/latest/quickstart.html
[3]Flask入門到精通(二): https://www.cnblogs.com/java-wgm/p/6602900.html
[4]Web服務器網關接口: https://zh.wikipedia.org/wiki/Web%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3
系列文章
第11天:Python 字典