3.1 後端開發與 Flask 框架

本節要點

  • 瞭解後端開發的概念、作用及應用場景
  • 重點掌握基於Flask框架的使用方式

課前準備

安裝 Flask 框架

在cmd(Windows)或終端(Mac)輸入:

pip install flask
#或
pip3 install flask
#或
pip3.8 install flask

課程內容

後端開發

1. 後端開發概念

以 Jodoo 網頁為例

前端:網頁上的文字、圖片、圖標、點擊後的交互效果、彈框等,所有這些東西都屬於前端;

後端:伺服器的運維管理、資料庫的管理,以及用於連接前後端的API(私有API)。

  • 私有API:例如Jodoo 前後端協同開發所用的API,僅在產品內部使用;
  • 公共API:把一些服務封裝好供開發者使用,例如Jodoo的資料API、通訊錄API。

2. Jodoo 相關功能

API(公共API),開發文件地址:https://hc.jodoo.com/open/10992 後端 + API,開發者在後端發送請求(攜帶資料)觸發 Jodoo 的服務

Webhook,開發文件地址:https://hc.jodoo.com/open/11500 鉤子,Jodoo 事件觸發推播資料到管理員指定的API

前端事件,開發文件地址:https://hc.jodoo.com/doc/11825 前端+API,使用者在表單填報界面,透過事件觸發調用管理員配置的API來取得資料或觸發事件

3. 場景

透過前三節的學習,我們已經掌握了API調用能力:

  • 如何透過POSTMAN去調用API
  • 如何透過Python處理資料
  • 如何透過Python封裝函數調用API

透過後端開發,我們可以自己開發API,編寫服務,更加自由地去使用資料!

  • 如何在本地編寫API
  • 如何將API部署至雲伺服器(ECS)
  • 如何將資料備份至資料庫以及從資料庫取數

實現下面的場景:

  • Jodoo 資料推播 - 資料處理(ECS)- 簡訊(第三方API)
    • 講解:例如我們透過第3課的學習,學會了封裝API函數,那麼我們封裝一個發送簡訊的API,當我們接收到資料推播後,即調用函數去發送簡訊!
  • Jodoo 資料推播 - 資料處理(ECS)- 調用Jodoo API(相當於高級的智慧助手)
  • Jodoo 資料推播 - 資料處理(ECS)- OCR(第三方API)- 資料處理(ECS)- 調用JodooAPI
  • Jodoo 資料推播 - 資料處理(ECS)- Mysql(資料庫)
  • ASP定時框架(ECS) - 調用JodooAPI - 資料處理(ECS)- 釘釘羣推播
  • ASP定時框架(ECS) - 調用JodooAPI - 資料處理(ECS)- Mysql(資料庫)
  • Jodoo 前端事件 - 資料處理(ECS)- 分析資料(OCR)
  • Jodoo 前端事件 - 資料處理(ECS)- 資料校驗(身份證、姓名一致性校驗)
  • Jodoo 前端事件 - 資料處理(ECS)- 取得資料
  • Jodoo 前端事件 - 資料處理(ECS)- Mysql取數 - 資料處理(ECS)- 取得資料 其他

Flask 框架

官方文件:點擊查看中文文件:點擊查看

Flask是由python實現的一個web微框架,讓我們可以使用Python語言快速實現一個網站或Web服務。

1. 一個最小化的Flask應用

注意:直接在IDLE運行Flask文件會出現 io.UnsupportedOperation: fileno 錯誤,雙擊.py文件運行即可解決這個問題!

from flask import Flask

app = Flask(__name__)       

@app.route('/')
def hello_world():    #注意接收函數名不要重複
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=3100)

我們一步步拆解來看:

  • 首先我們匯入了 Flask 包;
from flask import Flask
  • 接著我們建立一個該類的實例。第一個參數是應用模塊或者包的名稱。如果你使用 一個單一模塊(就像本例),那麼應當使用__name__,因為名稱會根據這個模塊是按應用方式使用還是作為一個模塊匯入而發生變化(可能是__main__, 也可能是實際匯入的名稱)。這個參數是必需的,這樣Flask才能知道在哪裏可以找到範本和靜態文件等東西;
app = Flask(__name__)
  • 然後我們使用 route() 裝飾器來告訴 Flask 觸發函數的 URL ;
@app.route('/')
  • 函數名稱被用於生成相關聯的 URL 。函數最後返回需要在使用者瀏覽器中顯示的資訊;
def hello_world():
    return 'Hello, World!'
  • 缺省設定是運行伺服器後,只有你自己的電腦可以使用服務,只監聽 127.0.0.1。 所以要加上 --host=0.0.0.0 ,這行程式碼告訴你的操作系統監聽所有公開的 IP,本節課我們只寫本地API,不加也是可以的 :
if __name__ == '__main__':
    app.run(host='0.0.0.0',port=3100)

2. URL 構成

域名(Host,這裡我們在本地運行,使用本地機ip:127.0.0.1) + 端口 + 路徑

端口:

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=3100)

路徑:

@app.route('/route')

你也可以在一個端口下,定義多個路徑(注意接收函數名不要重複):

from flask import Flask

app = Flask(__name__)       

@app.route('/a')
def hello_world1():    #注意接收函數名不要重複
    return 'Hello, World!'
    
@app.route('/b/')
def hello_world2():    #注意接收函數名不要重複
    return 'Thank you'

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=3100)

3. 接收資料

定義 API 類型

@app.route('/',methods=['GET'])

@app.route('/',methods=['GET', 'POST'])

@app.route('/',methods=['POST'])

接收不同的資料

先要記得引入request模塊

from flask import Flask,request
import json
  • 接收URL params
request.args

request.args.get("canshu1")
  • 接收Headers
request.headers

request.headers.get("xxx")
  • 接收 multipart/form-data 或 application/x-www-from-urlencoded 格式的資料
request.form

request.form.get("xxx")
  • 接收 application/json 格式的資料
request.data

json.loads(request.data)
from flask import Flask,request
import json

app = Flask(__name__)       

@app.route('/',methods=['GET', 'POST'])
def hello_world():
    print(request.args)
    print(request.headers)
    print(request.form)
    print(request.data)
    print(json.loads(request.data))
    return 'success',200

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=3100)

4. 返回資料

JSON 格式的回應是常見的,用 Flask 寫這樣的 API 是很容易上手的。

import json
import urllib.parse
# 返回文字
return 'Hello, World!'
# 返回Json格式的資料
a = json.dumps({"aaa":123})
return a
# 返回x-www-from-urlencoded格式的資料
return urllib.parse.urlencode({"aaa":123})
# 不需要返回資料,只需要返回狀態碼
return 'success',200

HTTP 狀態碼點擊查看

捕捉異常可以使用try/except語句。

try/except語句用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常資訊並處理。

如果你不想在異常發生時結束你的程式,只需在try裏捕獲它。

以下為簡單的try…except…else的語法:

try:
<語句>        #運行別的程式碼
except <名字>:
<語句>        #如果在try部份引發了'name'異常
except <名字>,<資料>:
<語句>        #如果引發了'name'異常,獲得附加的資料
else:
<語句>        #如果沒有異常發生

在API開發過程中,可以配合異常處理返回不同的狀態碼!

  • 400 參數錯誤

Key

Value

name

姓名

age

年齡

import json

request_data = {"name":"ziv"}

def response():
    try:
        name = request_data['name']
        age = request_data['age']
    except KeyError as e:
        return  '參數錯誤',400
    else:
        return 'success',200
  • 401 Unauthorized 鑑權失敗
if request.headers['x-jdy-signature'] != get_signature(nonce, payload, 'test-secret', timestamp):
        return 'fail', 401

Jodoo webhook推播錯誤說明

接收到推播後需要返回給Jodoo2xx表示推播接收成功。其他的返回結果則為返回資訊錯誤,使用者可以根據HTTP狀態碼自行定義推播錯誤的情況給Jodoo的返回碼,Jodoo接受後,可在推播日誌中顯示出。

這項資訊有幫助嗎?
需要更多協助嗎?聯繋技術支援。