flask框架
用Python作Web開發的三大框架特色
Django
主要特色是大而全,集成了不少的組件,例如:Admin Form Model等,無論你用不用的到,他都會爲
你提供,一般用於大型Web應用,因爲內部組件足夠強大,因此使用Django能夠作到一鼓作氣,
Django的優勢是大而全,缺點也就露出來,這麼多的資源一次性所有加載,確定會形成cpu資源的浪費
flask
flask原生組件幾乎爲零,只有底層的jinja2(模板)和Werkzeug(服務器),屬於短小精悍型框架,
flask一般用於小型應用和快速構建應用,其強大的第三方庫足以支持一個大型項目
Tornado
主要特色是原生異步非阻塞,在IO密集型和多任務處理上佔據壓倒性的優點,屬於專一性框架,通
經常使用於API後端應用,遊戲服務後臺,其內部實現的異步非阻塞真的是很穩,優勢是異步,缺點是乾淨,連個session也不支持
什麼是flask的框架
web訪問流程
web框架
flask簡介
建立flask的虛擬環境
windos下用pycharm建立flask的虛擬環境
windows下,直接在user目錄中建立一個pip目錄,如:C:\Users\xx\pip,新建文件pip.ini
內容以下
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
利用pycharm的優勢自動建立虛擬環境
寫模板程序
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "hello word"
if __name__ == "__main__":
app.run(port=9001, debug=True)
Flask參數的配置
import_name, #至關於 __name__/"__main__"
static_path=None, #靜態路徑
static_url_path=None, #規定了哪一種類型的url是靜態請求
static_folder='static', #若是是靜態請求,去static文件夾找文件
template_folder='templates', #靜態模板,去templates中找模板文件
instance_path=None, #論壇
instance_relative_config=False #應用程序的配置
加載配置的方式
DEBUG = True 設置爲調試模式
app.config.from_object()
從對象中加載
class Config(object):
DEBUG = True
app.config.from_object(Config)
從配置文件中加載
從config.ini文件中加載的內容爲
DEBUG = True
app.config.from_object("config.ini")
從環境變量中加載(不推薦使用)
經常使用配置的參數
app.debug = True
app.config["DEBUG"] = True
app.run()的三個參數
host="127.0.0.1"
port=9001
debug = True
JSON的數據格式
json中的數據必定要加雙引號("")
json中的數據實際就是一種在特定格式下顯示的字符串
json中的數據通常是POST請求方式
json經常使用的方法
json.dump()
json.dumps() #將字典對象轉化爲標準格式的json字符串,沒有格式化(按照代碼中定義的json格式)
json.load()
json.loads() #將json格式的字符串轉化爲Python對象(字典)
jsonify() #將字典對象轉化爲標準格式的json字符串,格式化顯示
若是JSON數據中有中文,在瀏覽器顯示是unicode編碼,需設置以下:
#將默認的ASCII編碼屏蔽掉,才能在瀏覽器中顯示當前json數據中的具體內容
app.config["JSON_AS_ASCII"] = False
json_data = {
"name": "張三",
"age": 20,
"gender": "男"
}
重定向(redirect)
@app.route("/redirect")
def func_redirect():
#跳轉到百度等其餘網頁
#return redirect("http://www.baidu.com")
#跳轉到當前路徑下的某個文件
return redirect(url_for("要跳轉的函數名",是否攜帶參數))
提供模板文件(render)
在當前路徑中必許有一個文件夾叫templates,其中存放html中的模板代碼,不然會有一個
jinja2.exceptions.TenplatesNotFound的錯誤
@app.route("/home")
def home():
return render_template("/test.html") //直接跳轉到test.html視圖中
自定義狀態碼
如何自定義狀態碼
@app.route('/login')
def func():
return 'login',666 #其實是一個元祖,猶如 return("login",666)
路由的參數配置
url中參數的定義
尖括號(<int:result>)中存放的是轉換器和參數,參數的名稱以及對參數類型的限制
請求類型的指定
默認是GET的請求模式
app.route("",methods=["GET","POST"]) #app.route()定義規則
用request.method獲取當前請求,查看當前請求是那種請求方式
自定義轉換器
自定義一個類繼承BaseConverter
重寫父類的regex變量
在app.url_map.converters這個字典中增長一組當前所定義的轉換器數據(本身定義名字)
像使用int轉換器同樣的使用它
讓自定義的轉換器可以接收參數
自定義一個類繼承BaseConverter
用super重寫init方法,在init方法中須要有url_map這個參數以及正則表達式的參數*args,這個參數是咱們在使用轉換器的時候咱們本身傳遞過來的
在app.url_map.converters這個字典中增長一組當前所定義的轉換器數據
@app.route("/demo/<re(r'a[0-9]{6}'):uname>")
BaseConverter中的其餘兩個參數的執行時機
轉換器to_python
匹配和調用的前後順序:必定是先匹配,再調用視圖函數
to_python調用的時機:匹配了url以後,在調用視圖函數以前
to_python的做用:用來決定視圖函數中的參數的值
轉換器to_url
to_url是給url_for這個函數使用
做用:決定url_for 中咱們傳遞的參數,最終的地址欄中所呈現出來的狀態
請求錯誤的處理方式
主動拋出狀態碼(abort)
統一處理錯誤(@app.errorhandler(404/500/Exception))
![](http://static.javashuo.com/static/loading.gif)
@app.route("/")
def index():
return "hello word"
@app.route("/login")
def func_login():
result = 4/0
abort(404)
return "login......"
@app.route("/register")
def func_register():
result = 100 + "111"
abort(500)
return "regsit......"
@app.errorhandler(ZeroDivisionError)
def errorhandler(e):
return "除數不能爲0"
@app.errorhandler(TypeError)
def errorhandler(e):
return "整型和字符型的數據不能進行運算"
@app.errorhandler(404)
def func_browser(e):
return "瀏覽器正在更新,請稍等"
@app.errorhandler(500)
def func_server(e):
return "服務器繁忙,請稍後"
@app.errorhandler(Exception)
def errorhandler(e):
return "頁面正在加載,請稍後"
if __name__ == "__main__":
app.run(port=9001, debug=True)
View Code
鉤子函數(回調函數)
before_first_request
時機:
在開啓服務器以後的第一次請求
before_request
時機:
每個請求以前
使用場景:
對請求統一進行處理,好比黑名單功能 綁定IP地址remote_addr=="192.168.15.60"
after_request
時機:
每一次沒有報錯的請求以後
場景:
統一的對沒有報錯的響應進行響應頭信息增長,如:
response.headers["Content-Type"] = "application/json"
teardown_request
時機:
每一次請求以後,都會調用
場景:
對錯誤進行收集
request請求知識
獲取請求類型:request.method #獲取當前是哪種請求方式
獲取請求的ip地址:request.remote_addr #訪問IP地址
獲取請求的數據:
request.args.get("xxx") #GET請求數據 獲取URL中的參數
request.form.get("xxx") #POST請求數據 獲取form表單中的數據
request.files.get("xxx") #獲取文件數據
list(request.form.keys("name","pwd"))
request.values.get("user") #取不到返回None
request.values["user"] #直接取用戶名
request.values.to_dict() #獲取當前表單提交中的全部數據
request.data() #request是基於mimetype進行處理的
request.headers()
print(type(request.headers))
"""
Host: 127.0.0.1:5000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1:5000/home
Content-Type: application/x-www-form-urlencoded
Content-Length: 26
Cookie:csrftoken=vDIozqveCEfArdYXlM6goHVlSQEn7h4bDygNphL2Feas60DiM2di0jlqKfxo7xhA
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
"""
#獲取當前的url路徑
print(request.path) #/req
# 當前url路徑的上一級路徑
print(request.script_root)
# 當前url的所有路徑
print(request.url) # http://127.0.0.1:5000/req
# 當前url的路徑的上一級所有路徑
print(request.url_root ) # http://127.0.0.1:5000/
注意事項
若是url和form中的Key重名的話,form中的同名的key中value會被url中的value覆蓋
#http://127.0.0.1:5000/req?id=1&user=20
print(request.values.to_dict()) #{'user': 20 'pwd': 'DragonFire', 'id': '1'}
請求參數攜帶參數的幾種方式
一、http://127.0.0.1/login/zhangan/123456 #直接在地址欄中輸入
二、http://127.0.0.1/login?uname=zhangsan&upwd=123456 #利用GET請求
三、http://127.0.0.1/login #利用POST請求
uname=zhangsan&upwd=123456
狀態的保持
http默認是無狀態的,前一個請求和後一個請求之間是獨立的,這個是http協議的特性
基於他的這種特性,若是想讓不一樣請求之間能夠有關聯,須要引入cookie機制
設置cookie
cookie是存儲在瀏覽器端的鍵值字符串,會伴隨着瀏覽器的自求自動提交到服務器,不一樣的網站不能共享cookie,保存在本地瀏覽器中安全性較低,
瀏覽器第一次發起登陸請求該網站時,,若是服務器檢測到帳號和密碼正確,就會給該請求設立一個cookie,瀏覽器會自動把cookie保存起來,
下一次請求登陸時會把該cookie帶到服務器,服務器從當前請求中獲取當前所使用的cookie,根據cookie就能夠判斷當前是誰登陸
![](http://static.javashuo.com/static/loading.gif)
from flask import Flask, make_response, request
app = Flask(__name__)
# 存儲在客戶端
@app.route("/")
def index():
user = request.cookies.get("user_name")
id = request.cookies.get("user_id")
return "%s---%s"%(user,id)
@app.route("/login")
def login():
response = make_response("success")
response.set_cookie("user_name", "zhangsan",max_age=3600)
response.set_cookie("user_id", "2",max_age=3600)
# return "success"
return response
@app.route("/logout")
def logout():
response = make_response("success")
response.delete_cookie("user_name")
response.delete_cookie("user_id")
return response
if __name__ == "__main__":
app.run(port=9001, debug=True)
View Code
設置session
存儲在服務器上,對於敏感、重要的信息,建議要存儲在服務器端,不能存儲在瀏覽器中,如用戶名、餘額、等級、驗證碼等信息在服務器端進行狀態保持的方案就是session
session依賴於cookie
![](http://static.javashuo.com/static/loading.gif)
from flask import Flask, session
app = Flask(__name__)
app.config["SECRET_KEY"] = "wxb"
# 存儲在服務器上
@app.route("/")
def index():
user_id = session.get("user_id", "")
user_name = session.get("user_name", "")
return "%s---%s"%(user_id,user_name)
@app.route("/login")
def login():
session["user_name"] = "lisi"
session["user_id"] = "1"
return "success"
@app.route("/logout")
def logout():
session.pop("user_name",None)
session.pop("user_id",None)
return "success"
if __name__ == "__main__":
app.run(port=9001, debug=True)
View Code
上下文管理器(相似全局變量)
請求上下文
request 當請求發生時,調用視圖函數,觸發request.get()
session
拋出異常 RuntimeError:working outside of request context
應用上下文
current_app current_app.config.get("DEBUG")
g變量 通常做用於跨py文件,先用g.num存取變量,在再另外一個py文件中取值
拋出異常 RuntimeError:working outside of application context
flask_script
pip install flask_script
from flask import Flask
flask_script import Manager
app = Flask(__name__)
manager = Manager(app)
@app.route("/")
def index():
return "hello world"
if __name__ == "__main__":
manager.run(debug=True)
flask中能夠return的幾種寫法
1)return "字符串"
2)return "字符串",666
3)return redirect("/")
4)response = make_response("字符串")
response.set_cookie('username', username)
return response
5)return render_template("demo.html",mylist=["haha","hehe"])
6)response = make_response(render_template("index.html"))
response.set_cookie('username', username)
return response
7)response = redirect(url_for('transfer'))
response.set_cookie('username', username)
return response