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。
使用方式
使用藍圖可以分為三個步驟:
- 建立一個藍圖物件
users/__init__.py
from flask import Blueprint
users_bp = Blueprint('users', __name__)
from . import views
- 在這個藍圖物件上進行操作,註冊路由,指定靜態資料夾,註冊模板過濾器
users/views.py
@user_bp.route('/profile')
def get_profile():
return 'user profile!'
- 在應用物件上註冊藍圖物件
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步:
-
建立轉換器類
from werkzeug.routing import BaseConverter class MobileConverter(BaseConverter): regex = r'1[3-9]\d{9}' # 轉換器的正則規則
注意:regex名字是固定的
-
將轉換器新增到converters中
app.url_map.converters['mobile'] = MobileConverter
-
使用自定義的轉換器
@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)