1. 程式人生 > 其它 >Flask學習筆記(2)

Flask學習筆記(2)

路由

在flask中,使用 @route() 裝飾器來把函式繫結到URL。

@app.route('/home') #宣告路由
def index(): # 宣告檢視函式
    return '<h1>Hello, Flask!</h1>'

注意:路由和檢視的名稱必須全域性唯一,不能出現重複。

除了可以使用裝飾器的方式註冊路由,還可以使用app的add_url_rule方法。

def hello():
    return 'Hello, Flask!'

app.add_url_rule('/hello', view_func=hello)

查詢路由資訊

有兩種方式可以檢視當前應用的路由資訊

  • 命令列方式

    flask routes
    

    輸出內容如下:

    Endpoint  Methods  Rule
    --------  -------  -----------------------
    index     GET      /
    static    GET      /static/<path:filename>
    
  • 在程式中獲取

    在應用的url_map屬性中儲存著當前flask應用所有的對映資訊,可以讀取這個屬性獲取路由資訊

    print(app.url_map)
    

    遍歷所有路由資訊:

    for rule in app.url_map.iter_rules():
        print(rule.endpoint, rule.rule)
    

請求方式

路由預設的請求方式為

  • GET
  • OPTIONS
  • HEAD

使用 methods 引數可以指定一個介面的請求方式

@app.route('/', methods=["POST"])
def hello_world():
    return 'Hello World!'

藍圖

當flask程式越來越複雜,我們需要對程式進行模組化處理,在Flask中使用Blueprint來分模組組織管理。

藍圖可以理解為是一個儲存一組檢視方法的容器物件,其具有如下特點:

  • 一個應用可以具有多個Blueprint。
  • 可以將一個Blueprint註冊到任何一個未使用的URL下,比如"/hello"、"/user"。
  • Blueprint可以單獨具有自己的模板、靜態檔案或者其他的通用的操作方法,它並不是必須要實現應用的檢視和函式。
  • 在一個應用初始化時,就應該註冊需要使用的Blueprint。

使用方式

使用藍圖可以分為三個步驟:

  1. 建立一個藍圖物件 users/__init__.py
from flask import Blueprint
users_bp = Blueprint('users', __name__)
from . import views
  1. 在這個藍圖物件上進行操作,註冊路由,指定靜態資料夾,註冊模板過濾器 users/views.py
@user_bp.route('/profile')
def get_profile():
    return 'user profile!'
  1. 在應用物件上註冊藍圖物件 app.py
app.register_blueprint(user_bp)

目錄(包)的方式使用藍圖

對應一個打算包含多個檔案的藍圖,可以將建立藍圖物件放到python包的 __init__.py 檔案中

--------- project #工程目錄
  |------ app.py  #啟動檔案
  |------ users    #使用者藍圖
  |  |--- __init__.py #此處建立藍圖物件
  |  |...
  |------ goods   #商品藍圖
  |  |--- __init__.py 
  |...

示例:

新建包goods,__init__.py檔案內容如下

from flask import Blueprint

goods_bp = Blueprint('goods', __name__)

from . import views # 此處匯入程式碼必須放在最後,如果放在最上方,會出現迴圈引用的問題

在goods目錄下,新建 views.py 檔案內容如下:

from . import goods_bp

@goods_bp.route('/goods')
def get_goods():
    return 'get goods'

app.py內容如下:

from flask import Flask
from goods import goods_bp
app = Flask(__name__)

app.register_blueprint(goods_bp)

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

藍圖內部靜態檔案

和應用物件不同,藍圖物件建立時不會預設註冊靜態目錄的路由,需要我們在建立時指定 static_folder 引數。

示例:

goods_bp = Blueprint('goods', __name__, static_folder='static_file', template_folder='goods_templates')
app.register_blueprint(goods_bp, url_prefix='/goods')

轉換器

動態路由

通過把 URL 的一部分標記為 <variable_name> 就可以在 URL 中新增變數。標記的部分會作為關鍵字引數傳遞給函式。通過使用 <converter:variable_name> ,可以選擇性的加上一個轉換器,為變數指定規則。

from flask import Flask

app = Flask(__name__)


@app.route('/users/<user_id>')
def hello_world(user_id):
    print(type(user_id))  # <class 'str'>
    return 'users {} '.format(user_id)


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

此處 user_id 作為引數名傳入檢視,預設為字串型別。

預設轉換器

除了預設的字串型別之外,Flask還提供瞭如下其他型別的轉換器。

DEFAULT_CONVERTERS = {
    "default": UnicodeConverter,
    "string": UnicodeConverter,
    "any": AnyConverter,
    "path": PathConverter,
    "int": IntegerConverter,
    "float": FloatConverter,
    "uuid": UUIDConverter,
}

轉換器對應的含義:

轉換器 含義
default 接受字串,預設轉換器
string 接受字串,跟預設一樣
any 限定url中接收引數的值
path 可以接受斜線
int 接受整數
float 接受浮點數
uuid 只接收uuid型別的字串

示例:

@app.route('/users/<path:user_id>')
def hello_world(user_id):
    print(type(user_id))
    return 'users {} '.format(user_id)

自定義轉換器

當系統提供的轉換器並不能滿足我們的要求時,此時我們需要自定義轉換器。需要用到Flask的轉換器基類BaseConverter

自定義轉換器主要做3步:

  1. 建立轉換器類

    from werkzeug.routing import BaseConverter
    class MobileConverter(BaseConverter):
        regex = r'1[3-9]\d{9}'  # 轉換器的正則規則
    
    

    注意:regex名字是固定的

  2. 將轉換器新增到converters中

    app.url_map.converters['mobile'] = MobileConverter
    
  3. 使用自定義的轉換器

    @app.route('/message/<mobile:mobile_num>')
    def send_message(mobile_num):
        print(type(mobile_num))
        return 'mobile num  {} '.format(mobile_num)
    

Request

如果想要獲取其他地方的引數,可以通過Flask提供的全域性物件 request 來獲取。request 中不同的屬性對應不同位置的請求引數。

常見的屬性和說明如下:

屬性 說明
data 記錄請求的資料,並轉換為字串
form 請求中的表單資料
args 請求中的查詢引數
cookies 請求中的cookie資訊
headers 請求中的報文頭
method 請求使用的HTTP方法
url 記錄請求的URL地址
files 請求上傳的檔案

示例:

@app.route('/users')
def get_user_id():
    user_id = request.args.get('user_id')
    return 'your user id is {} '.format(user_id)

接受上傳檔案示例:

@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files['file']
    # with open('./test.png', 'wb') as new_file:
    #     new_file.write(file.read())
    file.save('./test.png') # 可以直接呼叫save方法儲存
    return 'ok'

模板

在專案的目錄下新建名為templates的資料夾,並在此資料夾下新建名為index.html的html檔案。

內容如下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <h1>我的模板內容</h1>
    名字: <span>{{ name }}</span> <br>
    年齡: <span>{{ age }}</span> <br>

</body>
</html>

渲染資料到模板

@app.route('/')
def home():
    uname = '張三'
    uage = '20'
    return render_template('index.html', name=uname, age=uage)