一、.基于裝飾器的session通路控制,endpoint路由參數可以解決視圖函數重名的情況。
下面我有一個簡單的需求,就是一個網站有三個頁面,分别是home、index和login界面,使用者隻有當登陸後才可以正常通路home和index頁面,通過裝飾器的方法來實作。接下來看代碼
from flask import Flask, request, render_template, redirect, Markup, session
app = Flask(__name__)
app.secret_key = "abcdefghijklmn"
def wrapper(f):
def inner(*args, **kwargs):
if session.get("user"):
ret = f(*args, **kwargs)
return ret
else:
return redirect("/login")
return inner
@app.route("/login", methods=("GET","POST"))
def login():
if request.method == "GET":
return render_template("login.html")
if request.method == "POST":
username = request.form.get("username")
session["user"] = username
return "登陸成功"
@app.route("/home", methods=("GET", "POST"))
@wrapper
def home():
return "這是home界面的内容"
@app.route("/index")
def index():
return "我是index界面的内容"
app.run()
當我們隻對home視圖函數加上認證裝飾器時實作了我們的需求,但是如果你給index也加上認證裝飾器時你就會發現Flask項目啟動不起來了,會報一個這樣的錯誤:

image.png
這是因為,當我們對一個以上的視圖函數添加了認證裝飾器後 ,認證裝飾器會将視圖函數名替換成裝飾器的内層函數名inner,在記憶體中就會出現視圖函數名重複的情況,這樣Flask的路由裝飾器裝飾視圖函數時就會報錯,解決這個錯誤的方法就是給路由的endpoint參數指定視圖函數名,即:
from flask import Flask, request, render_template, redirect, Markup, session
app = Flask(__name__)
app.secret_key = "abcdefghijklmn"
def wrapper(f):
def inner(*args, **kwargs):
if session.get("user"):
ret = f(*args, **kwargs)
return ret
else:
return redirect("/login")
return inner
@app.route("/login", methods=("GET","POST"))
def login():
if request.method == "GET":
return render_template("login.html")
if request.method == "POST":
username = request.form.get("username")
session["user"] = username
return "登陸成功"
@app.route("/home",endpoint="home", methods=("GET", "POST"))
@wrapper
def home():
return "這是home界面的内容"
@app.route("/index",endpoint="index")
@wrapper
def index():
return "我是index界面的内容"
app.run()
二、Flask中的路由參數
- @app.route()
@app.route(
"/<age>" // 動态路由參數,預設是string,也可以是"/<int:age>"
redirect_to = "/login" //不經過視圖函數直接重定向指定url
defaults = {"age": 999} //指定預設參數
endpoint = "home" //路由别名,用于反向生成URL,即: url_for('名稱')
methods = ("GET", "POST") //請求方式
strict_slashes = False //是否嚴格比對url最後的"/",例:http://127.0.0.1:5000/home 和
//http://127.0.0.1:5000/home/
)
常用動态路由參數有以下五種,所有的路由系統都是基于以下對應關系來處理:
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
url_for的用法
from flask import Flask,url_for
app = Flask(__name__)
@app.route("/index/<int:age>",endpoint="index")
def index(age):
url = url_for("index",age = age)
print(url) // "/index/122"
return "我是index界面的内容"
app.run()
- app.add_url_rule()方法:比@app.route()多了一個 view_func=view_func參數,其他的相同。
三、Flask配置檔案
1. 初始化Flask執行個體時的配置
app = Flask(_name_,template_folder="template",static_folder="static",static_url_path="/static")
- static_url_path = "/static_folder" 通路靜态目錄檔案時的位址 預設值是等于static_folder的名字,(應用場景描述:當後端static檔案名修改後,加入前端頁面使用了大量的之前的static路徑,可以将static_url_path參數設定為老的,這樣就可以不用修改前端代碼了。)
- static_folder = "static" 靜态檔案的存放路徑
- template_folder='templates' 模闆路徑
2. Flask執行個體的配置 app配置
-
方式一、app.config["DEBUG"] = True
PS: 由于Config對象本質上是字典,是以還可以使用app.config.update(...)
- 方式二、app.config.from_object(obj)
class obj():
DEBUG = True
SECERT_KEY = "123123"
-
方式三、app.config.from_pyfile("settings.py")
settings.py
DEBUG = True
SECERT_KEY = "123123"
-
方式四、app.config.from_envvar("環境變量名稱")
PS:環境變量的值為python檔案名稱名稱,内部調用from_pyfile方法
-
方式五、app.config.from_json("json檔案名稱")
PS: JSON檔案名稱,必須是json格式,因為内部會執行json.loads
-
方式六、app.config.from_mapping({'DEBUG':True})
PS:字典格式
四、Flask的藍圖
藍圖”和一個Flask應用對象很相似,但是并不是一個Flask應用對象。它是可以注冊到Flask應用上的一系列操作(對于此的了解,後文會詳細講到)。使用“藍圖”,可以實作以下的一些功能:
- 将Flask應用“分割”為一系列“藍圖”的集合,簡化了大型應用工作的方式;
- 在Flask應用上,以 URL 字首和或子域名注冊一個藍圖。可以以不同的URL多次注冊一個藍圖;
- 通過藍圖提供模闆過濾器、靜态檔案、模闆和其它功能。
第一步:藍圖的建立(藍圖的示例和Flask的執行個體參數一樣)
add.py
from flask import Blueprint,render_template
bp = Blueprint("bp", __name__,
template_folder="blueprint_temp",
static_folder="blueprint_static",
static_url_path="/static2")
@bp.route("/add")
def add():
return render_template("add.html")
第二步:注冊藍圖:
from flask import Flask
import add
app = Flask(\__name__)
app.register_blueprint(add.bp)
if __name__ == '__main__':
app.run()
五、Flask裡面的擴充,相當于django中的中間件
1.before_request 再請求進入視圖函數之前作出處理 return None;before_request是順序執行
2.after_request 在請求結束視圖函數之後,傳回用戶端之前 ,要有參數和傳回值,after_request是逆向執行
3.errorheadler(404) 自定制錯誤提示,自定義的函數必須有參數
- before_request和after_request裝飾器的使用
from flask import Flask, request, render_template, redirect, Markup, session, url_for
app = Flask(__name__)
app.secret_key = "abcdefghijklmn"
@app.before_request
def process_request1():
print('process_request1')
@app.after_request
def process_response1(response): # 必須有參數
print('process_response1')
return response # 必須有傳回值
@app.before_request
def process_request2():
print('process_request2')
@app.after_request
def process_response2(response): # 必須有參數
print('process_response2')
return response # 必須有傳回值
@app.route("/login", methods=("GET", "POST"))
def login():
if request.method == "GET":
return render_template("login.html")
if request.method == "POST":
username = request.form.get("username")
session["user"] = username
return "登陸成功"
app.run()
通路login視圖函數後的控制台輸出結果為:
process_request1
process_request2
process_response2
process_response1
通過代碼的列印結果可以看出,before_request順序執行;after_request逆向執行
- errorhandler(404)的使用
@app.errorhandler(404)
def errors(code_or_exception): //必須有參數
return "錯誤" //可以傳回字元串,html,重定向等
六、閃現:flash
session存在在服務端的一個字典裡面,session儲存起來,取一次裡面還是有的,直到你删除之後才沒有了。
flash的本質:flash是基于session建立的,flash支援往裡邊放值,隻要你取一下就沒有了,相當于pop了一下。不僅吧值取走,而且吧session裡的東西去掉。
flash的使用:get_flashed_messages()和flash("内容")
from flask import Flask,session,render_template,request,flash,get_flashed_messages
import flask_config
app = Flask(__name__)
@app.route("/index")
def index():
res = get_flashed_messages()
if not res:
res = [""]
flash("你剛才通路了index")
return render_template("index.html",msg=res[0])
@app.route("/home")
def index1():
res = get_flashed_messages()
if not res:
res = [""]
flash("你剛才通路了home")
return render_template("index.html",msg=res[0])
if __name__ == '__main__':
app.run()
七、Flask的send_file使用
from flask import Flask,send_file
app = Flask(__name__)
@app.route("/index", endpoint="index")
def index():
return send_file(file_path) //send_file()的作用是打開檔案傳輸内容
app.run()
八、Flask的jsonify的使用
- json.dumps的作用是序列化資料
- jsonify的作用是将後端資料json序列化,打包一個 content-Type:application/json 傳回給用戶端
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/index", endpoint="index")
def index():
#return json.dumps({123:"34"}) //傳給前端的是json資料,僅此而已!
return jsonify({123:"34"})) //序列化資料,将響應頭的content-Type: 更改為application/json
app.run()