初見Flask

flask簡述

Flask 是一個基於 Python 開發而且依賴 jinja2 模板和 Werkzeug WSGI 服務的一個微型框架,對於 Werkzeug 本質是 Socket 服務端,其用於接收 http 請求並對請求進行預處理,而後觸發 Flask 框架,開發人員基於 Flask 框架提供的功能對請求進行相應的處理,並返回給用戶,若是要返回給用戶複雜的內容時,須要藉助 jinja2 模板來實現對模板的處理,將模板和數據進行渲染,將渲染後的字符串返回給用戶瀏覽器。python

「微」 (micro) 並不表示你須要把整個 Web 應用塞進單個 Python 文件(雖然確實能夠),也不意味着 Flask 在功能上有所欠缺。微框架中的「微」意味着 Flask 旨在保持核心簡單而易於擴展。git

默認狀況下,Flask 不包含數據庫抽象層、表單驗證,或是其它任何已有多種庫能夠勝任的功能。然而,Flask 支持用擴展來給應用添加這些功能,如同是 Flask 自己實現的同樣。衆多的擴展提供了數據庫集成、表單驗證、上傳處理、各類各樣的開放認證技術等功能。Flask 也許是「微小」的,但它已準備好在需求繁雜的生產環境中投入使用。github

搭建開發環境

pipenv 是基於 pip 的 Python 的包管理工具,它和 pip 的用法很類似,能夠看做是 pip 的增強版,它的出現解決了舊的 pip+virtualenv+requirements.txt 的工做方式的弊端。能夠說 pipenv 是 pip、pipfile、virtualenv 的結合體,它讓包安裝、包依賴管理和虛擬環境管理更加方便,使用它能夠實現高效的 Python 項目開發工做流。shell

安裝

在 Linux 或 macOS 系統中使用 sudo 以全局安裝:數據庫

sudo pip install pipenv

查看pipenv版本號:flask

pipenv --version

建立虛擬環境

在 Python 中,虛擬環境(virtual enviroment)就是隔離的 Python 解釋器環境。經過建立虛擬環境,你能夠擁有一個獨立的 Python 解釋器環境。這樣作的好處是能夠爲每個項目建立獨立的Python解釋器環境,由於不一樣的項目經常會依賴不一樣版本的庫或 Python 版本。使用虛擬環境能夠保持全局 Python 解釋器環境的乾淨,避免包和版本的混亂,而且能夠方便地區分和記錄每一個項目的依賴,以便在新環境下復現依賴環境。
用如下命令爲當前的項目建立虛擬環境:瀏覽器

pipenv install

虛擬環境的目錄

這會爲當前項目建立一個文件夾,其中包含隔離的 Python 解釋器環境,而且安裝 pip、wheel、setuptools 等基本的包。若是是下載的已經寫好的程序,而且裏面包含 Pipfile 文件,那麼這個文件中列出的依賴包,會在這個命令執行時一併被安裝。默認狀況下,Pipenv 會統一管理全部虛擬環境。在 Windows 系統中,虛擬環境文件夾會在 C:\Users\Administrator\.virtualenvs\ 目錄下建立;在 Linux 或 macOS 會在 ~/.local/share/virtualenvs/ 目錄下建立。若是你想在項目目錄內建立虛擬環境文件夾,能夠設置環境變量安全

PIPENV_VENV_IN_PROJECT = True

這時名爲 .venv 的虛擬環境文件夾將在項目根目錄被建立。固然咱們能夠經過--three和--two選項來聲明虛擬環境中使用的 Python 版本(分別對應Python3和Python2),或是使用--python選項指定具體的版本號。同時要確保對應版本的Python已經安裝在電腦中。用如下命令顯示激活虛擬環境:服務器

pipenv shell

當執行 pipenv shellpipenv run 命令時,Pipenv 會自動從項目目錄下的 .env 文件中加載環境變量。Pipenv會啓動一個激活虛擬環境的子 shell ,如今你會發現命令行提示符前添加了虛擬環境名「(虛擬環境名稱)$」,好比:app

(helloflask-5Pa0ZfZw) $

這說明咱們已經成功激活了虛擬環境,如今你的全部命令都會在虛擬環境中執行。當你須要退出虛擬環境時,使用 exit 命令。除了顯式地激活虛擬環境,Pipenv 還提供了一個神奇的命令,容許你不顯式激活虛擬環境便可在當前項目的虛擬環境中執行命令,好比:

pipenv run python hello.py

這會使用虛擬環境中的Python解釋器,而不是全局的Python解釋器。事實上,和顯式激活/關閉虛擬環境的傳統方式相比,pipenv run是更推薦的作法,由於這個命令可讓你在執行操做時不用關心本身是否激活了虛擬環境。

依賴管理

在建立虛擬環境時,若是項目根目錄下沒有 Pipfile 文件,pipenv install 命令還會在項目文件夾根目錄下建立PipfilePipfile.lock 文件,前者用來記錄項目依賴包列表,然後者記錄了固定版本的詳細依賴包列表。當咱們使用 Pipen 安裝/刪除/更新依賴包時,Pipfile 以及 Pipfile.lock 會自動更新。你可使用 pipenv graph 命令查看當前環境下的依賴狀況,或是在虛擬環境中使用 pip list 命令查看依賴列表。當須要在一個新的環境運行程序時,只須要執行 pipenv install 命令。Pipenv 就會建立一個新的虛擬環境,而後自動從 Pipfile 中讀取依賴並安裝到新建立的虛擬環境中。

Pipenv 會自動幫咱們管理虛擬環境,因此在執行 pipenv install 安裝 Python 包時,不管是否激活虛擬環境,包都會安裝到虛擬環境中。後面咱們都將使用 Pipenv 安裝包,這至關於在激活虛擬環境的狀況下使用 pip 安裝包。只有須要在全局環境下安裝/更新/刪除包,咱們纔會使用pip。

建立 flask 程序

最小的flask程序在此

from flask import Flask
app  = Flask(__name__)

@app.route('/')
def hello():
    return "<h1>hello flask</h1>"

建立程序實例

from flask import Flask
app = Flask(__name__)

傳入構造方法的第一個參數是模塊或包的名稱,咱們應該使用特殊變量 __name__ 。Python 會根據所處的模塊來賦予 name 變量相應的值,對於咱們的程序來講(app.py),這個值爲 app 。除此以外,這也會幫助 Flask 在相應的文件夾裏找到須要的資源,好比模板和靜態文件。

註冊路由

@app.route('/')
def hello():
    return "<h1>hello flask</h1>"

在一個 Web 應用裏,客戶端和服務器上的 Flask 程序的交互能夠簡單歸納爲如下幾步:

  1. 用戶在瀏覽器輸入 URL 訪問某個資源。
  2. Flask 接收用戶請求並分析請求的 URL。
  3. 爲這個 URL 找到對應的處理函數。
  4. 執行函數並生成響應,返回給瀏覽器。
  5. 瀏覽器接收並解析響應,將信息顯示在頁面中。

在上面這些步驟中,大部分都由 Flask 完成,咱們要作的只是創建處理請求的函數,併爲其定義對應的 URL 規則。只需爲函數附加 app.route() 裝飾器,並傳入 URL 規則做爲參數,咱們就可讓 URL 與函數創建關聯。這個過程咱們稱爲註冊路由 (route),路由負責管理 URL 和函數之間的映射,而這個函數則被稱爲視圖函數 (view function)。route() 裝飾器的第一個參數是 URL 規則,用字符串表示,必須以斜槓(/)開始。這裏的 URL 是相對 URL(又稱爲內部 URL ),即不包含域名的 URL。

爲視圖函數綁定多個 URL

一個視圖函數能夠綁定多個 URL,好比下面的代碼把 /hi 和 /hello 都綁定到 say_hello() 函數上,這就會爲 say_hello 視圖註冊兩個路由,用戶訪問這兩個 URL 均會觸發 say_hello() 函數,得到相同的響應。

@app.route('/')
@app.route('/hello')
def index():
    return "hello world"

爲視圖函數綁定動態 URL

在 URL 規則中添加變量部分,使用「<變量名>」的形式表示。Flask 處理請求時會把變量傳入視圖函數,因此咱們能夠添加參數獲取這個變量值。

@app.route('/greet/<name>')
def index(name):
    return "hello,{}".format(name)

由於 URL 中能夠包含變量,因此咱們將傳入 app.route() 的字符串稱爲 URL 規則,而不是 URL。Flask 會解析請求並把請求的URL與視圖函數的URL規則進行匹配。好比,這個 index 視圖的 URL 規則爲 '/greet/<name>',那麼相似 /greet/foo、/greet/bar 的請求都會觸發這個視圖函數。還能夠設置默認值,這樣即便不輸入 name 的值訪問也不會 404

啓動開發服務器

Flask 內置了一個簡單的開發服務器(由依賴包 Werkzeug 提供), 足夠在開發和測試階段使用。Flask 經過依賴包 Click 內置了一個 CLI(Command Line Interface,命令行交互界面)系統。當咱們安裝 Flask 後,會自動添加一個 flask 命令腳本,咱們能夠經過 flask 命令執行內置命令、擴展提供的命令或是咱們本身定義的命令。其中,flask run 命令用來啓動內置的開發服務器。

pipenv run flask run

自動發現程序

通常來講,在執行 flask run 命令運行程序前,咱們須要提供程序實例所在模塊的位置。咱們在上面能夠直接運行程序,是由於 Flask 會自動探測程序實例,自動探測存在下面這些規則:

  • 從當前目錄尋找 app.pywsgi.py 模塊,並從中尋找名爲 app 或 application 的程序實例。
  • 從環境變量 FLASK_APP 對應的值尋找名爲 app 或 application 的程序實例。

由於咱們的程序主模塊命名爲 app.py,因此 flask run 命令會自動在其中尋找程序實例。若是你的程序主模塊是其餘名稱,好比 hello.py,那麼須要設置環境變量 FLASK_APP,將包含程序實例的模塊名賦值給這個變量。Linux 或 macOS 系統使用 export 命令:

export FLASK_APP=hello

管理環境變量

Flask的自動發現程序實例機制還有第三條規則:若是安裝了 python-dotenv,那麼在使用 flask run 或其餘命令時會使用它自動從 .flaskenv 文件和 .env 文件中加載環境變量。當安裝了 python-dotenv 時,Flask 在加載環境變量的優先級是:
手動設置的環境變量>.env 中設置的環境變量>.flaskenv 設置的環境變量。
除了 FLASK_APP,在後面咱們還會用到其餘環境變量。環境變量在新建立命令行窗口或重啓電腦後就清除了,每次都要重設變量有些麻煩。並且若是你同時開發多個 Flask 程序,這個 FLASK_APP 就須要在不一樣的值之間切換。爲了不頻繁設置環境變量,咱們可使用 python-dotenv 管理項目的環境變量,首先使用 Pipenv 將它安裝到虛擬環境:

pipenv install python-dotenv

咱們在項目根目錄下分別建立兩個文件:.env 和 .flaskenv。.flaskenv 用來存儲和 Flask 相關的公開環境變量,好比 FLASK_APP;而 .env 用來存儲包含敏感信息的環境變量,好比後面咱們會用來配置 Email 服務器的帳戶名與密碼。在 .flaskenv 或 .env 文件中,環境變量使用鍵值對的形式定義,每行一個以#開頭的爲註釋。.env 包含敏感信息,除非是私有項目,不然絕對不能提交到 Git 倉庫中。當你開發一個新項目時,記得把它的名稱添加到 .gitignore 文件中, 這會告訴 Git 忽略這個文件。gitignore 文件是一個名爲 .gitignore 的文本文件,它存儲了項目中 Git 提交時的忽略文件規則清單。Python項目的.gitignore模板

更多啓動選項

使服務器外部可見

在上面啓動的 Web 服務器默認是對外不可見的,能夠在 run 命令後添加 --host 選項將主機地址設爲 0.0.0.0 使其對外可見

flask run --host=0.0.0.0

內網穿透工具

改變默認端口

Flask 提供的 Web 服務器默認監聽 5000 端口,你能夠在啓動時傳入參數來改變它

flask run --port=8000

執行 flask run 命令時的 host 和 port 選項也能夠經過環境變量 FLASK_RUN_HOSTFLASK_RUN_PORT 設置。事實上,Flask 內置的命令均可以使用這種模式定義默認選項值,即 「FLASK_<COMMAND>_<OPTION>」,你可使用 flask--help 命令查看全部可用的命令。

設置運行環境

開發環境(development enviroment)和生產環境(production enviroment)是咱們會頻繁接觸到的概念。
開發環境是指咱們在本地編寫和測試程序時的計算機環境,
而生產環境與開發環境相對,它指的是網站部署上線供用戶訪問時的服務器環境。
根據運行環境的不一樣,Flask 程序、擴展以及其餘程序會改變相應的行爲和設置。爲了區分程序運行環境,Flask 提供了一個 FLASK_ENV 環境變量用來設置環境,默認爲 production 。在開發時,咱們能夠將其設爲 development ,這會開啓全部支持開發的特性。爲了方便管理,咱們將把環境變量 FLASK_ENV 的值寫入 .flaskenv 文件中:

FLASK_ENV=development

在開發環境下,調試模式(Debug Mode)將被開啓,這時執行 flask run 啓動程序會自動激活 Werkzeug 內置的調試器(debugger)和重載器(reloader),它們會爲開發帶來很大的幫助。若是你想單獨控制調試模式的開關,能夠經過 FLASK_DEBUG 環境變量設置,設爲 1 則開啓,設爲 0 則關閉,不過一般不推薦手動設置這個值。
在生產環境中部署程序時,毫不能開啓調試模式。儘管 PIN 碼能夠避免用戶任意執行代碼,提升攻擊者利用調試器的難度,但並不能確保調試器徹底安全,會帶來巨大的安全隱患。並且攻擊者可能會經過調試信息獲取你的數據庫結構等容易帶來安全問題的信息。另外一方面,調試界面顯示的錯誤信息也會讓普通用戶感到困惑。
當在一個新電腦建立運行環境時,使用 pipenv install 命令時須要添加額外的 --dev 選項纔會安裝 dev-packages 部分定義的開發依賴包。

項目配置

在Flask中,配置變量就是一些大寫形式的 Python 變量,你也能夠稱之爲配置參數或配置鍵。使用統一的配置變量能夠避免在程序中以硬編碼(hard coded)的形式設置程序。在一個項目中,你會用到許多配置:Flask 提供的配置,擴展提供的配置,還有程序特定的配置。和平時使用變量不一樣,這些配置變量都經過 Flask 對象的 app.config 屬性做爲統一的接口來設置和獲取,它指向的 Config 類其實是字典的子類,因此你能夠像操做其餘字典同樣操做它。

app.config['ADMIN_NAME']='Eric'

配置的名稱必須是全大寫形式,小寫的變量將不會被讀取。使用 update() 方法則能夠一次加載多個值:

app.config.update(
    TESTING1=True
    TESTING2=flase
)

和操做字典同樣,讀取一個配置就是從config字典裏經過將配置變量的名稱做爲鍵讀取對應的值:

value = app.config['ADMIN_NAME']

URL與端點

在 Web 程序中,URL 無處不在。若是程序中的 URL 都是以硬編碼的方式寫出,那麼將會大大下降代碼的易用性。好比,當你修改了某個路由的URL 規則,那麼程序裏對應的 URL 都要一個一個進行修改。更好的解決辦法是使用 Flask 提供的 url_for() 函數獲取 URL,當路由中定義的 URL 規則被修改時,這個函數總會返回正確的 URL。調用 url_for() 函數時,第一個參數爲端點(endpoint)值。在 Flask 中,端點用來標記一個視圖函數以及對應的 URL 規則。

@app.route('/')
def index():
    return "hello flask"

這個路由的端點即視圖函數的名稱 index,調用 url_for('index')便可獲取對應的 URL,即「/」。
若是 URL 含有動態部分,那麼咱們須要在 url_for() 函數裏傳入相應的參數,如下面的視圖函數爲例:

@app.route('/hello/<name>')
def index(name):
    return "hello {}".format(name)

這時使用 url_for('say_hello',name='Jack')獲得的 URL 爲「/hello/Jack」。
咱們使用 url_for()函數生成的 URL 是相對 URL(即內部URL), 即URL中的path部分,好比「/hello」,不包含根URL。相對URL只能在程序內部使用。若是你想要生成供外部使用的絕對 URL,能夠在使用 url_for()函數時,將 _external 參數設爲 True,這會生成完整的 URL, 好比 http://helloflask.com/hello,在本地運行程序時則會得到 http://localhost:5000/hello。

Flask 命令

除了 Flask 內置的 flask run 等命令,咱們也能夠自定義命令。在虛擬環境安裝 Flask 後,包含許多內置命令的 flask 腳本就可使用了。在前面咱們已經接觸了不少 flask 命令,好比運行服務器的 flask run,啓動 shell 的 flask shell。經過建立任意一個函數,併爲其添加 app.cli.command() 裝飾器, 咱們就能夠註冊一個 flask 命令。hello() 命令函數,在函數中咱們仍然只是打印一行問候。

@app.cli.command() 
def hello():
    click.echo("hello,flask")

函數的名稱即爲命令名稱,這裏註冊的命令即 hello,你可使用 flask hello 命令來觸發函數。做爲替代,你也能夠在 app.cli.command() 裝飾器中傳入參數來設置命令名稱,好比 app.cli.command('hello'), 會把命令名稱設置爲hello,完整的命令即flask hello。

相關文章
相關標籤/搜索