Day1
flask依賴包
當執(zhí)行pip install flask后,會發(fā)現(xiàn)多了這些依賴
1.Flask flask核心庫
2.Jinja2 模板渲染庫
3.Markupsafe 安全標簽庫 只要flask返回模板或者標簽時健无,都會依賴它
4.Werkzeug 德文“工具”的意思,應用程序網關接口庫 WSGI告希,flask項目啟動基于Werkzeug
啟動項目實現(xiàn)hello world
注意:盡量不要使用pycharm中自帶的flask模板創(chuàng)建flask
啟動服務:
from flask import Flask # 導入flask核心類,創(chuàng)建Flask應用對象
app = Flask(__name__) # app-application,實例化的flask對象
app.run() # 啟動Flask
實現(xiàn)helloworld
from flask import Flask
app = Flask(__name__)
@app.route("/index"): # 為flask應用對象增加路由
def index(): # 與路由綁定的視圖函數
return "hello world" # 返回,相當于響應
if __name__ == '__main__':
app.run()
response
1.return "hello world"
2.return render_template("xxx.html")
html文件的默認存放路徑是/templates
下
3.return redirect("/home")
重定向路由
@app.route("/home")
def home():
return "home主頁"
@app.route("/red")
def red():
return redirect("/home")
當訪問/red
時宫盔,http status 302盏浙,3xx表示當前瀏覽器要做出指令眉睹。
請求時荔茬,response header中有參數location:http://127.0.0.1:5000/home,就會根據location對應的地址跳轉竹海。
小知識:pycharm中redirect("/home")
的("/home")
會有小黃塊慕蔚,提示的意思是,不知道這個/home存在或者不存在斋配,所以可以把templates標記為templates folder孔飒,這樣黃色的小塊就不在了。
4.return send_file("文件路徑")
打開艰争,并返回文件內容十偶,并自動識別文件類型,在response header中加入园细,不能識別的類型惦积,僅會做下載處理。(其實所有的都會下載猛频,只是瀏覽器能夠識別圖片狮崩、map4毡熏,所以給你播放出來了蘸炸。并且把Content-Type作為標簽放到了頁面上淹禾,識別文件類型的能力取決于瀏覽器铲咨,如wma文件粹湃,微軟自帶的錄音文件格式歧斟,所以只有ie瀏覽器能識別萨惑,而其他瀏覽器不能識別)
如:
放一個jpg文件,response header中Content-Type: image/jpeg
放一個mp4文件壤追,response header中Content-Type: video/mp4
Content-Type :文件類型
二進制文件的第一行,會寫文件類型行冰,如果沒有寫文件類型溺蕉,就是普通的文本文件伶丐。
5.jsonify 返回標準格式
@app.route("/get_json")
def get_json():
data = {"username": "tony"}
return jsonify(data)
Content-Type: application/json
flask1.1.1以上版本,可以直接使用 return data疯特,即return一個字典時哗魂,就是在執(zhí)行jsonify,不建議使用漓雅,因為要兼容低版本录别。
修改app.config['JSONIFY_MINETYPE'],就是修改jsonify解析時返回的response header中Content-Type
request
1.請求方式
@app.route("login",method=["GET","POST"]) #在路由后面添加路由支持的請求方式
2.獲取請求參數
@app.route("/login", methods=["GET", "POST"])
def login():
print(request.form)
print(request.url)
print(request.url_charset)
print(request.url_root)
print(request.url_rule)
print(request.values)
print(request.values.to_dict())
print(request.args.to_dict())
data = {"username": "tony"}
return jsonify(data)
request.form
邻吞,獲取formdata中的數據
to_dict()
组题,如果類型是ImmutableMultiDict,都可以用to_dict()
request.url
抱冷,獲取請求的完整url
request.url_charset
崔列,獲取請求url的編碼方式
request.url_root
,獲取請求url的ip和port
request.url_rule
旺遮,獲取請求路由
request.values
赵讯,獲取post、get請求的請求數據趣效,包括url和formdata中的數據
request.args
瘦癌,獲取請求參數,類型是ImmutableMultiDict,支持to_dict()跷敬,get(key)
3.上傳文件讯私、保存文件
html文件部分
<body>
<form action="http://127.0.0.1:5000/upload" method="post" enctype="multipart/form-data">
上傳文件:<input type="file" name="my_file">
<button type="submit">提交</button><br>
</form>
后端:
@app.route("/upload", methods=["POST"])
def upload():
print(request.files) # FileStorage對象是Flask的文件特殊對象
# 打印結果:ImmutableMultiDict([('my_file', < FileStorage: '' ('application/octet-stream') >)])
my_file = request.files.get("my_file") # 獲取FileStorage文件對象
my_file.save(my_file.filename) # 保存文件
return "200 ok"
4.其他數據
request.headers
request.cookies
request.path==request.url_rule
request.host
request.host_url
5.特殊的提交方式獲取
content-type:application/json
這時,request.form西傀、request.arg是沒有數據斤寇,放在request.json中
request.json:獲取content-type:application/json 時提交的數據
content-type無法被識別時,放在request.data中
request.data:獲取content-type無法被識別或不包括有form字眼拥褂,原始請求中的數據 b''
6.登錄示例:
前端:
<body>
<form action="http://127.0.0.1:5000/login" method="post">
用戶名:<input type="text" name="username"><br>
密碼:<input type="password" name="pwd"><br>
<button type="submit">提交</button><br>
</form>
flask
@app.route("/index")
def index():
return "歡迎進入首頁"
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "GET":
return render_template("login.html")
if request.method == "POST":
if request.form.get("username") == "ltx" and request.form.get("pwd") == "123":
return redirect("/index")
else:
return "error,用戶名或密碼錯誤"
Flask session
Session 服務器端鍵值對
Cookie 客戶端的鍵值對
flask的session交由客戶端保管機制:
1.開啟session[username]=123
{
username:123
}
2.序列化字典==字符串
3.加密字符串SecretKey 密鑰字符串
接收反序列化session
1.從cookie中獲取到一個叫session key的值
eyJ1c2VyIjoibHR4In0.Y2vCsg.VQloai4PfMQHN_gOp_bLUvdaEkQ
2.通過SecretKey 解密session
3.反序列化成字典
@app.route("/index")
def index():
if session.get("user")=="ltx": #判斷session的用戶名是否正確
print(session.get("user"))
return "歡迎進入首頁"
else:
return redirect("/login")
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "GET":
return render_template("login.html")
if request.method == "POST":
if request.form.get("username") == "ltx" and request.form.get("pwd") == "123":
session["user"]=request.form.get("username") #新增session
return redirect("/index")
else:
return "error,用戶名或密碼錯誤"
Jinja2
{{}} 引用變量參數
{%%} 邏輯代碼
jinja2的簡單實用:變量娘锁、循環(huán)、if判斷
# 模擬數據庫
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}
STUDENT_LIST = [
{'name': 'Old', 'age': 38, 'gender': '中'},
{'name': 'Tony', 'age': 31, 'gender': '男'},
{'name': 'EDU', 'age': 39, 'gender': '女'}
]
STUDENT_DICT = {
1: {'name': 'Old', 'age': 38, 'gender': '中'},
2: {'name': 'Tony', 'age': 31, 'gender': '男'},
3: {'name': 'EDU', 'age': 39, 'gender': '女'}
}
stuinfo.html
<body>
{{stu_info}}
<table border="1">
<tr>
<td>name</td>
<td>age</td>
<td>gender</td>
</tr>
<tr>
<td>{{stu_info.name}}</td>
<td>{{stu_info.get("age")}}</td>
<td>{{stu_info["gender"]}}</td>
</tr>
</table>
{{stu_list}}
<table border="1">
<tr>
<td>name</td>
<td>age</td>
<td>gender</td>
</tr>
{% for stu in stu_list %} <!--for循環(huán)-->
<tr>
<td>{{stu.name}}</td>
<td>{{stu.get("age")}}</td>
<td> <!--if判斷-->
{% if stu["gender"]!='男' and stu["gender"]!='女'%}
酷兒
{% else %}
{{stu["gender"]}}
{% endif %} <!--if結束-->
</td>
</tr>
{% endfor %} <!--for循環(huán)結束-->
</table>
{{stu_dict}}
<table border="1">
<tr>
<td>id</td>
<td>name</td>
<td>age</td>
<td>gender</td>
</tr>
{% for foo,item in stu_dict.items() %}
<tr>
<td>{{foo}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.gender}}</td>
</tr>
{% endfor %}
</table>
</body>
flask
# 1.查看STUDENT放在studentinfo頁面
@app.route("/stu")
def stu():
return render_template("stuinfo.html", stu_info=STUDENT,stu_list=STUDENT_LIST,stu_dict=STUDENT_DICT)
可以自己創(chuàng)建一個標簽饺鹃,傳入參數:
Day2
Flask路由參數
1.endpoint
不能重復莫秆,對應視圖函數 ,endpoint默認是視圖函數名悔详。
請求時镊屎,通過路由找到endpoint,再通過endpoint找到對應的視圖函數。
是否能反向操作茄螃,能通過endpoint找回路由嗎缝驳?
通過url_for
反向創(chuàng)建路由。
@app.route("/look_test", endpoint="/look")
def look():
print(url_for("/look")) # 通過endpoint找到路由,所以結果是:/look_test
return "999"
2.methods
支持的請求方式用狱,列表形式:methods=["GET","POST"]
3.redirect_to
永久重定向运怖,308,沒有進入到視圖層面直接跳轉夏伊。
正常情況下:
請求-->路由匹配-->通過路由找到endpoint-->通過endpoint找到視圖函數
redirect_to:
請求-->路由匹配時摇展,發(fā)現(xiàn)有redirect_to,立即返回署海,不用再走后面的部分吗购。
應用場景:當前地址不存在時医男,直接給你跳轉到redirect_to的地址砸狞。api發(fā)生變更了,老用戶沒有新的訪問地址镀梭,可以使用redirect_to刀森。
4.strict_slashes
對url最后的/是否嚴格。
strict_slashes=True
嚴格:url最后的有/不能訪問报账,404
strict_slashes=False
不嚴格:url最后的有/也可以訪問
5.default
默認參數研底,如果有默認參數,視圖函數中一定要接收參數透罢,否則就會異常榜晦。
6.動態(tài)參數
<類型:變量>
類型:int string
@app.route("/look/<int:page>",methods=["GET"])
def look(page):
print(page)
return "這是第{}頁".format(page)
訪問:http://127.0.0.1:5000/look/10
@app.route("/look/<folder>/<filename>", methods=["GET"])
def look(folder, filename):
filepath = os.path.join(folder, filename)
return send_file(filepath)
傳入不帶類型的,不寫默認為string
@app.route("/look/<folder>/<filename>", methods=["GET"])
def look(folder, filename):
filepath = os.path.join(folder, filename)
return send_file(filepath)
Flask 初始化(實例化)配置
app = Flask(__name__)
從Flask跳轉進去羽圃,init參數如下:
1.template_folder
template模板路徑乾胶,默認為
templates
app = Flask(__name__,template_folder="templates_new")
2.static_folder
靜態(tài)文件路徑,默認為static
,static_folder的實現(xiàn)方式就是send_file朽寞。
在根目錄下新建static
和image
文件夾识窿,分別方上1.jpg和2.jpg
訪問:http://127.0.0.1:5000/image/2.jpg
,報錯404脑融,
訪問:http://127.0.0.1:5000/static/1.jpg
喻频,展示圖片,跟send_file效果一樣肘迎。
修改static_folder路徑app = Flask(__name__,static_folder="image")
甥温,訪問:http://127.0.0.1:5000/image/2.jpg
,展示圖片妓布,而訪問:http://127.0.0.1:5000/static/1.jpg
報錯404姻蚓。
3.static_url_path
靜態(tài)文件訪問路徑,默認值是static_folder
4.static_host
靜態(tài)文件訪問服務秋茫,比如:
<img src="/static/2.jpg" alt="">
也能訪問到圖片史简,因為自動拼接出host。
Flask config配置
1.app.default_config
默認配置
default_config = ImmutableDict(
{
"ENV": None,
"DEBUG": None,
"TESTING": False,
"PROPAGATE_EXCEPTIONS": None,
"SECRET_KEY": None,
"PERMANENT_SESSION_LIFETIME": timedelta(days=31),
"USE_X_SENDFILE": False,
"SERVER_NAME": None,
"APPLICATION_ROOT": "/",
"SESSION_COOKIE_NAME": "session",
"SESSION_COOKIE_DOMAIN": None,
"SESSION_COOKIE_PATH": None,
"SESSION_COOKIE_HTTPONLY": True,
"SESSION_COOKIE_SECURE": False,
"SESSION_COOKIE_SAMESITE": None,
"SESSION_REFRESH_EACH_REQUEST": True,
"MAX_CONTENT_LENGTH": None,
"SEND_FILE_MAX_AGE_DEFAULT": None,
"TRAP_BAD_REQUEST_ERRORS": None,
"TRAP_HTTP_EXCEPTIONS": False,
"EXPLAIN_TEMPLATE_LOADING": False,
"PREFERRED_URL_SCHEME": "http",
"JSON_AS_ASCII": None,
"JSON_SORT_KEYS": None,
"JSONIFY_PRETTYPRINT_REGULAR": None,
"JSONIFY_MIMETYPE": None,
"TEMPLATES_AUTO_RELOAD": None,
"MAX_COOKIE_SIZE": 4093,
}
)
DEBUG 開啟代碼編輯時重啟、Log打印級別最低圆兵、錯誤信息透傳
TESTING 無限接近生產跺讯、不會開啟代碼編輯重啟、Log打印級別較高殉农、錯誤信息不透傳
SECRET_KEY 設置secret_key刀脏,生成session,前面說過
app.config["SECRET_KEY"]="@@#!#!@"
app.secret_key="@@#!#!@"
# 效果都是一樣的,但app.config["SECRET_KEY"]是直接改配置超凳,效率更高
PERMANENT_SESSION_LIFETIME session的生命周期愈污,默認是31天,如果修改值的話轮傍,單位是秒,默認值timedelta(days=31)
代表31天對應的秒暂雹。app.config["PERMANENT_SESSION_LIFETIME"]=3600*24
SESSION_COOKIE_NAME 存放在瀏覽器cookie中session名,第一個字符不能是空格
JSONIFY_MIMETYPE jsonify的標準格式创夜,前面有說過
2.Flask 快速配置
使用app.config.from_object()快速切換不同環(huán)境配置
在settting.py存放各項配置
class DebugConfig: # 開發(fā)環(huán)境
DEBUG = True
SECRET_KEY = "123!@#$%%^"
class TestingConfig: # 測試環(huán)境
DEBUG = False
SECRET_KEY = "正式環(huán)境需要一個很復雜的SECRET_KEY"
導入 from setting import DebugConfig,TestingConfig
,使用app.config.from_object(TestingConfig)
或app.config.from_object(DebugConfig)就能快速切換不同環(huán)境的配置
from flask import Flask
from setting import DebugConfig,TestingConfig
app = Flask(__name__)
app.config.from_object(TestingConfig)
@app.route("/index")
def index():
return "歡迎你呀"
if __name__ == '__main__':
app.run()
BluePrint 藍圖
藍圖的作用是 :功能隔離杭跪、路由隔離
1.藍圖示例一:
根目錄下,有程序的入口:s2-bp.py
,其他的模塊app_01
驰吓。
s2-bp.py
from flask import Flask
app = Flask(__name__)
# 建立藍圖注冊
from app_01.views import user
app.register_blueprint(user)
if __name__ == '__main__':
app.run()
在app_01下views.py文件
from flask import Blueprint
# BluePrint 當作一個不能run的Flask實例
user = Blueprint("user", __name__) # 參數:先是藍圖的名字
@user.route("/login")
def login():
return "BP login"
此時訪問:127.0.0.1:5000/login ,返回BP login
2.藍圖示例二
多個模塊有同個路由涧尿,比如一個模塊app_01
是管理后臺的登錄接口,一個模塊app_02
有C端用戶登錄接口檬贰。使用url_prefix
url前綴參數解決姑廉。
s2-bp.py
from flask import Flask
app = Flask(__name__)
# 藍圖 建立藍圖注冊
from app_01.views import user
from app_02.views import app_user
app.register_blueprint(user)
app.register_blueprint(app_user)
if __name__ == '__main__':
app.run()
app_01下的views.py
from flask import Blueprint
user = Blueprint("user", __name__,url_prefix="/admin") # 添加前綴
@user.route("/login")
def login():
return "admin 管理端 BP login"
app_02下的views.py
from flask import Blueprint
app_user = Blueprint("app_user", __name__,url_prefix="/shop")
@app_user.route("/login")
def login():
return "shop商城 BP login"
在訪問路由時,加上對應的前綴翁涤,如:
訪問http://127.0.0.1:5000/shop/login
,是訪問app_02中的login
訪問http://127.0.0.1:5000/admin/login
是訪問app_01中的login
Flask 特殊裝飾器
@app.before_request
@app.after_request
@app.errorhandler(4xx or 5xx)
1.@app.before_request
請求進入視圖函數之前
2.@app.after_request
請求結束桥言,返回響應客戶端之前
定義函數的順序:be1--be2--be3--af1--af2--af3
正常 : be1--be2--be3--vf--af3--af2--af1
異常: be1--be2--阻斷--af3--af2--af1
3.@app.errorhandler(4xx or 5xx) 自定義錯誤處理
@app.errorhandler(404)
def error404(ErrorMassage):
print(ErrorMassage)
return "頁面{}不存在".format(request.path)
Flask endpoint補充
沒懂 有機會再學
Day3
Flask 藍圖結構
1.回顧藍圖
前面翻翻吧
2.一個簡單的藍圖結構
根目錄下新建一個app01文件夾:
-static
-templates
-views
-models.py
根目錄下新建一個manage.py文件
在app01下的__init__.py
文件中:
from flask import Flask
from app01.views.user import user_bp
def create_app():
app = Flask(__name__)
# 配置
app.config["DEBUG"]=True
# 注冊藍圖
app.register_blueprint(user_bp)
return app
views下的user.py
from flask import Blueprint
user_bp = Blueprint("user", __name__)
@user_bp.route("/login")
def login():
return "登陸成功"
根目錄下manage.py
from app01 import create_app
app=create_app()
if __name__ == '__main__':
app.run()
在__init__.py
文件創(chuàng)建Flask實例、配置config迷雪、注冊藍圖
在manage.py調用app.run()方法
views.py 注冊路由限书、視圖函數
使用python manage,py
啟動項目。
Flask CBV
flask中有兩種視圖章咧,一種是基于函數的視圖FBV倦西,一種是基于類的視圖CBV
flask視圖函數注冊路由的本質:
其實,route裝飾器內部也是通過調用add_url_rule()方法實現(xiàn)的路由注冊赁严,只是route裝飾器看起來更加美觀扰柠。
from flask import Flask, views # 導入CBV的視圖基類
app = Flask(__name__)
class Login(views.MethodView): # 繼承CBV視圖基類的最高類
def get(self): # get方法的視圖函數實現(xiàn)
return "GET OK 200"
def post(self):
return "POST OK 200"
# 為CBV添加路由
app.add_url_rule("/login", view_func=Login.as_view(name="login"))
if __name__ == '__main__':
app.run()
as_view
把視圖類轉化為視圖函數
Flask 監(jiān)聽端口 數據傳遞
app.run("127.0.0.1",5000)
IP對應本機訪問IP,如果是0.0.0.0表示本機所有IP
端口對應應用程序
應用層:
瀏覽器-端口9528疼约,對應用192.168.14.26:9527
發(fā)起請求時卤档,傳遞了b'' HTTP 1.1 / GET\t\n
網卡b'' HTTP 1.1 / GET\t\n
傳遞給操作系統(tǒng)
操作系統(tǒng) 解包 根據端口9527--傳遞給9527
WSGI:9527收到b'' HTTP 1.1 / GET\t\n
,F(xiàn)lask讓WSGI把這些數據轉換成對象environ
Flask收到WSGI轉換的environ對象request_class(request類)程剥,轉換為Flask的request樣式劝枣,比如請求參數,轉換為request.form
Flask-session
第三方組件
flask-session是flask框架的session組件,由于原來flask內置session使用簽名cookie保存(交給客戶端保管不安全)舔腾,該組件則將支持session保存到多個地方溪胶,如:
- redis
- memcached
- filesystem
- mongodb
- sqlalchmey
安裝pip install Flask-session
def create_app():
app = Flask(__name__)
# 配置
app.config["DEBUG"] = True
# 在config配置之后,在注冊藍圖之前稳诚,是三方組件的空間
# 實例化一個session
Session(app)
# 注冊藍圖
app.register_blueprint(user_bp)
return app
SESSION_SQLALCHEMY
數據庫ORM
# session存儲在redis
app.config["SESSION_TYPE"]='redis'
# 實例化
Session(app)
# 在login方法中設置session
class Login(views.MethodView): # 繼承CBV視圖基類的最高類
def get(self): # get方法的視圖函數實現(xiàn)
session["username"]="電地大"
return "GET OK 200"
Redis模塊的簡單用法
redis安裝
https://redis.io/download/
啟動服務
from redis import Redis
rdb=Redis()
rdb.set("username","NB")
print(rdb.get("username"))
存一個字典
rdb=Redis()
d={"key":"value"}
# 把dict轉為byte
rdb.set("username",json.dumps(d))
# 把byte轉為dict
print(json.loads(rdb.get("username")))
db參數:
rdb=Redis(host="127.0.0.1",port=6379,db=8) # db-->0-15,除了0哗脖,其他都會顯示,數據隔離的作用
在redis服務中命令select 8
Flask-session高級源碼閱讀
看不懂 就這樣吧扳还。
app.config["SESSION_TYPE"] = 'redis'
app.config["SESSION_REDIS"] = Redis(host="192.168.14.25") # 實例化才避,部署在內網的其他服務器
Session(app)
Day4
Flask請求上下文預備知識
1.線程安全
2.偏函數
3.OOP 面向對象
面向對象回顧
偏函數
簡單的理解偏函數,它是對原始函數的二次封裝氨距,是將現(xiàn)有函數的部分參數預先綁定為指定值桑逝,從而得到一個新的函數,該函數就稱為偏函數衔蹲。相比原函數肢娘,偏函數具有較少的可變參數呈础,從而降低了函數調用的難度舆驶。
from functools import partial
def abfun(a, b):
print(a)
print(b)
return a + b
new_ab = partial(abfun, 2, 3)
print(new_ab) # functools.partial(<function abfun at 0x000001BA7781D0D8>, 2, 3)
print(new_ab()) # 5
將原函數和原函數接收的參數一并存放,返回新函數而钞,在執(zhí)行新函數時沙廉,將參數傳入原函數中一并執(zhí)行。
from functools import partial
def abfun(a, b,x):
print(a)
print(b)
return a + b+x
# 只知道一個參數的值
new_ab = partial(abfun,x=80)
print(new_ab)
print(new_ab(3,10)) # 93
線程安全
單線程讀取19個臼节,需要19s撬陵,打印內容為012345...19
import time
class Foo:
pass
f = Foo()
f.num = 0
def add(i):
f.num = i
# 模擬IO操作需要1s
time.sleep(1)
print(f.num)
for i in range(20):
add(i)
開啟多線程,使任務在1.5s左右完成:
但打印的結果是19 19 19...19
import time
from threading import Thread
class Foo:
pass
f = Foo()
f.num = 0
def add(i):
f.num = i
time.sleep(1)
print(f.num)
for i in range(20):
task=Thread(target=add,args=(i,))
task.start()
使用深copy:
很快解決了阻塞 保證了公共對象的安全性
但浪費了大量的資源 拿空間浪費換取時間
import time
from threading import Thread,get_ident
from copy import deepcopy
class Foo:
pass
f = Foo()
f.num = 0
local_dict={}
def add(i):
# 深copy
local_dict[get_ident()]=deepcopy(f)
local_dict[get_ident()].num = i
time.sleep(1)
print("{}_{}".format(local_dict[get_ident()].num,get_ident()))
# print(get_ident())
for i in range(20):
task=Thread(target=add,args=(i,))
task.start()
WSGI收取request
請求上下文:讀flask源碼
1.請求是如何到達flask應用的
由底層傳到高層
請求上文
from werkzeug.wrappers import Request,Response
from werkzeug import run_simple
# run_simple監(jiān)聽操作系統(tǒng)傳遞來的數據
@Request.application
def app(req):
print(req,req.method,type(req))
return Response("200 ok")
run_simple("127.0.0.1",5000,app)
打印結果:
req # <Request 'http://127.0.0.1:5000/' [GET]>
req.method # GET
type(req) #<class 'werkzeug.wrappers.request.Request'>
falsk中的app.run()
調用的就是run_simple()
方法
一頓轉換网缝,轉換為flask風格的request
environ是原始的請求信息巨税,app
golbals.py中 --》請求上文