flask框架总结
文章目錄
- flask框架總結
- 原理
- 請求上下文原理
- flask握手原理
- flask發送數據加密,解密原理
- 快速啟動flask服務
- app.run()接受參數如下
- app.route()裝飾器接受參數如下
- 動態路由參數
- 處理請求方法
- FBV 方法示例
- CBV方法示例
- flask響應三劍客
- reqeust
- 模板語法jinja2
- for語法
- if語法
- safe過濾器
- Markup
- 傳入函數名
- 自定義標簽
- 自定義過濾器
- extends標簽
- include標簽
- include和extend區別
- 宏指令
- session
- flask配置
- app配置
- 初始化配置
- flask藍圖
- flask中間件
- 自定義錯誤errorhandler
- flask中flash閃現
flask框架總結
特點:短小精悍,支持三方組件,穩定性相對其他框架較差。
web服務端,基于socket制作
原理
wsgi:應用程序網關接口
django使用的是uwsgi
flask使用的是werkzeug(wsgi封裝)
請求上下文原理
在flask中reqeust和session都為公共變量,直接通過flask導入,而不是通過參數傳入視圖函數
實現原理是:
wsgi處理-》打包成ctx=RequestContext(包含reqeust,session)->ctx.push(將當前請求信息存入棧中)-》視圖函數處理-》執行reqeust相關方法時,從棧中獲取數據
{__storage__:{線程號:{"stack":[ctx]}},__ident_func__:get_ident}
get_ident為獲取線程號的方法名
flask握手原理
websocket通信原理
后端
獲取請求體中字符串Sec-WebSocket-Key,拿到key
用magic_string字符串與其拼接,使用sha1加密,再用base64加密
拼接響應頭,添加Sec-WebSocket-Accept字段,發送給瀏覽器
前端瀏覽器
鏈接服務器,發送請求頭,含Sec-WebSocket-Key字段
獲取響應頭,解密,校驗握手是否成功
flask發送數據加密,解密原理
解密
瀏覽器send發送數據過來為bytes類型
情況一: <= 125 當前data_length就為數據長度 125(3-6為mask_key)
情況二:==126 數據長度兩位,3-4字節為數據長度 65535(5-8mask_key)
情況三:==127 數據長度為八位,3-10字節為數據長度 2**64(11-14mask_key)
bytes = decode[i] ^ mask[i%4]
每位用或運算和mask—key的四個數
加密
struct打包
情況一: < 126 struct.pack("B",length)
情況二: == 126 struct.pack("!BH",126,length)
情況三: > 126 struct.pack("!BQ",127,length)
快速啟動flask服務
from flask import Flaskapp = Flask(__name__) #在該模塊中Flask標識,可以傳入任意字符串@app.route('/') #裝飾器第一個參數為路由 def index():return "hello world" # 直接返回字符串到頁面上app.run() # 啟動flaskapp.run()接受參數如下
run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
例如:
app.run(host="127.0.0.1",port=9527,debug=True)
debug為true時,每次修改代碼后,自動重啟服務
app.route()裝飾器接受參數如下
@app.route('/hi2',endpoint="hi2",redirect_to="/",methods=("GET","POST"),defaults={"age":22}) def hi2(age):return redirect('/')endpoint:函數標識,默認為函數名,在反向解析時使用url_for(‘hi2’)可以解析出url。 當函數重名時,只要endpoint不重名即可
redirect_to:不通過視圖函數,直接重定向(永久重定向)
methods:允許請求方法,默認只允許GET,可以傳入一個列表或元組
defaults:默認參數,默認傳入視圖函數的參數,視圖函數必須要有參數來接受
strict_slashes:嚴格匹配,默認值為False,值為True時,地址末尾多一個斜杠也不允許訪問
動態路由參數
可以使用<>方式添加變量名,同時視圖函數也要接受參數,來匹配路由
<a> <int:b> <string:c>
默認參數類型是字符串
處理請求方法
處理請求有CBV和FBV兩種方式
FBV:在視圖中,通過函數類處理請求
CBV:在視圖中,通過類來處理請求
FBV 方法示例
通常我們使用函數加裝飾器方法組成視圖函數
@app.route('/') def index():return "hello world"等價于
def index2():return "hello world1" app.add_url_rule("/index2",view_func=index2)view_func為視圖函數的函數名
CBV方法示例
from flask import viewsdef war(func):def inner(*args,**argv):print("inner")return func(*args,**argv)return innerclass Index3(views.MethodView):methods = ["GET","POST"]decorators = [war]def get(self):return "nice get"def post(self):return "nice post" app.add_url_rule(rule="/test",view_func=Index3.as_view(name="index33"))類需要繼承views.MethodView,類中添加相應請求方法的處理函數(get方法請求,就添加名為get的函數)
methods:默認為只允許get方法訪問
decorators: 將類中每個函數添加裝飾器,每次執行函數時,自動依次執行裝飾器
as_view:將類轉換為相應視圖函數,name為函數標識
flask響應三劍客
from flask import Flask,render_template,redirect,jsonify,send_file @app.route('/') def index():return "hello world"@app.route("/login") def login():return render_template('login.html')@app.route('/hi') def hi():return redirect('/')@app.route("/hello") def hello():return jsonify({"name":"xiaoming","age":16})@app.route("/web") def web():return send_file("./small.png")直接返回字符串,類似于django的HttpResponse
render_template返回模板,類似于django的render
redirect重定向(默認302臨時重定向),和django一樣
jsonify返回json字符串,content-Type為Content-Type: application/json
send_file返回一個本地文件,根據文件不同content-Type不同
reqeust
reqeust為一個全局變量,獲取請求信息,所有請求信息經過wsgi處理后轉換為鍵值對形式存入字典中
from flask import request @app.route('/') def index():print(request.method) #返回當前請求方法print(request.args) #get攜帶的參數鍵值對(字典),get取值print(request.form) #表單提交<form>的結果(字典),get取值print(request.json) #數據格式application/json bytes類型print(request.data) #request定義的格式不存在的 application/xiaowangba bytes類型的數組 print(request.values) #同時獲得url攜帶參數和post請求獲取的參數,get取值如果get和post請求參數重名時,取get請求參數的值因為先序列化form,后序列化args,args同名參數會將其覆蓋return "hello world"request還有url,path等方法
模板語法jinja2
在django和flask中都使用了jinja2語法
變量語法 {{ msg }}
tag標簽語法 邏輯代碼 {% if %}
for語法
遍歷
{% for stu in stu_list %} {% endfor %}獲取字典值時,可以使用下標,[],get方法
<td>{{ student.name }}</td> <td>{{ student["name"] }}</td> <td>{{ student.get("name") }}</td>獲取列表值時,可以使用下標方法或傳入索引
<td>{{ student[0] }}</td><td>{{ student.0 }}</td>if語法
條件判斷
{% if session %} {% elif session1 %} {% else %} {% endif %}示例
{% if student.3 == 'female' %}<input class="form-check-input" type="radio" name="sex" id="female" value="female" checked> {% else %}<input class="form-check-input" type="radio" name="sex" id="female" value="female"> {% endif %}safe過濾器
將變量中字符串渲染成標簽
{{ msg|safe }}
默認情況,字符串不能直接被渲染成字符串,必須使用safe過濾器
Markup
類似于safe,只不是在后端執行
from flask import Markup @app.route('/1') def index1():text_tag = "<p>我是p標簽</p>"text_tag = Markup(text_tag)return render_template("index.html",msg=text_tag)將字符串轉換為標簽,在頁面上渲染
傳入函數名
后端也可以直接向前端傳入函數名,前進接受后直接使用
python
html
{{ add(1,2) }}自定義標簽
自定義全局函數
python
不需要通過參數傳入模板,直接在模板中調用
html
自定義過濾器
自定義全局過濾器
python
html
{{ 5|jiou }}extends標簽
繼承父模板框架,必須卸載最上方
block:在index.html中為占位符,在index2.html中為實際內容
index.html
index2.html
{% extends "index.html" %} {% block container %}<p>新內容</p> {% endblock %}1include標簽
include:導入代碼塊,將代碼塊導入到網頁中
index.html
login.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>登錄</title> </head> <body> 登錄 </body> </html>include和extend區別
include:用于多個html頁面,有相同代碼部分,這部分用include導入,比如導入小廣告
extends:用戶同一主題的頁面,用相同主題,只修改block部分,其他部分不變。extends必須寫在頁面開頭,配合block使用。模板繼承
宏指令
創建標簽,宏指令
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>登錄</title> </head> <body> 登錄 {% macro create_tag(name) %}<p>{{ name }}</p> {% endmacro %}{{ create_tag("xiaoming") }} {{ create_tag("wanghua") }}</body> </html>相當于html中的函數,傳入參數,執行參數
session
session和cookie用戶信息的緩存,cookie一般存放在用戶端,session一般存放在服務端
但是flask原生session是將用戶信息存放在cookie中,也就是用戶端
注意:首先導入session,其次必須要secret_key
session存放在cookie中,鍵session,值(secret_key經過md5序列化+時間戳+session字典中的鍵值)
flask配置
app配置
方法一:
使用字典方式設置
方法二:
使用對象方式
在對象中設置值
初始化配置
flask示例初始化配置
app = Flask(__name__) ''' def __init__(self,import_name, #該參數用來標識實例的(用來區分是否是一個實例化對象,request等)static_url_path=None, #訪問靜態文件的url 默認等于static_folderstatic_folder="static", #靜態文件夾static_host=None, #遠程訪問靜態文件(靜態文件夾不在本地)必須和host_matching一起用host_matching=False,subdomain_matching=False,template_folder="templates", #指定模板文件夾instance_path=None,instance_relative_config=False,root_path=None, ): '''flask藍圖
flask藍圖相當于不能運行的flask實例,用來做插件用
student_add.py
參數一位藍圖實例名,用來區分藍圖與藍圖
參數二藍圖空間標識
注意:藍圖默認static和template和app默認存儲位置相同
注冊藍圖
main.py
即可使用
藍圖中的視圖函數名與app視圖函數名相同時不會出錯,但url_for反向解析時會報錯
flask中間件
flask使用兩種裝飾器類似于django中的中間件
@app.before_request def is_login():white_list = ['/login',]if request.path in white_list:return Noneif session.get("is_login") and session["is_login"] + 3000*60 > time.time():return Noneelse:return redirect('/login')@app.after_request def go(res):print("after")return res自定義錯誤errorhandler
可以自定義404錯誤
@app.errorhandler(404) def errors(*args):print(args)return "沒有找到當前頁面"也可以自定義錯誤頁面
flask中flash閃現
flash存一次,取一次后就銷毀,不占空間。
通常用來上一個位置使用
總結
- 上一篇: 什么是软件测试?软件测试和研发的区别
- 下一篇: 数据分析师要求mysql的_做数据分析师