Flask 快速指南

2019-07-03 09:58 更新

Flask - 概述

什么是Web框架?

Web應(yīng)用程序框架或簡單的Web框架表示一組庫和模塊,使Web應(yīng)用程序開發(fā)人員能夠編寫應(yīng)用程序,而不必擔心協(xié)議,線程管理等低級細節(jié)。

什么是Flask?

Flask是一個用Python編寫的Web應(yīng)用程序框架。它由Armin Ronacher開發(fā),他領(lǐng)導(dǎo)一個名為Pocco的國際Python愛好者團體。Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。兩者都是Pocco項目。

WSGI

Web服務(wù)器網(wǎng)關(guān)接口(WSGI)已被用作Python Web應(yīng)用程序開發(fā)的標準。WSGI是Web服務(wù)器和Web應(yīng)用程序之間通用接口的規(guī)范。

Werkzeug

它是一個WSGI工具包,它實現(xiàn)了請求,響應(yīng)對象和其他實用函數(shù)。這使得能夠在其上構(gòu)建Web框架。Flask框架使用Werkzeug作為其基礎(chǔ)之一。

Jinga2

Jinja2是Python的一個流行的模板引擎。Web模板系統(tǒng)將模板與特定數(shù)據(jù)源組合以呈現(xiàn)動態(tài)網(wǎng)頁。

Flask通常被稱為微框架。它旨在保持應(yīng)用程序的核心簡單而可擴展。Flask沒有用于數(shù)據(jù)庫處理的內(nèi)置抽象層,也沒有形成驗證支持。相反,F(xiàn)lask支持擴展以向應(yīng)用程序添加此類功能。一些流行的Flask擴展將在本教程后面討論。

Flask - 環(huán)境

安裝Flask通常需要Python 2.6或更高版本。雖然Flask及其依賴項適用于Python 3(Python 3.3以后版本),但是許多Flask擴展不能正確支持它。因此,建議在Python 2.7上安裝Flask。

為開發(fā)環(huán)境安裝virtualenv

virtualenv是一個虛擬的Python環(huán)境構(gòu)建器。它幫助用戶并行創(chuàng)建多個Python環(huán)境。因此,它可以避免不同版本的庫之間的兼容性問題。

以下命令用于安裝virtualenv:

pip install virtualenv

此命令需要管理員權(quán)限。您可以在Linux / Mac OS上的 pip 之前添加 sudo 。如果您使用的是Windows,請以管理員身份登錄。在Ubuntu上, virtualenv可以使用它的包管理器安裝。

Sudo apt-get install virtualenv

安裝后,將在文件夾中創(chuàng)建新的虛擬環(huán)境。

mkdir newproj
cd newproj
virtualenv venv

要在 Linux / OS X 上激活相應(yīng)的環(huán)境,請使用以下命令:

venv/bin/activate

要在 Windows 上激活相應(yīng)的環(huán)境,可以使用以下命令:

venv\scripts\activate

我們現(xiàn)在準備在這個環(huán)境中安裝Flask:

pip install Flask

上述命令可以直接運行,不需要系統(tǒng)范圍安裝的虛擬環(huán)境。

Flask - 應(yīng)用

為了測試 Flask 安裝,請在編輯器中將以下代碼輸入 Hello.py:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
   return 'Hello World’

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

必須在項目中導(dǎo)入Flask模塊。Flask類的一個對象是我們的WSGI應(yīng)用程序。

Flask構(gòu)造函數(shù)使用當前模塊(__name __)的名稱作為參數(shù)。

Flask類的route()函數(shù)是一個裝飾器,它告訴應(yīng)用程序哪個URL應(yīng)該調(diào)用相關(guān)的函數(shù)。

app.route(rule, options)
  • rule 參數(shù)表示與該函數(shù)的URL綁定。

  • options 是要轉(zhuǎn)發(fā)給基礎(chǔ)Rule對象的參數(shù)列表。

在上面的示例中,'/ ' URL與hello_world()函數(shù)綁定。因此,當在瀏覽器中打開web服務(wù)器的主頁時,將呈現(xiàn)該函數(shù)的輸出。

最后,F(xiàn)lask類的run()方法在本地開發(fā)服務(wù)器上運行應(yīng)用程序。

app.run(host, port, debug, options)

所有參數(shù)都是可選的

序號參數(shù)與描述
1

host

要監(jiān)聽的主機名。 默認為127.0.0.1(localhost)。設(shè)置為“0.0.0.0”以使服務(wù)器在外部可用

2

port

默認值為5000

3

debug

默認為false。 如果設(shè)置為true,則提供調(diào)試信息

4

options

要轉(zhuǎn)發(fā)到底層的Werkzeug服務(wù)器。

上面給出的Python腳本是從Python shell執(zhí)行的。

Python Hello.py

Python shell中的消息通知您:

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

在瀏覽器中打開上述URL(localhost:5000)。將顯示“Hello World”消息。

調(diào)試模式

通過調(diào)用run()方法啟動Flask應(yīng)用程序。但是,當應(yīng)用程序正在開發(fā)中時,應(yīng)該為代碼中的每個更改手動重新啟動它。為避免這種不便,請啟用調(diào)試支持。如果代碼更改,服務(wù)器將自行重新加載。它還將提供一個有用的調(diào)試器來跟蹤應(yīng)用程序中的錯誤(如果有的話)。

在運行或?qū)⒄{(diào)試參數(shù)傳遞給run()方法之前,通過將application對象的debug屬性設(shè)置為True來啟用Debug模式。

app.debug = True
app.run()
app.run(debug = True)

燒瓶 - 路由

現(xiàn)代Web框架使用路由技術(shù)來幫助用戶記住應(yīng)用程序URL。 可以直接訪問所需的頁面,而無需從主頁導(dǎo)航。

Flask中的 route()裝飾器用于將URL綁定到函數(shù)。 例如 -

@app.route(‘/hello’)
def hello_world():
   return ‘hello world’

這里,URL \'/ hello\'規(guī)則綁定到 hello_world()函數(shù)。 因此,如果用戶訪問 http:// localhost:5000 / hello URL, hello_world()函數(shù)的輸出將在瀏覽器中呈現(xiàn)。

應(yīng)用程序?qū)ο蟮?strong> add_url_rule()函數(shù)也可用于使用函數(shù)綁定URL,如上例所示,使用 route()

裝飾者的目的也由以下表示 -

def hello_world():
   return ‘hello world’
app.add_url_rule(‘/’, ‘hello’, hello_world)

Flask - 變量規(guī)則

可以通過向規(guī)則參數(shù)添加可變部分來動態(tài)構(gòu)建URL。 此可變部分標記為< variable-name> 它作為關(guān)鍵字參數(shù)傳遞到與規(guī)則相關(guān)聯(lián)的函數(shù)。

在以下示例中, route()裝飾器的規(guī)則參數(shù)包含附加到URL \'/ hello\'< name> 因此,如果在瀏覽器中輸入 http:// localhost:5000 / hello / TutorialsPoint 作為 URL ,則\'TutorialPoint\' 提供給 hello()函數(shù)作為參數(shù)。

from flask import Flask
app = Flask(__name__)

@app.route('/hello/<name>')
def hello_name(name):
   return 'Hello %s!' % name

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

將上述腳本保存為 hello.py 并從Python shell運行它。 接下來,打開瀏覽器并輸入URL http:// localhost:5000 / hello / TutorialsPoint。

以下輸出將在瀏覽器中顯示。

Hello TutorialsPoint!

除了默認字符串變量部分之外,還可以使用以下轉(zhuǎn)換器構(gòu)建規(guī)則:

Sr.No轉(zhuǎn)換器 描述
1

int

接受整數(shù)

2

float

浮點值

3

路徑

接受用作目錄分隔符的斜杠

在下面的代碼中,使用所有這些構(gòu)造函數(shù)。

from flask import Flask
app = Flask(__name__)

@app.route('/blog/<int:postID>')
def show_blog(postID):
   return 'Blog Number %d' % postID

@app.route('/rev/<float:revNo>')
def revision(revNo):
   return 'Revision Number %f' % revNo

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

從Python Shell運行上面的代碼。 訪問瀏覽器中的網(wǎng)址 http:// localhost:5000 / blog / 11

給定的數(shù)字用作 show_blog()函數(shù)的參數(shù)。 瀏覽器顯示以下輸出 -

Blog Number 11

在瀏覽器中輸入此網(wǎng)址 - http:// localhost:5000 / rev / 1.1

revision()函數(shù)將浮點數(shù)作為參數(shù)。 以下結(jié)果顯示在瀏覽器窗口中 -

Revision Number 1.100000

Flask的URL規(guī)則基于 Werkzeug的路由模塊。 這確保形成的URL是唯一的,并基于Apache規(guī)定的先例。

考慮以下腳本中定義的規(guī)則 -

from flask import Flask
app = Flask(__name__)

@app.route('/flask')
def hello_flask():
   return 'Hello Flask'

@app.route('/python/')
def hello_python():
   return 'Hello Python'

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

這兩個規(guī)則看起來類似,但在第二個規(guī)則中,使用尾部斜杠(/)。 因此,它成為一個規(guī)范的URL。 因此,使用 / python / python / 返回相同的輸出。 但是,如果是第一個規(guī)則, / flask / 網(wǎng)址會產(chǎn)生 404未找到 頁。

Flask - URL構(gòu)建

url_for()函數(shù)對于動態(tài)構(gòu)建特定函數(shù)的URL非常有用。 該函數(shù)接受函數(shù)的名稱作為第一個參數(shù),以及一個或多個關(guān)鍵字參數(shù),每個參數(shù)對應(yīng)于URL的可變部分。

以下腳本演示了如何使用 url_for()函數(shù)。

from flask import Flask, redirect, url_for
app = Flask(__name__)

@app.route('/admin')
def hello_admin():
   return 'Hello Admin'

@app.route('/guest/<guest>')
def hello_guest(guest):
   return 'Hello %s as Guest' % guest

@app.route('/user/<name>')
def hello_user(name):
   if name =='admin':
      return redirect(url_for('hello_admin'))
   else:
      return redirect(url_for('hello_guest',guest = name))

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

上述腳本有一個函數(shù) user(name),它接受來自URL的參數(shù)的值。

User()函數(shù)檢查接收的參數(shù)是否與\'admin\'匹配。 如果匹配,則使用 url_for()將應(yīng)用程序重定向到 hello_admin()函數(shù),否則將 hello_guest 參數(shù)作為guest參數(shù)。

保存上面的代碼并從Python shell運行。

打開瀏覽器并輸入網(wǎng)址為 - http:// localhost:5000 / hello / admin

在瀏覽器中的應(yīng)用程序響應(yīng)是 -

Hello Admin

在瀏覽器中輸入以下網(wǎng)址 - http:// localhost:5000 / hello / mvl

應(yīng)用程序響應(yīng)現(xiàn)在更改為 -

Hello mvl as Guest

Flask - HTTP方法

Http協(xié)議是萬維網(wǎng)中數(shù)據(jù)通信的基礎(chǔ)。 在此協(xié)議中定義了從指定的URL檢索不同的數(shù)據(jù)方法。

下表總結(jié)了不同的http方法 -

Sr.No方法&amp; 描述
1

GET

以未加密的形式將數(shù)據(jù)發(fā)送到服務(wù)器。 最常用的方法。

2

HEAD

和GET一樣,但沒有響應(yīng)體

3

POST

用于將HTML表單數(shù)據(jù)發(fā)送到服務(wù)器。 POST方法接收的數(shù)據(jù)不由服務(wù)器緩存。

4

PUT

用所上傳的內(nèi)容替換目標資源的所有當前表示。

5

刪除

刪除由URL給定的目標資源的所有當前表示

默認情況下,F(xiàn)lask路由響應(yīng) GET 請求。 但是,可以通過為 route()裝飾器提供方法參數(shù)來更改此偏好。

為了演示在URL路由中使用 POST 方法,首先讓我們創(chuàng)建一個HTML表單,并使用 POST 方法將表單數(shù)據(jù)發(fā)送到URL。

將以下腳本另存為login.html

<html>
   <body>
      
      <form action = "http://localhost:5000/login" method = "post">
         <p>Enter Name:</p>
         <p><input type = "text" name = "nm" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
      
   </body>
</html>

現(xiàn)在在Python shell中輸入以下腳本。

from flask import Flask, redirect, url_for, request
app = Flask(__name__)

@app.route('/success/<name>')
def success(name):
   return 'welcome %s' % name

@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      user = request.form['nm']
      return redirect(url_for('success',name = user))
   else:
      user = request.args.get('nm')
      return redirect(url_for('success',name = user))

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

開發(fā)服務(wù)器開始運行后,在瀏覽器中打開 login.html ,在文本字段中輸入name,然后單擊提交。

Post Method Example

表單數(shù)據(jù)被發(fā)送到表單標簽的action子句中的URL。

http:// localhost / login 映射到 login()函數(shù)。 由于服務(wù)器通過 POST 方法接收數(shù)據(jù),從表單數(shù)據(jù)獲得的“nm”參數(shù)的值通過 -

user = request.form['nm']

它作為可變部分傳遞給\'/ success\' URL。 瀏覽器在窗口中顯示歡迎消息。

Welcome Message

login.html 中的方法參數(shù)更改為\'GET\',然后在瀏覽器中再次打開。 在服務(wù)器上接收的數(shù)據(jù)是通過 GET 方法。 \'nm\'參數(shù)的值現(xiàn)在通過 -

User = request.args.get(‘nm’)

這里, args 是包含表單參數(shù)及其對應(yīng)值對的列表的字典對象。 與\'nm\'參數(shù)對應(yīng)的值將像之前一樣傳遞到\'/ success\'URL。

燒瓶 - 模板

可以以HTML的形式返回綁定到某個URL的函數(shù)的輸出。 例如,在以下腳本中, hello()函數(shù)將使用&lt; h1&gt; 標簽呈現(xiàn)\'Hello World\'

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
   return '<html><body><h1>Hello World'</h1></body></html>'

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

但是,從Python代碼生成HTML內(nèi)容很麻煩,尤其是當需要放置可變數(shù)據(jù)和Python語言元素(如條件語句或循環(huán))時。 這需要經(jīng)常從HTML轉(zhuǎn)義。

這是可以利用基于Flask的 Jinja2 模板引擎的地方。 代替從函數(shù)返回硬編碼HTML,可以通過 render_template()函數(shù)呈現(xiàn)HTML文件。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
   return render_template(‘hello.html’)

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

Flask將嘗試在templates文件夾中找到與此腳本所在的文件夾中的HTML文件。

  • Application folder
    • Hello.py
    • templates
      • hello.html

術(shù)語\'web模板系統(tǒng)\'是指設(shè)計一個HTML腳本,其中可以動態(tài)插入變量數(shù)據(jù)。 web模板系統(tǒng)包括模板引擎,某種數(shù)據(jù)源和模板處理器。

Flask使用 jinja2 模板引擎。 Web模板包含用于變量和表達式(在這些情況下為Python表達式)的HTML語法分散的占位符,在呈現(xiàn)模板時,這些占位符是替換的值。

以下代碼在模板文件夾中另存為 hello.html

<!doctype html>
<html>
   <body>
   
      <h1>Hello {{ name }}!</h1>
      
   </body>
</html>

接下來,從Python shell運行以下腳本。

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello/<user>')
def hello_name(user):
   return render_template('hello.html', name = user)

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

當開發(fā)服務(wù)器開始運行時,打開瀏覽器并輸入URL - http:// localhost:5000 / hello / mvl

網(wǎng)址的變量部分插入到 {{name}} 占位符。

Web Templating System Example

jinja2 模板引擎使用以下定界符從HTML轉(zhuǎn)義。

  • {% ... %} for Statements
  • {{ ... }} for Expressions to print to the template output
  • {# ... #} for Comments not included in the template output
  • # ... ## for Line Statements

在下面的示例中,演示了在模板中使用條件語句。 hello()函數(shù)的URL規(guī)則接受整數(shù)參數(shù)。 它被傳遞到 hello.html 模板。 在其內(nèi)部,比較接收的數(shù)字(標記)的值(大于或小于50),并且相應(yīng)地有條件地呈現(xiàn)HTML。

Python腳本如下 -

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/hello/<int:score>')
def hello_name(score):
   return render_template('hello.html', marks = score)

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

hello.html 的HTML模板腳本如下 -

<!doctype html>
<html>
   <body>
   
      {% if marks>50 %}
      <h1> Your result is pass!</h1>
      {% else %}
      <h1>Your result is fail</h1>
      {% endif %}
      
   </body>
</html>

請注意,條件語句 if-else endif 由分隔符 {%..%} 括起。

運行Python腳本并訪問網(wǎng)址 http:// localhost / hello / 60 ,然后訪問 http:// localhost / hello / 30 ,查看有條件地更改HTML的輸出。

Python循環(huán)結(jié)構(gòu)也可以在模板中使用。 在以下腳本中,當網(wǎng)址 http:// localhost:5000 / result 時, result()函數(shù)會將字典對象發(fā)送到模板 results.html >在瀏覽器中打開。

result.html 的模板部分使用 for循環(huán)來呈現(xiàn)字典對象 result {} 的鍵和值對作為HTML表格的單元格 。

從Python shell運行以下代碼。

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/result')
def result():
   dict = {'phy':50,'che':60,'maths':70}
   return render_template('result.html', result = dict)

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

將以下HTML腳本作為 result.html 保存在templates文件夾中。

<!doctype html>
<html>
   <body>
   
      <table border = 1>
         {% for key, value in result.iteritems() %}
         
            <tr>
               <th> {{ key }} </th>
               <td> {{ value }} </td>
            </tr>
            
         {% endfor %}
      </table>
      
   </body>
</html>

這里,對應(yīng)于 For 循環(huán)的Python語句也包含在{%..%}中,而表達式鍵和值 } 。

開發(fā)開始后,在瀏覽器中打開 http:// localhost:5000 / result 即可獲得以下輸出。

Table Template Example

Flask - 靜態(tài)文件

網(wǎng)絡(luò)應(yīng)用程序通常需要一個靜態(tài)文件,例如支持顯示網(wǎng)頁的 javascript 文件或 CSS 文件。 通常,網(wǎng)絡(luò)服務(wù)器配置為為您提供服務(wù),但在開發(fā)過程中,這些文件是從您的軟件包中的 static 文件夾或模塊旁邊提供的,并且可以從 i> / static

特殊的端點\'static\'用于為靜態(tài)文件生成URL。

在下面的示例中, index.html 中的 OnClick HTML事件按鈕調(diào)用 hello.js 中定義的 / b>,它顯示在Flask應(yīng)用程序的\'/\' URL上。

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def index():
   return render_template("index.html")

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

index.html 的HTML腳本如下所示。

<html>

   <head>
      <script type = "text/javascript" 
         src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
   </head>
   
   <body>
      <input type = "button" onclick = "sayHello()" value = "Say Hello" />
   </body>
   
</html>

Hello.js 包含 sayHello()函數(shù)。

function sayHello() {
   alert("Hello World")
}

Flask - 請求對象

來自客戶端網(wǎng)頁的數(shù)據(jù)作為全局請求對象發(fā)送到服務(wù)器。 為了處理請求數(shù)據(jù),它應(yīng)該從Flask模塊導(dǎo)入。

請求對象的重要屬性如下所列 -

  • 表單 - 它是一個字典對象,包含表單參數(shù)的鍵和值對及其值。

  • args - 在問號(?)后面的URL的一部分的查詢字符串的解析內(nèi)容。

  • Cookie - 保存Cookie名稱和值的字典對象。

  • 文件 - 與上傳的文件有關(guān)的數(shù)據(jù)。

  • 方法 - 當前請求方法。

Flask - 將表單數(shù)據(jù)發(fā)送到模板

我們已經(jīng)看到,可以在URL規(guī)則中指定http方法。 觸發(fā)函數(shù)接收的 Form 數(shù)據(jù)可以以字典對象的形式收集它并將其轉(zhuǎn)發(fā)到模板以在相應(yīng)的網(wǎng)頁上呈現(xiàn)它。

在以下示例中,\'/\'網(wǎng)址會呈現(xiàn)具有表單的網(wǎng)頁(student.html)。 填入的數(shù)據(jù)會發(fā)布到觸發(fā) result()函數(shù)的\'/ result\'網(wǎng)址。

results()函數(shù)收集呈現(xiàn)在 request.form 中的表單數(shù)據(jù),并將其發(fā)送給 result.html

模板動態(tài)呈現(xiàn)形式數(shù)據(jù)的HTML表格。

下面給出的是應(yīng)用程序的Python代碼 -

from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/')
def student():
   return render_template('student.html')

@app.route('/result',methods = ['POST', 'GET'])
def result():
   if request.method == 'POST':
      result = request.form
      return render_template("result.html",result = result)

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

下面給出的是 student.html 的HTML腳本。

<html>
   <body>
   
      <form action = "http://localhost:5000/result" method = "POST">
         <p>Name <input type = "text" name = "Name" /></p>
         <p>Physics <input type = "text" name = "Physics" /></p>
         <p>Chemistry <input type = "text" name = "chemistry" /></p>
         <p>Maths <input type ="text" name = "Mathematics" /></p>
         <p><input type = "submit" value = "submit" /></p>
      </form>
      
   </body>
</html>

下面給出了模板(result.html)的代碼:

<!doctype html>
<html>
   <body>
   
      <table border = 1>
         {% for key, value in result.iteritems() %}
         
            <tr>
               <th> {{ key }} </th>
               <td> {{ value }} </td>
            </tr>
            
         {% endfor %}
      </table>
      
   </body>
</html>

運行Python腳本,并在瀏覽器中輸入網(wǎng)址 http:// localhost:5000 / 。

Submit Marks

當點擊提交按鈕時,表單數(shù)據(jù)以HTML表格的形式呈現(xiàn)在 result.html 上。

Marks Table

燒瓶 - 曲奇餅

Cookie以文本文件的形式存儲在客戶端的計算機上。 其目的是記住和跟蹤與客戶的使用相關(guān)的數(shù)據(jù),以獲得更好的訪問者體驗和網(wǎng)站統(tǒng)計信息。

請求對象包含Cookie的屬性。 它是所有cookie變量及其對應(yīng)值的字典對象,客戶端已傳輸。 除此之外,cookie還存儲其到期時間,路徑和站點的域名。

在Flask中,對響應(yīng)對象設(shè)置cookie。 使用 make_response()函數(shù)從視圖函數(shù)的返回值獲取響應(yīng)對象。 之后,使用響應(yīng)對象的 set_cookie()函數(shù)來存儲cookie。

讀回cookie很容易。 request.cookies 屬性的 get()方法用于讀取cookie。

在以下Flask應(yīng)用程序中,當您訪問\'/\' URL時,會打開一個簡單的窗體。

@app.route('/')
def index():
   return render_template('index.html')

此HTML頁面包含一個文本輸入。

<html>
   <body>
   
      <form action = "/setcookie" method = "POST">
         <p><h3>Enter userID</h3></p>
         <p><input type = 'text' name = 'nm'/></p>
         <p><input type = 'submit' value = 'Login'/></p>
      </form>
      
   </body>
</html>

表單發(fā)布到\'/ setcookie\' URL。 相關(guān)聯(lián)的視圖函數(shù)設(shè)置Cookie名稱 userID 并呈現(xiàn)另一個頁面。

@app.route('/setcookie', methods = ['POST', 'GET'])
def setcookie():
   if request.method == 'POST':
   user = request.form['nm']
   
   resp = make_response(render_template('readcookie.html'))
   resp.set_cookie('userID', user)
   
   return resp

\'readcookie.html\'包含指向另一個視圖函數(shù) getcookie()的超鏈接,它讀回并在瀏覽器中顯示Cookie值。

@app.route('/getcookie')
def getcookie():
   name = request.cookies.get('userID')
   return '<h1>welcome '&plus;name&plus;'</h1>'

運行應(yīng)用程序,并訪問 http:// localhost:5000 /

ReadCookie HTML

設(shè)置cookie的結(jié)果顯示為這樣 -

Result of Setting Cookie

回讀cookie的輸出如下所示。

Reading Cookie Back

燒瓶 - 會話

與Cookie不同,會話數(shù)據(jù)存儲在服務(wù)器上。 會話是客戶端登錄到服務(wù)器并注銷它的時間間隔。 需要在該會話中保存的數(shù)據(jù)存儲在服務(wù)器上的臨時目錄中。

與每個客戶端的會話都分配有會話ID 。 會話數(shù)據(jù)存儲在cookie的頂部,服務(wù)器對它們進行加密簽名。 對于此加密,F(xiàn)lask應(yīng)用程序需要定義 SECRET_KEY 。

Session對象也是一個字典對象,包含會話變量和關(guān)聯(lián)值的鍵值對。

例如,要設(shè)置一個\'username\'會話變量,請使用語句 -

Session[‘username’] = ’admin’

要釋放會話變量,請使用 pop()方法。

session.pop('username', None)

以下代碼是Flask中的會話工作的簡單演示。 URL \'/\'只是提示用戶登錄,因為未設(shè)置會話變量\'username\'。

@app.route('/')
def index():
   if 'username' in session:
      username = session['username']
         return 'Logged in as ' &plus; username &plus; '<br>' &plus; \
         "<b><a href = '/logout'>click here to log out</a></b>"
   return "You are not logged in <br><a href = '/login'></b>" &plus; \
      "click here to log in</b></a>"

當用戶瀏覽到“/ login”login()視圖函數(shù)時,因為它是通過GET方法調(diào)用的,打開一個登錄表單。

表單發(fā)布回\'/ login\',現(xiàn)在設(shè)置會話變量。 應(yīng)用程序重定向到\'/\'。 此時會找到會話變量\'username\'

@app.route('/login', methods = ['GET', 'POST'])
def login():
   if request.method == 'POST':
      session['username'] = request.form['username']
      return redirect(url_for('index'))
   return '''
	
   <form action = "" method = "post">
      <p><input type = text name = username/></p>
      <p<<input type = submit value = Login/></p>
   </form>
	
   '''

應(yīng)用程序還包含一個 logout()視圖函數(shù),它會彈出\'username\'會話變量。 因此,\'/\' URL再次顯示開始頁面。

@app.route('/logout')
def logout():
   # remove the username from the session if it is there
   session.pop('username', None)
   return redirect(url_for('index'))

運行應(yīng)用程序并訪問主頁。 (確保設(shè)置應(yīng)用程序的 secret_key

from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
app.secret_key = 'any random string’

輸出將顯示如下所示。 點擊鏈接“點擊此處登錄”。

Login Page Using Session

鏈接將被定向到另一個屏幕。 鍵入“admin”。

Another Login Screen

屏幕將顯示消息“以管理員身份登錄”。

Logged in as admin

Flask - 重定向&amp; 錯誤

Flask類有一個 redirect()函數(shù)。 調(diào)用時,它返回一個響應(yīng)對象,并將用戶重定向到具有指定狀態(tài)代碼的另一個目標位置。

redirect()函數(shù)的原型如下 -

Flask.redirect(location, statuscode, response)

在上述函數(shù)中 -

  • location 參數(shù)是應(yīng)重定向響應(yīng)的網(wǎng)址。

  • statuscode 發(fā)送到瀏覽器標頭,默認為302。

  • response 參數(shù)用于實例化響應(yīng)。

以下狀態(tài)代碼已標準化 -

  • HTTP_300_MULTIPLE_CHOICES
  • HTTP_301_MOVED_PERMANENTLY
  • HTTP_302_FOUND
  • HTTP_303_SEE_OTHER
  • HTTP_304_NOT_MODIFIED
  • HTTP_305_USE_PROXY
  • HTTP_306_RESERVED
  • HTTP_307_TEMPORARY_REDIRECT

默認狀態(tài)代碼為 302 ,用于\'found\'

在以下示例中, redirect()函數(shù)用于在登錄嘗試失敗時再次顯示登錄頁面。

from flask import Flask, redirect, url_for, render_template, request
# Initialize the Flask application
app = Flask(__name__)

@app.route('/')
def index():
   return render_template('log_in.html')

@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST' and
   request.form['username'] == 'admin' :
   return redirect(url_for('success'))
   return redirect(url_for('index'))

@app.route('/success')
def success():
   return 'logged in successfully'
	
if __name__ == '__main__':
   app.run(debug = True)

Flask類具有帶錯誤代碼的 abort()函數(shù)。

Flask.abort(code)

代碼參數(shù)采用以下值之一:

  • 400 - 用于錯誤請求

  • 401 - 用于未經(jīng)身份驗證

  • 403 - Forbidden

  • 404 - 找不到

  • 406 - 表示不接受

  • 415 - 用于不支持的媒體類型

  • 429 - 請求過多

讓我們在上述代碼中的 login()函數(shù)中稍作更改。 如果要顯示\'Unauthurized\'頁面,而不是重新顯示登錄頁面,請?zhí)鎿Q為調(diào)用 abort(401)。

from flask import Flask, redirect, url_for, render_template, request, abort
app = Flask(__name__)

@app.route('/')
def index():
   return render_template('log_in.html')

@app.route('/login',methods = ['POST', 'GET'])
def login():
   if request.method == 'POST':
      if request.form['username'] == 'admin' :
         return redirect(url_for('success'))
      else:
         abort(401)
   else:
      return redirect(url_for('index'))

@app.route('/success')
def success():
   return 'logged in successfully'

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

Flask - 消息閃爍

好的基于GUI的應(yīng)用程序向用戶提供關(guān)于交互的反饋。 例如,桌面應(yīng)用程序使用對話框或消息框,JavaScript使用警報用于類似目的。

在Flask Web應(yīng)用程序中生成這樣的信息性消息很容易。 Flask框架的閃爍系統(tǒng)使得可以在一個視圖中創(chuàng)建消息,并在稱為下一的視圖函數(shù)中呈現(xiàn)它。

Flask模塊包含 flash()方法。 它將消息傳遞給下一個請求,通常是一個模板。

flash(message, category)

這里,

  • message 參數(shù)是要閃爍的實際消息。

  • category 參數(shù)是可選的。 它可以是“錯誤”,“信息”或“警告”。

為了從會話中刪除郵件,模板調(diào)用 get_flashed_messages()。

get_flashed_messages(with_categories, category_filter)

兩個參數(shù)都是可選的。 如果接收到的消息具有類別,則第一個參數(shù)是元組。 第二個參數(shù)僅用于顯示特定消息。

以下閃爍模板中接收的消息。

{% with messages = get_flashed_messages() %}
   {% if messages %}
      {% for message in messages %}
         {{ message }}
      {% endfor %}
   {% endif %}
{% endwith %}

讓我們看一個簡單的例子,展示Flask中的閃存機制。 在以下代碼中,\'/\' URL顯示登錄頁面的鏈接,沒有要閃爍的消息。

@app.route('/')
def index():
   return render_template('index.html')

該鏈接會將用戶引導(dǎo)到顯示登錄表單的\'/ login\' URL。 提交時, login()視圖函數(shù)驗證用戶名和密碼,并相應(yīng)閃爍\'success\'消息或創(chuàng)建\'error\'變量。

@app.route('/login', methods = ['GET', 'POST'])
def login():
   error = None
   
   if request.method == 'POST':
      if request.form['username'] != 'admin' or \
         request.form['password'] != 'admin':
         error = 'Invalid username or password. Please try again!'
      else:
         flash('You were successfully logged in')
         return redirect(url_for('index'))
   return render_template('login.html', error = error)

如果出現(xiàn)錯誤,則會重新顯示登錄模板,并顯示錯誤消息。

Login.html

<!doctype html>
<html>
   <body>
   
      <h1>Login</h1>
      
      {% if error %}
      <p><strong>Error:</strong> {{ error }}
      {% endif %}
      
      <form action = "" method = post>
         <dl>
            <dt>Username:</dt>
            
            <dd>
               <input type = text name = username 
                  value = "{{request.form.username }}">
            </dd>
            
            <dt>Password:</dt>
            <dd><input type = password name = password></dd>
         </dl>
         <p><input type = submit value = Login></p>
      </form>
      
   </body>
</html>

另一方面,如果 login 成功,則索引模板上會顯示成功消息。

Index.html

<!doctype html>
<html>
   
   <head>
      <title>Flask Message flashing</title>
   </head>
   <body>
   
      {% with messages = get_flashed_messages() %}
         {% if messages %}
            <ul>
               {% for message in messages %}
               <li<{{ message }}</li>
               {% endfor %}
            </ul>
         {% endif %}
      {% endwith %}
		
      <h1>Flask Message Flashing Example</h1>
      <p>Do you want to <a href = "{{ url_for('login') }}">
         <b>log in?</b></a></p>
      
   </body>
</html>

下面給出了Flask消息閃爍示例的完整代碼 -

Flash.py

from flask import Flask, flash, redirect, render_template, request, url_for
app = Flask(__name__)
app.secret_key = 'random string'

@app.route('/')
def index():
   return render_template('index.html')

@app.route('/login', methods = ['GET', 'POST'])
def login():
   error = None
   
   if request.method == 'POST':
      if request.form['username'] != 'admin' or \
         request.form['password'] != 'admin':
         error = 'Invalid username or password. Please try again!'
      else:
         flash('You were successfully logged in')
         return redirect(url_for('index'))
			
   return render_template('login.html', error = error)

if __name__ == "__main__":
   app.run(debug = True)

執(zhí)行上述代碼后,您將看到如下所示的屏幕。

Flask Message Flashing Example

當您點擊鏈接,您將被定向到登錄頁面。

輸入用戶名和密碼。

Login Page

點擊登錄。 將顯示一條消息“您已成功登錄”。

Successfully Logged in Page

Flask - 消息閃爍...

在Flask中處理文件上傳非常容易。 它需要一個HTML表單,其enctype屬性設(shè)置為“multipart / form-data”,將文件發(fā)布到URL。 URL處理程序從 request.files [] 對象中提取文件,并將其保存到所需的位置。

每個上傳的文件首先保存在服務(wù)器上的臨時位置,然后實際保存到其最終位置。 目標文件的名稱可以是硬編碼的,也可以從 request.files [file] 對象的filename屬性中獲取。 但是,建議使用 secure_filename()函數(shù)獲取安全版本。

可以在Flask對象的配置設(shè)置中定義默認上傳文件夾的路徑和上傳文件的最大大小。

app.config[‘UPLOAD_FOLDER’]定義上傳文件夾的路徑
app.config[‘MAX_CONTENT_PATH’]指定要上傳的文件的最大大小(以字節(jié)為單位)

以下代碼具有在模板文件夾中顯示\'upload.html\'\'/ upload\'網(wǎng)址規(guī)則,以及\'/ upload-file\' 調(diào)用 uploader()函數(shù)處理上傳過程的網(wǎng)址規(guī)則。

\'upload.html\'有一個文件選擇器按鈕和一個提交按鈕。

<html>
   <body>
   
      <form action = "http://localhost:5000/uploader" method = "POST" 
         enctype = "multipart/form-data">
         <input type = "file" name = "file" />
         <input type = "submit"/>
      </form>
      
   </body>
</html>

您將看到如下所示的屏幕。

Flask File Uploading

選擇文件后,單擊提交 表單的后方法調(diào)用\'/ upload_file\'網(wǎng)址。 底層函數(shù) uploader()執(zhí)行保存操作。

以下是Flask應(yīng)用程序的Python代碼。

from flask import Flask, render_template, request
from werkzeug import secure_filename
app = Flask(__name__)

@app.route('/upload')
def upload_file():
   return render_template('upload.html')
	
@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
   if request.method == 'POST':
      f = request.files['file']
      f.save(secure_filename(f.filename))
      return 'file uploaded successfully'
		
if __name__ == '__main__':
   app.run(debug = True)

Flask - 擴展

Flask通常被稱為微框架,因為核心功能包括基于 Werkzeug 的WSGI和路由以及基于 Jinja2 的模板引擎。 此外,F(xiàn)lask框架還支持cookie和會話,以及像 JSON ,靜態(tài)文件等Web幫助。顯然,這不足以開發(fā)一個成熟的Web應(yīng)用程序。 這是Flask擴展在哪里。 Flask擴展為Flask框架提供了可擴展性。

有大量的Flask擴展可用。 Flask擴展是一個Python模塊,它向Flask應(yīng)用程序添加特定類型的支持。 Flask擴展注冊表是可用的擴展的目錄。 所需的擴展程序可以通過 pip 實用程序下載。

在本教程中,我們將討論以下重要的Flask擴展 -

  • Flask Mail - 為Flask應(yīng)用程序提供SMTP接口

  • Flask WTF - 添加了WTForms的渲染和驗證

  • Flask SQLAlchemy - 為Flask應(yīng)用程序添加SQLAlchemy支持

  • Flask Sijax - Sijax的接口 - Python / jQuery庫,使AJAX易于在Web應(yīng)用程序中使用

每種類型的擴展通常提供有關(guān)其使用的廣泛文檔。 由于擴展是一個Python模塊,它需要導(dǎo)入才能使用。 瓶子延伸部分通常命名為flask-foo。 要導(dǎo)入,

from flask_foo import [class, function]

對于晚于0.7的Flask版本,您還可以使用語法 -

from flask.ext import foo

對于此用法,需要激活兼容性模塊。 它可以通過運行flaskext_compat.py來安裝

import flaskext_compat
flaskext_compat.activate()
from flask.ext import foo

Flask - 郵件

基于web的應(yīng)用程序通常需要具有向用戶/客戶端發(fā)送郵件的功能。 Flask-Mail 擴展功能可以很容易地與任何電子郵件服務(wù)器建立簡單的界面。

首先,F(xiàn)lask-Mail擴展應(yīng)該在pip實用程序的幫助下安裝。

pip install Flask-Mail

然后Flask-Mail需要通過設(shè)置以下應(yīng)用程序參數(shù)的值進行配置。

Sr.No參數(shù)&amp; 描述
1

MAIL_SERVER

電子郵件服務(wù)器的名稱/ IP地址

2

MAIL_PORT

使用的服務(wù)器的端口號

3

MAIL_USE_TLS

啟用/禁用傳輸安全層加密

4

MAIL_USE_SSL

啟用/禁用安全套接字層加密

5

MAIL_DEBUG

調(diào)試支持。 默認是Flask應(yīng)用程序的調(diào)試狀態(tài)

6

MAIL_USERNAME

發(fā)件人的用戶名

7

MAIL_PASSWORD

發(fā)件人的密碼

8

MAIL_DEFAULT_SENDER

設(shè)置默認發(fā)件人

9

MAIL_MAX_EMAILS

設(shè)置要發(fā)送的最大電子郵件

10

MAIL_SUPPRESS_SEND

如果app.testing設(shè)置為true,則發(fā)送抑制

11

MAIL_ASCII_ATTACHMENTS

如果設(shè)置為true,則附加的文件名轉(zhuǎn)換為ASCII

flask-mail模塊包含以下重要類的定義。

郵件類

它管理電子郵件消息傳遞需求。 類構(gòu)造函數(shù)采用以下形式 -

flask-mail.Mail(app = None)

構(gòu)造函數(shù)將Flask應(yīng)用程序?qū)ο笞鳛閰?shù)。

Mail類的方法

Sr.No方法&amp; 描述
1

send()

發(fā)送消息類對象的內(nèi)容

2

connect()

打開與郵件主機的連接

3

send_message()

發(fā)送消息對象

消息類

它封裝了一封電子郵件。 消息類構(gòu)造函數(shù)有幾個參數(shù) -

flask-mail.Message(subject, recipients, body, html, sender, cc, bcc, 
   reply-to, date, charset, extra_headers, mail_options, rcpt_options)

消息類方法

attach() - 在郵件中添加附件。 此方法采用以下參數(shù) -

  • filename - 要附加的文件的名稱

  • content_type - MIME類型的文件

  • data - 原始文件數(shù)據(jù)

  • 處置 - 內(nèi)容處置(如果有)。

add_recipient() - 向郵件中添加另一個收件人

在下面的示例中,Google gmail服務(wù)的SMTP服務(wù)器用作Flask-Mail配置的MAIL_SERVER。

步驟1 - 從代碼中的郵箱模塊導(dǎo)入郵件和郵件類。

from flask_mail import Mail, Message

步驟2 - 然后按照以下設(shè)置配置Flask-Mail。

app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'yourId@gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True

步驟3 - 創(chuàng)建Mail類的實例。

mail = Mail(app)

步驟4 - 在由URL規(guī)則(\'/\')映射的Python函數(shù)中設(shè)置Message對象。

@app.route("/")
def index():
   msg = Message('Hello', sender = 'yourId@gmail.com', recipients = ['id1@gmail.com'])
   msg.body = "This is the email body"
   mail.send(msg)
   return "Sent"

步驟5 - 整個代碼如下。 在Python Shell中運行以下腳本并訪問 http:// localhost:5000 /。

from flask import Flask
from flask_mail import Mail, Message

app =Flask(__name__)
mail=Mail(app)

app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'yourId@gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(app)

@app.route("/")
def index():
   msg = Message('Hello', sender = 'yourId@gmail.com', recipients = ['id1@gmail.com'])
   msg.body = "Hello Flask message sent from Flask-Mail"
   mail.send(msg)
   return "Sent"

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

請注意,Gmail服務(wù)中的內(nèi)置安全功能可能會阻止此次登錄嘗試。 您可能需要降低安全級別。 請登錄您的Gmail帳戶,然后訪問鏈接,以減少 安全。

Decrease the Security

燒瓶 - WTF

Web應(yīng)用程序的一個重要方面是為用戶提供一個用戶界面。 HTML提供了一個&lt; form&gt; 標簽,用于設(shè)計接口。 可以適當?shù)厥褂?strong>表單元素,例如文本輸入,廣播,選擇等。

由用戶輸入的數(shù)據(jù)以Http請求消息的形式通過GET或POST方法提交給服務(wù)器端腳本。

  • 服務(wù)器端腳本必須從http請求數(shù)據(jù)重新創(chuàng)建表單元素。 因此,實際上,表單元素必須定義兩次 - 一次在HTML中,再次在服務(wù)器端腳本中。

  • 使用HTML表單的另一個缺點是動態(tài)地呈現(xiàn)表單元素是困難的(如果不是不可能的話)。 HTML本身沒有提供驗證用戶輸入的方法。

這是 WTForms ,一個靈活的形式,渲染和驗證庫的地方很方便。 Flask-WTF擴展為這個 WTForms 庫提供了一個簡單的接口。

使用 Flask-WTF ,我們可以在Python腳本中定義表單字段,并使用HTML模板呈現(xiàn)它們。 也可以對 WTF 字段應(yīng)用驗證。

讓我們看看這個動態(tài)生成的HTML是如何工作的。

首先,需要安裝Flask-WTF擴展。

pip install flask-WTF

已安裝的軟件包包含一個 Form 類,必須用作用戶定義表單的父類。

WTforms 包中包含各種表單字段的定義。 下面列出了一些標準表單字段。

Sr.No標準表格字段&amp; 描述
1

TextField

表示&lt; input type =\'text\'&gt; HTML表單元素

2

BooleanField

表示&lt; input type =\'checkbox\'&gt; HTML表單元素

3

DecimalField

用于顯示帶小數(shù)的數(shù)字的文本框

4

IntegerField

用于顯示整數(shù)的TextField

5

RadioField

表示&lt; input type =\'radio\'&gt; HTML表單元素

6

SelectField

表示選擇表單元素

7

TextAreaField

表示&lt; testarea&gt; html表單元素

8

PasswordField

表示&lt; input type =\'password\'&gt; HTML表單元素

9

SubmitField

表示&lt; input type =\'submit\'&gt; 表單元素

例如,包含文本字段的表單可以設(shè)計如下 -

from flask_wtf import Form
from wtforms import TextField

class ContactForm(Form):
   name = TextField("Name Of Student")

除了\'name\'字段,自動創(chuàng)建CSRF令牌的隱藏字段。 這是為了防止跨站點請求偽造攻擊。

呈現(xiàn)時,這將導(dǎo)致等效的HTML腳本,如下所示。

<input id = "csrf_token" name = "csrf_token" type = "hidden" />
<label for = "name">Name Of Student</label><br>
<input id = "name" name = "name" type = "text" value = "" />

在Flask應(yīng)用程序中使用用戶定義的表單類,并使用模板呈現(xiàn)表單。

from flask import Flask, render_template
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'development key'

@app.route('/contact')
def contact():
   form = ContactForm()
   return render_template('contact.html', form = form)

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

WTForms包也包含驗證器類。 它在將驗證應(yīng)用于表單字段時很有用。 以下列表顯示常用的驗證器。

Sr.No驗證器類&amp; 描述
1

DataRequired

檢查輸入字段是否為空

2

電子郵件

檢查字段中的文本是否符合電子郵件ID約定

3

IP地址

在輸入字段中驗證IP地址

4

長度

驗證輸入字段中的字符串長度是否在給定范圍內(nèi)

5

NumberRange

在給定范圍內(nèi)驗證輸入字段中的數(shù)字

6

網(wǎng)址

驗證在輸入字段中輸入的URL

現(xiàn)在,我們將對聯(lián)系表單中的 name 字段應(yīng)用\'DataRequired\'驗證規(guī)則。

name = TextField("Name Of Student",[validators.Required("Please enter your name.")])

表單對象的 validate()函數(shù)驗證表單數(shù)據(jù),并在驗證失敗時拋出驗證錯誤。 錯誤消息將發(fā)送到模板。 在HTML模板中,錯誤消息是動態(tài)呈現(xiàn)的。

{% for message in form.name.errors %}
   {{ message }}
{% endfor %}

以下示例演示了上面給出的概念。 聯(lián)系表單的設(shè)計如下(forms.py)。

from flask_wtf import Form
from wtforms import TextField, IntegerField, TextAreaField, SubmitField, RadioField,
   SelectField

from wtforms import validators, ValidationError

class ContactForm(Form):
   name = TextField("Name Of Student",[validators.Required("Please enter 
      your name.")])
   Gender = RadioField('Gender', choices = [('M','Male'),('F','Female')])
   Address = TextAreaField("Address")
   
   email = TextField("Email",[validators.Required("Please enter your email address."),
      validators.Email("Please enter your email address.")])
   
   Age = IntegerField("age")
   language = SelectField('Languages', choices = [('cpp', 'C&plus;&plus;'), 
      ('py', 'Python')])
   submit = SubmitField("Send")

驗證器會應(yīng)用到名稱電子郵件字段。

下面給出了Flask應(yīng)用程序腳本(formexample.py)

from flask import Flask, render_template, request, flash
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'development key'

@app.route('/contact', methods = ['GET', 'POST'])
def contact():
   form = ContactForm()
   
   if request.method == 'POST':
      if form.validate() == False:
         flash('All fields are required.')
         return render_template('contact.html', form = form)
      else:
         return render_template('success.html')
      elif request.method == 'GET':
         return render_template('contact.html', form = form)

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

模板(contact.html)的腳本如下 -

<!doctype html>
<html>
   <body>
   
      <h2 style = "text-align: center;">Contact Form</h2>
		
      {% for message in form.name.errors %}
         <div>{{ message }}</div>
      {% endfor %}
      
      {% for message in form.email.errors %}
         <div>{{ message }}</div>
      {% endfor %}
      
      <form action = "http://localhost:5000/contact" method = post>
         <fieldset>
            <legend>Contact Form</legend>
            {{ form.hidden_tag() }}
            
            <div style = font-size:20px; font-weight:bold; margin-left:150px;>
               {{ form.name.label }}<br>
               {{ form.name }}
               <br>
               
               {{ form.Gender.label }} {{ form.Gender }}
               {{ form.Address.label }}<br>
               {{ form.Address }}
               <br>
               
               {{ form.email.label }}<br>
               {{ form.email }}
               <br>
               
               {{ form.Age.label }}<br>
               {{ form.Age }}
               <br>
               
               {{ form.language.label }}<br>
               {{ form.language }}
               <br>
               {{ form.submit }}
            </div>
            
         </fieldset>
      </form>
      
   </body>
</html>

在Python shell中運行 formexample.py ,訪問URL http:// localhost:5000 / contact 。 將顯示聯(lián)系人表單,如下所示。

Form Example

如果有任何錯誤,頁面將看起來像這樣 -

Form Error Page

如果沒有錯誤,將顯示\'success.html\'

Form Success Page

Flask - SQLite

Python具有對 SQlite 的內(nèi)置支持。 SQlite3模塊隨Python分發(fā)。 有關(guān)在Python中使用SQLite數(shù)據(jù)庫的詳細教程,請參閱此鏈接 在本節(jié)中,我們將看到Flask應(yīng)用程序如何與SQLite交互。

創(chuàng)建SQLite數(shù)據(jù)庫\'database.db\'并在其中創(chuàng)建學(xué)生表。

import sqlite3

conn = sqlite3.connect('database.db')
print "Opened database successfully";

conn.execute('CREATE TABLE students (name TEXT, addr TEXT, city TEXT, pin TEXT)')
print "Table created successfully";
conn.close()

我們的Flask應(yīng)用程序有三個查看功能。

第一個 new_student()函數(shù)已綁定到網(wǎng)址規(guī)則(\'/ addnew\')。 它呈現(xiàn)包含學(xué)生信息表單的HTML文件。

@app.route('/enternew')
def new_student():
   return render_template('student.html')

\'student.html\'的HTML腳本如下 -

<html>
   <body>
      
      <form action = "{{ url_for('addrec') }}" method = "POST">
         <h3>Student Information</h3>
         Name<br>
         <input type = "text" name = "nm" /></br>
         
         Address<br>
         <textarea name = "add" ></textarea><br>
         
         City<br>
         <input type = "text" name = "city" /><br>
         
         PINCODE<br>
         <input type = "text" name = "pin" /><br>
         <input type = "submit" value = "submit" /><br>
      </form>
      
   </body>
</html>

可以看出,表單數(shù)據(jù)發(fā)布到綁定 addrec()函數(shù)的\'/ addrec\' URL。

addrec()函數(shù)通過 POST 方法檢索表單的數(shù)據(jù),并插入學(xué)生表中。 在插入操作中對應(yīng)于成功或錯誤的消息呈現(xiàn)到\'result.html\'

@app.route('/addrec',methods = ['POST', 'GET'])
def addrec():
   if request.method == 'POST':
      try:
         nm = request.form['nm']
         addr = request.form['add']
         city = request.form['city']
         pin = request.form['pin']
         
         with sql.connect("database.db") as con:
            cur = con.cursor()
            cur.execute("INSERT INTO students (name,addr,city,pin) 
               VALUES (?,?,?,?)",(nm,addr,city,pin) )
            
            con.commit()
            msg = "Record successfully added"
      except:
         con.rollback()
         msg = "error in insert operation"
      
      finally:
         return render_template("result.html",msg = msg)
         con.close()

result.html 的HTML腳本包含顯示插入操作結(jié)果的轉(zhuǎn)義語句 {{msg}} 。

<!doctype html>
<html>
   <body>
   
      result of addition : {{ msg }}
      <h2><a href = "\">go back to home page</a></h2>
      
   </body>
</html>

應(yīng)用程序包含由\'/ list\' URL表示的另一個 list()函數(shù)。 它將\'rows\'填充為包含學(xué)生表中所有記錄的 MultiDict 對象。 此對象將傳遞到 list.html 模板。

@app.route('/list')
def list():
   con = sql.connect("database.db")
   con.row_factory = sql.Row
   
   cur = con.cursor()
   cur.execute("select * from students")
   
   rows = cur.fetchall(); 
   return render_template("list.html",rows = rows)

list.html 是一個模板,它遍歷行集并在HTML表中呈現(xiàn)數(shù)據(jù)。

<!doctype html>
<html>
   <body>
   
      <table border = 1>
         <thead>
            <td>Name</td>
            <td>Address>/td<
            <td>city</td>
            <td>Pincode</td>
         </thead>
         
         {% for row in rows %}
            <tr>
               <td>{{row["name"]}}</td>
               <td>{{row["addr"]}}</td>
               <td> {{ row["city"]}}</td>
               <td>{{row['pin']}}</td>	
            </tr>
         {% endfor %}
      </table>
      
      <a href = "/">Go back to home page</a>
      
   </body>
</html>

最后,\'/\'網(wǎng)址規(guī)則呈現(xiàn)一個\'home.html\',作為應(yīng)用程序的入口點。

@app.route('/')
def home():
   return render_template('home.html')

這是 Flask-SQLite 應(yīng)用程序的完整代碼。

from flask import Flask, render_template, request
import sqlite3 as sql
app = Flask(__name__)

@app.route('/')
def home():
   return render_template('home.html')

@app.route('/enternew')
def new_student():
   return render_template('student.html')

@app.route('/addrec',methods = ['POST', 'GET'])
def addrec():
   if request.method == 'POST':
      try:
         nm = request.form['nm']
         addr = request.form['add']
         city = request.form['city']
         pin = request.form['pin']
         
         with sql.connect("database.db") as con:
            cur = con.cursor()
            
            cur.execute("INSERT INTO students (name,addr,city,pin) 
               VALUES (?,?,?,?)",(nm,addr,city,pin) )
            
            con.commit()
            msg = "Record successfully added"
      except:
         con.rollback()
         msg = "error in insert operation"
      
      finally:
         return render_template("result.html",msg = msg)
         con.close()

@app.route('/list')
def list():
   con = sql.connect("database.db")
   con.row_factory = sql.Row
   
   cur = con.cursor()
   cur.execute("select * from students")
   
   rows = cur.fetchall();
   return render_template("list.html",rows = rows)

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

在開發(fā)服務(wù)器開始運行時,從Python shell運行此腳本。 在瀏覽器中訪問 http:// localhost:5000 / ,顯示一個簡單的菜單 -

Simple Menu

點擊“添加新記錄”鏈接以打開學(xué)生信息表單。

Adding New Record

填寫表單字段并提交。 底層函數(shù)在學(xué)生表中插入記錄。

Record Successfully Added

返回首頁,然后點擊\'顯示列表\'鏈接。 將顯示顯示樣品數(shù)據(jù)的表。

Table Showing Sample Data

Flask - SQLAlchemy

在Flask Web應(yīng)用程序中使用原始SQL對數(shù)據(jù)庫執(zhí)行CRUD操作可能很乏味。 相反, SQLAlchemy ,Python工具包是一個強大的 OR Mapper ,為應(yīng)用程序開發(fā)人員提供了SQL的全部功能和靈活性。 Flask-SQLAlchemy是Flask擴展,為SQLAlchemy應(yīng)用程序添加了對SQLAlchemy的支持。

什么是ORM(對象關(guān)系映射)?

大多數(shù)編程語言平臺是面向?qū)ο蟮摹?/span> 另一方面,RDBMS服務(wù)器中的數(shù)據(jù)存儲為表。 對象關(guān)系映射是將對象參數(shù)映射到底層RDBMS表結(jié)構(gòu)的技術(shù)。 ORM API提供了執(zhí)行CRUD操作的方法,而不必編寫原始SQL語句。

在本節(jié)中,我們將研究Flask-SQLAlchemy的ORM技術(shù)并構(gòu)建一個小型Web應(yīng)用程序。

步驟1 - 安裝Flask-SQLAlchemy擴充功能。

pip install flask-sqlalchemy

步驟2 - 您需要從此模塊導(dǎo)入SQLAlchemy類。

from flask_sqlalchemy import SQLAlchemy

步驟3 - 現(xiàn)在創(chuàng)建一個Flask應(yīng)用程序?qū)ο蟛⒃O(shè)置要使用的數(shù)據(jù)庫的URI。

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3'

步驟4 - 然后創(chuàng)建一個SQLAlchemy類的對象,以應(yīng)用程序?qū)ο笞鳛閰?shù)。 此對象包含用于ORM操作的輔助函數(shù)。 它還提供了一個父Model類,使用它來聲明用戶定義的模型。 在下面的代碼段中,創(chuàng)建了學(xué)生模型。

db = SQLAlchemy(app)
class students(db.Model):
   id = db.Column('student_id', db.Integer, primary_key = True)
   name = db.Column(db.String(100))
   city = db.Column(db.String(50))  
   addr = db.Column(db.String(200))
   pin = db.Column(db.String(10))

def __init__(self, name, city, addr,pin):
   self.name = name
   self.city = city
   self.addr = addr
   self.pin = pin

步驟5 - 要創(chuàng)建/使用URI中提及的數(shù)據(jù)庫,請運行 create_all()方法。

db.create_all()

SQLAlchemy Session 對象管理 ORM 對象的所有持久性操作。

以下會話方法執(zhí)行CRUD操作 -

  • db.session.add (模型對象) - 將記錄插入到映射表中

  • db.session.delete (模型對象) - 從表中刪除記錄

  • model.query.all() - 從表中檢索所有記錄(對應(yīng)于SELECT查詢)。

您可以通過使用filter屬性將過濾器應(yīng)用于檢索的記錄集。 例如,要在學(xué)生表中檢索 city =\'Hyderabad\'的記錄,請使用以下語句 -

Students.query.filter_by(city = ’Hyderabad’).all()

有了這么多的背景,現(xiàn)在我們將提供視圖函數(shù)為我們的應(yīng)用程序添加學(xué)生數(shù)據(jù)。

應(yīng)用程序的入口點是綁定到\'/\' URL的 show_all()函數(shù)。 學(xué)生記錄集表作為參數(shù)發(fā)送到HTML模板。 模板中的服務(wù)器端代碼以HTML表格形式呈現(xiàn)記錄。

@app.route('/')
def show_all():
   return render_template('show_all.html', students = students.query.all() )

模板(\'show_all.html\')的HTML腳本就是這樣 -

<!DOCTYPE html>
<html lang = "en">
   <head></head>
   <body>
      
      <h3>
         <a href = "{{ url_for('show_all') }}">Comments - Flask 
            SQLAlchemy example</a>
      </h3>
      
      <hr/>
      {%- for message in get_flashed_messages() %}
         {{ message }}
      {%- endfor %}
		
      <h3>Students (<a href = "{{ url_for('new') }}">Add Student
         </a>)</h3>
      
      <table>
         <thead>
            <tr>
               <th>Name</th>
               <th>City</th>
               <th>Address</th>
               <th>Pin</th>
            </tr>
         </thead>
         
         <tbody>
            {% for student in students %}
               <tr>
                  <td>{{ student.name }}</td>
                  <td>{{ student.city }}</td>
                  <td>{{ student.addr }}</td>
                  <td>{{ student.pin }}</td>
               </tr>
            {% endfor %}
         </tbody>
      </table>
      
   </body>
</html>

上述網(wǎng)頁包含指向\'/ new\'網(wǎng)址映射 new()函數(shù)的超鏈接。 單擊時,將打開“學(xué)生信息”表單。 數(shù)據(jù)在 POST 方法中發(fā)布到相同的URL。

new.html

<!DOCTYPE html>
<html>
   <body>
   
      <h3>Students - Flask SQLAlchemy example</h3>
      <hr/>
      
      {%- for category, message in get_flashed_messages(with_categories = true) %}
         <div class = "alert alert-danger">
            {{ message }}
         </div>
      {%- endfor %}
      
      <form action = "{{ request.path }}" method = "post">
         <label for = "name">Name</label><br>
         <input type = "text" name = "name" placeholder = "Name" /><br>
         <label for = "email">City</label><br>
         <input type = "text" name = "city" placeholder = "city" /><br>
         <label for = "addr">addr</label><br>
         <textarea name = "addr" placeholder = "addr"></textarea><br>
         <label for = "PIN">City</label><br>
         <input type = "text" name = "pin" placeholder = "pin" /><br>
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

當http方法被檢測為POST時,表單數(shù)據(jù)被添加到學(xué)生表中,并且應(yīng)用返回到顯示添加的數(shù)據(jù)的主頁。

@app.route('/new', methods = ['GET', 'POST'])
def new():
   if request.method == 'POST':
      if not request.form['name'] or not request.form['city'] or not request.form['addr']:
         flash('Please enter all the fields', 'error')
      else:
         student = students(request.form['name'], request.form['city'],
            request.form['addr'], request.form['pin'])
         
         db.session.add(student)
         db.session.commit()
         
         flash('Record was successfully added')
         return redirect(url_for('show_all'))
   return render_template('new.html')

下面給出了應(yīng)用程序(app.py)的完整代碼。

from flask import Flask, request, flash, url_for, redirect, render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3'
app.config['SECRET_KEY'] = "random string"

db = SQLAlchemy(app)

class students(db.Model):
   id = db.Column('student_id', db.Integer, primary_key = True)
   name = db.Column(db.String(100))
   city = db.Column(db.String(50))
   addr = db.Column(db.String(200)) 
   pin = db.Column(db.String(10))

def __init__(self, name, city, addr,pin):
   self.name = name
   self.city = city
   self.addr = addr
   self.pin = pin

@app.route('/')
def show_all():
   return render_template('show_all.html', students = students.query.all() )

@app.route('/new', methods = ['GET', 'POST'])
def new():
   if request.method == 'POST':
      if not request.form['name'] or not request.form['city'] or not request.form['addr']:
         flash('Please enter all the fields', 'error')
      else:
         student = students(request.form['name'], request.form['city'],
            request.form['addr'], request.form['pin'])
         
         db.session.add(student)
         db.session.commit()
         flash('Record was successfully added')
         return redirect(url_for('show_all'))
   return render_template('new.html')

if __name__ == '__main__':
   db.create_all()
   app.run(debug = True)

從Python shell運行腳本,并在瀏覽器中輸入 http:// localhost:5000 / 。

Flask SQLAlchemy Example

點擊“添加學(xué)生”鏈接以打開學(xué)生信息表單。

Add Student

填寫表單并提交。 主頁將重新顯示提交的數(shù)據(jù)。

我們可以看到輸出如下所示。

Flask SQLAlchemy Example Output

燒瓶 - Sijax

Sijax 代表\'Simple Ajax\',它是一個 Python / jQuery 庫,旨在幫助您輕松地將 Ajax 到您的應(yīng)用程序。 它使用 jQuery.ajax 來創(chuàng)建AJAX請求。

安裝

安裝Flask-Sijax很容易。

pip install flask-sijax

組態(tài)

  • SIJAX_STATIC_PATH - 您希望對Sijax javascript文件進行鏡像的靜態(tài)路徑。 默認位置為 static / js / sijax 。 在此文件夾中,保存 sijax.js json2.js 文件。

  • SIJAX_JSON_URI - 用于加載json2.js靜態(tài)文件的URI

Sijax使用 JSON 在瀏覽器和服務(wù)器之間傳遞數(shù)據(jù)。 這意味著瀏覽器需要或從 json2.js 文件本身支持 JSON 或獲取 JSON 支持。

以此方式注冊的函數(shù)不能提供 Sijax 功能,因為它們在默認情況下不能使用 POST 方法訪問(而Sijax使用POST請求)。

要使 View 功能能夠處理 Sijax 請求,請使用 @ app.route(\'/ url\',methods = [\'GET\' ,\'POST\'])或使用 @ flask_sijax.route 輔助裝飾器,

@flask_sijax.route(app, '/hello')

每個Sijax處理函數(shù)(像這樣)至少接收一個參數(shù),就像Python傳遞\'self\'到對象方法。 \'obj_response\'參數(shù)是函數(shù)回傳瀏覽器的方式。

def say_hi(obj_response):
   obj_response.alert('Hi there!')

當檢測到Ajax請求時,Sijax處理它像這樣 -

g.sijax.register_callback('say_hi', say_hi)
   return g.sijax.process_request()

Sijax應(yīng)用

最小的Sijax應(yīng)用程序代碼如下 -

import os
from flask import Flask, g
from flask_sijax import sijax

path = os.path.join('.', os.path.dirname(__file__), 'static/js/sijax/')
app = Flask(__name__)

app.config['SIJAX_STATIC_PATH'] = path
app.config['SIJAX_JSON_URI'] = '/static/js/sijax/json2.js'
flask_sijax.Sijax(app)

@app.route('/')
def index():
   return 'Index'
	
@flask_sijax.route(app, '/hello')
def hello():
   def say_hi(obj_response):
      obj_response.alert('Hi there!')
   if g.sijax.is_sijax_request:
      # Sijax request detected - let Sijax handle it
      g.sijax.register_callback('say_hi', say_hi)
      return g.sijax.process_request()
      return _render_template('sijaxexample.html')

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

當Sijax向服務(wù)器請求(特殊的 jQuery.ajax()請求)時,此請求在服務(wù)器上通過 g.sijax.is_sijax_request()檢測到, case你讓 Sijax 處理請求。

使用 g.sijax.register_callback()注冊的所有函數(shù)都可以從瀏覽器調(diào)用。

調(diào)用 g.sijax.process_request()會告訴Sijax執(zhí)行相應(yīng)的(先前注冊的)函數(shù)并將響應(yīng)返回給瀏覽器。

燒瓶 - 部署

外部可見服務(wù)器

開發(fā)服務(wù)器上的Flask應(yīng)用程序只能在設(shè)置開發(fā)環(huán)境的計算機上訪問。 這是一種默認行為,因為在調(diào)試模式下,用戶可以在計算機上執(zhí)行任意代碼。

如果禁用了 debug ,則可以通過將主機名設(shè)置為\'0.0.0.0\',使本地計算機上的開發(fā)服務(wù)器對網(wǎng)絡(luò)上的用戶可用。

app.run(host = ’0.0.0.0’)

因此,您的操作系統(tǒng)偵聽所有公共IP。

部署

要從開發(fā)環(huán)境切換到完整的生產(chǎn)環(huán)境,應(yīng)用程序需要部署在真實的Web服務(wù)器上。 根據(jù)您的具體情況,有不同的選項可用于部署Flask Web應(yīng)用程序。

對于小型應(yīng)用程序,您可以考慮將其部署到以下任何托管平臺上,所有這些平臺都為小型應(yīng)用程序提供免費計劃。

  • Heroku
  • dotcloud
  • webfaction

Flask應(yīng)用程序可以部署在這些云平臺上。 此外,可以在Google云平臺上部署Flask應(yīng)用程序。 Localtunnel服務(wù)允許您在localhost上共享您的應(yīng)用程序,而不會破壞DNS和防火墻設(shè)置。

如果您傾向于使用專用的Web服務(wù)器代替上述共享平臺,以下選項有待探索。

mod_wsgi

mod_wsgi 是一個Apache模塊,它提供了一個符合WSGI的接口,用于在Apache服務(wù)器上托管基于Python的Web應(yīng)用程序。

安裝mod_wsgi

要直接從PyPi安裝官方發(fā)布,你可以運行 -

pip install mod_wsgi

要驗證安裝是否成功,請使用start-server命令運行mod_wsgi-express腳本 -

mod_wsgi-express start-server

這將啟動Apache / mod_wsgi在端口8000.然后您可以驗證安裝工作通過指向您的瀏覽器 -

http://localhost:8000/

正在創(chuàng)建.wsgi文件

應(yīng)該有一個 yourapplication.wsgi 文件。 此文件包含代碼 mod_wsgi,,它在啟動時執(zhí)行以獲取應(yīng)用程序?qū)ο蟆?/span> 對于大多數(shù)應(yīng)用程序,以下文件應(yīng)該足夠 -

from yourapplication import app as application

確保 yourapplication 和所有正在使用的庫都在python加載路徑。

配置Apache

您需要告訴 mod_wsgi,您的應(yīng)用程序的位置。

<VirtualHost *>
   ServerName example.com
   WSGIScriptAlias / C:\yourdir\yourapp.wsgi
   
   <Directory C:\yourdir>
      Order deny,allow
      Allow from all
   </Directory>
   
</VirtualHost>

獨立WSGI容器

有許多使用Python編寫的流行服務(wù)器,它們包含WSGI應(yīng)用程序和服務(wù)HTTP。

  • Gunicorn
  • Tornado
  • Gevent
  • Twisted Web

Flask - FastCGI

FastCGI是在像nginx,lighttpd和Cherokee這樣的web服務(wù)器上的Flask應(yīng)用程序的另一個部署選項。

配置FastCGI

首先,您需要創(chuàng)建 FastCGI 服務(wù)器文件。 讓我們將其稱為 yourapplication.fcgiC

from flup.server.fcgi import WSGIServer
from yourapplication import app

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

nginx 和舊版本的 lighttpd 需要一個套接字以明確傳遞,以便與 FastCGI 服務(wù)器通信。 要使其工作,您需要將路徑傳遞到 WSGIServer 的套接字。

WSGIServer(application, bindAddress = '/path/to/fcgi.sock').run()

配置Apache

對于基本的Apache部署,您的 .fcgi 文件將顯示在應(yīng)用程序網(wǎng)址中。 example.com/yourapplication.fcgi/hello / 。 有幾種方法可以配置您的應(yīng)用程序,以使 yourapplication.fcgi 不會顯示在網(wǎng)址中。

<VirtualHost *>
   ServerName example.com
   ScriptAlias / /path/to/yourapplication.fcgi/
</VirtualHost>

配置lighttpd

lighttpd 的基本配置如下所示:

fastcgi.server = ("/yourapplication.fcgi" => ((
   "socket" => "/tmp/yourapplication-fcgi.sock",
   "bin-path" => "/var/www/yourapplication/yourapplication.fcgi",
   "check-local" => "disable",
   "max-procs" => 1
)))

alias.url = (
   "/static/" => "/path/to/your/static"
)

url.rewrite-once = (
   "^(/static($|/.*))$" => "$1",
   "^(/.*)$" => "/yourapplication.fcgi$1"
)

請記住啟用 FastCGI ,別名和重寫模塊。 此配置將應(yīng)用程序綁定到 / yourapplication


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號