Flask基础一
一、Flask初始
首先,要看你學(xué)沒學(xué)過Django,如果學(xué)過Django的同學(xué),請從頭看到尾,如果沒有學(xué)過Django的同學(xué),并且不想學(xué)習(xí)Django的同學(xué),請繞過第一部分。
三大主流Web框架對比
1、Django主要特點是大而全,繼承了很多組件,例如:Models Admin Form等等,不管你用得到用不到,反正它全都有,屬于全能型框架
2、Tornado主要特點是原生異步非阻塞,在IO密集型應(yīng)用和多任務(wù)處理上占據(jù)絕對性的優(yōu)勢,屬于專注型框架
3、Flask主要特點小而輕,原生組件幾乎為0,三方提供的組件請參考Django非常全面,屬于短小精悍型框架
Django通常用于大型Web應(yīng)用,由于內(nèi)置組件足夠大,所以使用Django開發(fā)可以一氣呵成
Tornado通常用于API后端應(yīng)用,游戲服務(wù)后臺,其內(nèi)部實現(xiàn)的異步非阻塞真是穩(wěn)得一批
Flask通常應(yīng)用于小型應(yīng)用和快速構(gòu)建應(yīng)用,其強大的三方庫,足以支撐一個大型的Web應(yīng)用
Django優(yōu)點是大而全,缺點也就暴露出來了,這么多的資源一次性全部加載,肯定會造成一部分的資源浪費
Tornado優(yōu)點是異步,缺點是干凈,連個session都不支持
Flask優(yōu)點是精悍簡單,缺點是你不會
總結(jié):
Flask: 1、輕,短小精悍 2、快,三行代碼開啟服務(wù) 缺點: 1、組件大部分來源三方,flask-admin,flask-session 2、flask大版本更新,組件更新速度慢Django: 1、大而全,admin,models,Form,中間件,session 2、一個框架解決所有問題 缺點: 1、一旦啟動,所有資源全部加載,用不到的,浪費了 2、太大了,結(jié)構(gòu)復(fù)雜 3、所有的組件,全部由Django自身控制Tornado: 1、原生websocktet 2、異步io 3、非阻塞 缺點: 三方及原生組件幾乎為0Flask的安裝與HelloWorld
pip install Flask三行Flask
from flask import Flaskapp = Flask(__name__) app.run()執(zhí)行控制臺輸出:
| ?* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) |
默認端口是5000,訪問頁面:
因為沒有定義路由,所以報404。但是服務(wù)是起來了!
六行Flask
from flask import Flaskapp = Flask(__name__) @app.route("/") def index():return "HelloWorld" app.run()重啟程序,刷新頁面
實現(xiàn)了Flask的第一個HelloWorld程序,解讀一下代碼
from flask import Flask # 導(dǎo)入Flask類 app = Flask(__name__) # 實例化Flask對象app @app.route("/") # app中的route裝飾器 def index(): # 視圖函數(shù)return "HelloWorld" # 返回響應(yīng)提# 監(jiān)聽地址為0.0.0.0,表示服務(wù)器的所有網(wǎng)卡 # 5000是監(jiān)聽端口 # debug=True表示啟動debug模式。當代碼有改動時,Flask會自動加載,無需重啟! app.run("0.0.0.0", 5000, debug=True) # 啟動Flask服務(wù)注意:默認的debug模式是關(guān)閉的。如有代碼改動,需要重啟flask才能生效!但是開啟debug模式,代碼一有改動,會立刻加載,無需重啟!
還有一點,app=Flask(__name__)。這里面的__name__表示標識模塊的名字的一個系統(tǒng)變量
還可以是app=Flask("asdfasdf"),這樣運行也沒有問題。那么為什么要用__name__呢?
二、render redirect HttpResponse
HttpResponse
@app.route("/") # app中的route裝飾器 def index(): # 視圖函數(shù)return "HelloWorld" # HttpResponse在Flask中的HttpResponse在我們看來其實就是直接返回字符串
redirect
from flask import Flask from flask import redirect # 導(dǎo)入flask中的redirect app = Flask(__name__)# app中的route裝飾器,用來指定視圖函數(shù)的URL地址 @app.route("/redi") def redi(): # 視圖函數(shù)return redirect("/") # redirect跳轉(zhuǎn)至"/" @app.route("/") def index(): # 視圖函數(shù)return "hello"if __name__ == "__main__":app.run("0.0.0.0", 5000, debug=True)每當訪問"/redi"這個地址的時候,視圖函數(shù)redi會觸發(fā)redirect("/")跳轉(zhuǎn)到url地址:"/"并會觸發(fā)"/"對應(yīng)的視圖函數(shù)index()
訪問url:http://127.0.0.1:5000/redi
查看網(wǎng)頁工具,查看網(wǎng)絡(luò)。它經(jīng)歷了2次請求!
render (render_template)
編輯文件demo.py,代碼如下
from flask import Flask # 導(dǎo)入Flask類 from flask import render_template # 導(dǎo)入flask中的render_template app = Flask(__name__)@app.route("/home") def home(): # 視圖函數(shù)# 渲染html模板,返回html頁面return render_template('home.html')if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)在當前py文件目錄中創(chuàng)建templates,在此目錄下創(chuàng)建文件home.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h1>Flask</h1> </body> </html>重啟flask,訪問home頁面,效果如下:
HTML模板渲染是每個Web框架中都必須有的
注意:如果要使用render_template返回渲染的模板,請在項目的主目錄中假如一個目錄templates,否則可能會有一個jinja2的異常哦
遇到上述的問題,基本上就是你的template的路徑問題
為什么一定要創(chuàng)建templates文件夾呢?叫abc行不行呢?不行!看這一行代碼
app = Flask(__name__)使用Ctrl+鼠標左鍵,點擊Flask,查看源碼
def __init__(self,import_name,static_url_path=None,static_folder='static',static_host=None,host_matching=False,subdomain_matching=False,template_folder='templates',instance_path=None,instance_relative_config=False,root_path=None):看到template_folder變量沒有?文件均價必須叫這個名字!
指定templates路徑
注意:我的flask程序,是直接用新建py文件寫的。所以這一行代碼,會票黃
return render_template('home.html')怎么解決呢?很簡單!執(zhí)行目錄就好了
右鍵templates文件夾--→Mark Directory as--→Template Folder
選擇yes
選擇Jinja2,Flask中默認的模板語言是Jinja2
Django的模板語言為Django,其實Django底層也是用Jinja2開發(fā)的。其他模板語言同理!
后續(xù)會講到flask模板語法,你會發(fā)現(xiàn),和Django幾乎是一樣的!
注意:如果直接使用Pycharm創(chuàng)建Flask項目,是不存在這個問題的!
前期學(xué)習(xí)Flask,要先自己手動折騰,后期就可以用Pycharm創(chuàng)建了!
三、request
每個框架中都有處理請求的機制(request),但是每個框架的處理方式和機制是不同的
為了了解Flask的request中都有什么東西,首先我們要寫一個前后端的交互,基于HTML + Flask寫一段前后端的交互?
先寫一段兒HTML form表單中提交方式是post action地址是/req
在templates目錄創(chuàng)建文件login.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h1>歡迎登陸</h1> <form action="/req" method="post"><p><input type="text" name="user" placeholder="請輸入用戶名"></p><p><input type="password" name="pwd" placeholder="請輸入密碼"></p><input type="submit" value="提交"> </form> </body> </html>寫好一個標準form表單,一點提交,就向后端提交一個POST請求過去了,后端的接收方式就666了
首先要從flask包中導(dǎo)入request模塊
from flask import Flask # 導(dǎo)入flask類 from flask import render_template # 導(dǎo)入flask中的render_template from flask import request # 導(dǎo)入flask中的request app = Flask(__name__)@app.route("/login") def login():return render_template("login.html")@app.route("/req") def home(): # 視圖函數(shù)print(request)return "ok"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)重啟flask,訪問登陸頁面
輸入表單,提交之后,報錯!提示請求方式不被允許!
methods
為什么呢?因為默認路由只允許GET訪問。那么需要加一個參數(shù)methods,允許POST訪問
from flask import Flask # 導(dǎo)入flask類 from flask import render_template # 導(dǎo)入flask中的render_template from flask import request # 導(dǎo)入flask中的request app = Flask(__name__)@app.route("/login") def login():return render_template("login.html")@app.route("/req",methods=["POST"]) # 只允許POST def home(): # 視圖函數(shù)print(request) # request對象print(request.method) # POST看來可以使用這種方式來驗證請求方式# ImmutableMultiDict([('user','xiao'),('pwd','123')])print(request.form)# ImmutableMultiDict 它看起來像是Dict,使用字典方式取值print(request.form["user"]) # xiaoprint(request.form.get("pwd")) # 123# 字典迭代器對象,keys表示獲取所有值print(request.form.keys())# 既然是迭代器,就可以使用for循環(huán)了for i in request.form.keys():print(i)return "ok"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)重新提交一次,就可以了!
查看Pycharm控制臺輸出:
| <Request 'http://127.0.0.1:5000/req' [POST]> |
解釋一個@app.route("/req",methods=["POST"]):
methods=["POST"] 代表這個url地址只允許POST請求,是個列表也就是意味著可以允許多重請求方式,例如GET之類的
request.method
1、request.method之肯定知道前端用什么方式提交的
Flask的request中給我們提供了一個method屬性里面保存的就是前端的請求方式
print(request.method) # POST 看來可以使用這種方式來驗證請求方式request.form
2、request.form之拿他來舉例的話再好不過了
Form表單中傳遞過來的值 使用request.form中拿到
print(request.form) # ImmutableMultiDict([('user', 'xiao'), ('pwd', '123')]) # ImmutableMultiDict 它看起來像是的Dict 就用Dict的方法取值試一下吧 print(request.form["user"]) # xiao print(request.form.get("pwd")) # 123 # 看來全部才對了, ImmutableMultiDict 似乎就是個字典,再來玩一玩它 print(list(request.form.keys())) # ['user', 'pwd'] 看來是又才對了 #如果以上所有的方法你都覺得用的不爽的話 req_dict = dict(request.form) print(req_dict) # 如果你覺得用字典更爽的話,也可以轉(zhuǎn)成字典操作(這里有坑)request.args
3、request.args之你能看見的url參數(shù)全在里面
request.args中保存的是url中傳遞的參數(shù)
先把后端請求代碼改動一下,允許POST和GET
from flask import Flask # 導(dǎo)入flask類 from flask import render_template # 導(dǎo)入flask中的render_template from flask import request # 導(dǎo)入flask中的request app = Flask(__name__)@app.route("/login") def login():return render_template("login.html")@app.route("/req",methods=["POST","GET"]) # 只允許POST和GET def home(): # 視圖函數(shù)print(request.args) # ImmutableMultiDict([('id','1'),('age','20')])print(request.args["id"]) # 1print(request.args.get("age")) # 20print(list(request.args.keys())) # ['id','age']print(list(request.args.values())) # ['1','20']req_dict = dict(request.args) # {'id':['1'],'age':['20']}print(req_dict)return "ok"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)然后使用URL地址直接傳遞參數(shù)
然后會在控制臺中看到,ImmutableMultiDict
| ImmutableMultiDict([('id', '18'), ('age', '20')]) |
request.args與request.form的區(qū)別就是:
request.args 是獲取url中的參數(shù)
request.form 是獲取form表單中的參數(shù)
request.values
4、request.values 之 只要是個參數(shù)我都要
改動一下前端頁面(login.html)代碼:
| <form action="/req?id=1&age=20" method="post"> |
改動后端代碼:
from flask import Flask # 導(dǎo)入flask類 from flask import render_template # 導(dǎo)入flask中的render_template from flask import request # 導(dǎo)入flask中的request app = Flask(__name__)@app.route("/login") def login():return render_template("login.html")@app.route("/req",methods=["POST","GET"]) # 只允許POST和GET def home(): # 視圖函數(shù)print(request.values) # CombinedMultiDict([ImmutableMultiDict([('id', '1'), ('age', '20')]), ImmutableMultiDict([('user', 'xiao'), ('pwd', '123')])])print(request.values.get("id")) # 1print(request.values["user"]) # Oldboy# 這回喜歡直接操作字典的小伙伴們有驚喜了!to_dict()方法可以直接將我們的參數(shù)全部轉(zhuǎn)為字典形式print(request.values.to_dict()) # {'user': 'xiao', 'pwd': '123', 'id': '1', 'age': '20'}return "ok"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)這是讓我們在使用form表單提交的同時使用url參數(shù)提交
訪問登陸頁面,點擊提交,查看Pycharm控制臺輸出:
| CombinedMultiDict([ImmutableMultiDict([('age', '20'), ('id', '1')]), ImmutableMultiDict([('user', 'xiao'), ('pwd', '112')])]) |
form表單的坑
如果url和form中的Key重名的話,form中的同名的key中value會被url中的value覆蓋
http://127.0.0.1:5000/req?id=1&user=20
修改login.html
| <form action="/req?id=1&user=20" method="post"> |
重新訪問登陸頁面,再次提交。
查看Pycharm控制臺輸出:
| CombinedMultiDict([ImmutableMultiDict([('id', '1'), ('user', '20')]), ImmutableMultiDict([('user', 'xiao'), ('pwd', '123')])]) 1 20 {'user': '20', 'pwd': '123', 'id': '1'} |
發(fā)現(xiàn)user變成了20,如果url和form中key重名的話,form中的同名的key中value會被url中的value覆蓋
request.cookies?
5、request.cookies 之 存在瀏覽器端字符串兒也會一起帶過來
前提是你要開啟瀏覽器的cookies,request.cookies是將cookies中信息讀取出來
修改demo.py中的home視圖函數(shù)
def home(): # 視圖函數(shù)print(request.cookies)return "ok"重新登陸一次,查看Pycharm控制臺輸出:
| {'csrftoken': '5dbnoXpHe4dYUPZqCejRBleKc5HznLKY2sAgmTLqxSjL2kBPKLYAt9yxvPlNNMHf'} |
request.headers
6、request.headers 之 請求頭中的秘密
用來獲取本次請求的請求頭
修改demo.py中的home視圖函數(shù)
def home(): # 視圖函數(shù)print(request.headers)return "ok"重新登陸一次,查看Pycharm控制臺輸出:
| Connection: keep-alive |
request.data
7、request.data 之 如果處理不了的就變成字符串兒存在data里面
你一定要知道request是基于mimetype進行處理的
mimetype的類型以及字符串:http://www.w3school.com.cn/media/media_mimeref.asp
如果不屬于上述類型的描述,request就會將無法處理的參數(shù)轉(zhuǎn)為Json存入到data中
其實我們可以將request.data,json.loads同樣可以拿到里面的參數(shù)
修改demo.py中的home視圖函數(shù)
def home(): # 視圖函數(shù)print(request.data)return "ok"重新登陸一次,查看Pycharm控制臺輸出:
| b'' |
為什么是空的呢?注意:request處理不了的就變成字符串存在data里面!
因為它能處理,所以才是空的!
request.files
8、request.files 之 給我一個文件我?guī)湍惚9?/p>
如果遇到文件上傳的話,request.files里面存的是你上傳的文件,但是Flask在這個文件的操作中加了一定的封裝,讓操作變得極為簡單
首先改下前端代碼:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h1>歡迎登陸</h1> <form action="/req" method="post" enctype="multipart/form-data"><p><input type="file" name="file"></p><input type="submit" value="提交"> </form> </body> </html>再改后端代碼:
from flask import Flask # 導(dǎo)入flask類 from flask import render_template # 導(dǎo)入flask中的render_template from flask import request # 導(dǎo)入flask中的request app = Flask(__name__)@app.route("/login") def login():return render_template("login.html")@app.route("/req",methods=["POST","GET"]) # 只允許POST和GET def home(): # 視圖函數(shù)print(request.files) # ImmutableMultiDict([('file', <FileStorage: 'abc.txt' ('text/plain')>)])print(request.files['file']) # <FileStorage: 'abc.txt' ('text/plain')>my_file = request.files["file"]my_file.save("123.txt") # 保存文件,里面可以寫完整路徑+文件名return "ok"if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)訪問登陸頁面
上傳一個文件,比如是abc.txt
點擊提交,效果如下:
查看Pycharm控制臺輸出:
| ImmutableMultiDict([('file', <FileStorage: 'abc.txt' ('text/plain')>)]) |
這樣我們就成功的保存了一個名叫123.txt的文件了,操作還是很簡單的。保存目錄為當前py文件目錄!
注意:前端頁面必須設(shè)置enctype=“multipart/form-data”,否則提交時,會報錯
request.獲取各種路徑
9、request.獲取各種路徑 之 這些方法沒必要記,但是要知道它存在
修改后端代碼
def home(): # 視圖函數(shù)# 獲取當前的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/return "ok"直接訪問頁面
查看Pycharm控制臺輸出:
| /req http://127.0.0.1:5000/req |
request.json
10、request.json 之 前提你得告訴是json
如果在請求中寫入了“application/json”使用request.json則返回json解析數(shù)據(jù),否則返回None
修改后端代碼:
def home(): # 視圖函數(shù)# 獲取json數(shù)據(jù)print(request.json)return "ok"使用postman發(fā)送一個json數(shù)據(jù)
查看返回值
查看Pycharm控制臺輸出:
| {'id': 1} |
四、模板語言Jinja2
Jinja2?
Flask中默認的模板語言是Jinja2 ,現(xiàn)在我們來一步一步的學(xué)習(xí)下Jinja2。
首先我們要在后端定義幾個字符串,用于傳遞到前端
| STUDENT = {'name':'韓雪','age':24,'gender':'女'} STUDENT_LIST = [ {'name':'韓雪','age':24,'gender':'女'}, {'name':'舒暢','age':23,'gender':'女'}, {'name':'唐嫣','age':25,'gender':'女'}, ] STUDENT_DICT = { {'name':'韓雪','age':24,'gender':'女'}, {'name':'舒暢','age':23,'gender':'女'}, {'name':'唐嫣','age':25,'gender':'女'}, } |
但是前提我們要知道Jinja2模板中的流程控制
for
Jinja2模板語言中的for
{% for foo in session %} {{ foo }} {% endfor %}if
Jinja2模板語言中的if
{% if session %} {% elif session %} {% else %} {% endif %}接下來,我們對這幾種情況分別進行傳遞,并在前端顯示成表格
字典
1、使用STUDENT字典傳遞至前端
后端demo.py
from flask import Flask # 導(dǎo)入flask類 from flask import render_template # 導(dǎo)入flask中的render_template from flask import request # 導(dǎo)入flask中的request app = Flask(__name__)STUDENT = {'name': '韓雪', 'age': 24, 'gender': '女'}STUDENT_LIST = [{'name': '韓雪', 'age': 24, 'gender': '女'},{'name': '舒暢', 'age': 23, 'gender': '女'},{'name': '唐嫣', 'age': 25, 'gender': '女'}, ]STUDENT_DICT = {1: {'name': '韓雪', 'age': 24, 'gender': '女'},2: {'name': '舒暢', 'age': 23, 'gender': '女'},3: {'name': '唐嫣', 'age': 25, 'gender': '女'}, }@app.route("/student") def student():return render_template("student.html", student=STUDENT)if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)前端student.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h3>學(xué)生列表</h3> <div>{{ student }}</div> <table border="1px"><tr><td>{{ student.name }}</td><td>{{ student["age"] }}</td><td>{{ student.get("gender") }}</td></tr> </table> </body> </html>重新flask,訪問頁面
從這個例子中,可以看出來,字典傳入前端Jinja2模板語言中的取值操作,與Python中的Dict操作極為相似,并且多了一個student.name的對象操作
列表
2、STUDENT_LIST列表傳入前端Jinja2模板的操作:
后端:
@app.route("/student_list")def student_list():
return render_template("student.html",student=STUDENT_LIST)
前端:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h3>學(xué)生列表</h3> <div>{{ student }}</div> <table border="1px">{% for foo in student %}<tr><td>{{ foo }}</td><td>{{ foo.name }}</td><td>{{ foo.get("age") }}</td><td>{{ foo["gender"] }}</td></tr>{% endfor %} </table> </body> </html>訪問頁面,注意:路徑改了,效果如下:
這里我們可以看出,如果是需要循環(huán)遍歷的話,Jinja2給我們的方案是
| {% for foo in student %} <tr> <td>{{ foo }}</td> </tr> {% endfor %} |
修改前端:
<div>{{ student }}</div> <table border="1px">{% for foo in student %}<tr><td>{{ foo }}</td></tr>{% endfor %} </table>訪問頁面,注意:路徑改了,效果如下:
大字典
3、STUDENT_DICT大字典傳入前端Jinja2模板
后端:
@app.route("/student_dict") def student_dict():return render_template("student.html",student=STUDENT_DICT)前端:
<table border="1px">{% for foo in student %}<tr><td>{{ foo }}</td><td>{{ student.get(foo).name }}</td><td>{{ student[foo].get("age") }}</td><td>{{ student[foo]["gender"] }}</td></tr>{% endfor %} </table>在遍歷字典的時候,foo其實是相當于拿出了字典中的Key
訪問頁面,注意:路徑變了,效果如下:
數(shù)據(jù)集合
4、結(jié)合所喲的字符串全部傳遞前端Jinja2模板
后端:
@app.route("/allstudent") def allstudent():return render_template("student.html", student=STUDENT, student_list=STUDENT_LIST, student_dict=STUDENT_DICT)前端:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <h3>學(xué)生列表</h3> <div> _____________________________________</div> Welcome to : student <div>{{ student }}</div> <table border="1px"><tr><td>{{ student.name }}</td><td>{{ student["age"] }}</td><td>{{ student.get("gender") }}</td></tr> </table> <div> _____________________________________</div> Welcome to : student_list <div>{{ student_list }}</div> <table border="1xp">{% for foo in student_list %}<tr><td>{{ foo }}</td><td>{{ foo.name }}</td><td>{{ foo.get("age") }}</td><td>{{ foo["gender"] }}</td></tr>{% endfor %} </table> <div> _____________________________________</div> Welcome to : student_dict <div>{{ student_dict }}</div> <table border="1xp">{% for foo in student_dict %}<tr><td>{{ foo }}</td><td>{{ student_dict.get(foo).name }}</td><td>{{ student_dict[foo].get("age") }}</td><td>{{ student_dict[foo]["gender"] }}</td></tr>{% endfor %} </table> </body> </html> View Code訪問頁面,注意,路徑改了,效果如下:
這里可以看出來render_template中可以傳遞多個關(guān)鍵字
**{}字典
5、利用**{}字典的方式傳遞參數(shù)
前端不變(標題4的前端代碼)
后端:
@app.route("/allstudent") def allstudent():return render_template("student.html",**{"student": STUDENT, "student_list": STUDENT_LIST, "student_dict": STUDENT_DICT})刷新頁面,效果同上!
Jinja2的高階用法
safe?
6.1.safe: 此時你與HTML只差一個safe
后端代碼:
from flask import Flask from flask import render_templateapp = Flask(__name__)@app.route("/") def index():tag = '<input type="text" name="user" value="xiao">'return render_template("index.html", tag=tag)if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)在templates目錄下新建文件index.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> {{ tag }} </body> </html>訪問首頁,效果如下:
似乎和我們想要的結(jié)果不太一樣,有兩種解決方案。
第一種,從前端入手
修改前端代碼:
{{ tag|safe }}刷新頁面,效果如下:
還有一種方式是從后端入手
后端代碼:
from flask import Flask from flask import render_template from flask import Markup # 導(dǎo)入flask中的Markup模塊 app = Flask(__name__)@app.route("/") def index():tag = '<input type="text" name="user" value="xiao">'# Markup幫助咱們在HTML的標簽上做了一層封裝,讓Jinja2模板語言知道這是一個安全的HTML標簽markup_tag = Markup(tag)print(markup_tag, type(markup_tag))# <input type='text' name='user' value='DragonFire'> <class 'markupsafe.Markup'>return render_template("index.html", tag=markup_tag)if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)執(zhí)行Python函數(shù)
模板中執(zhí)行函數(shù),首先在文件中定義一個函數(shù)
后端代碼:
from flask import Flask from flask import render_templateapp = Flask(__name__)# 定義一個函數(shù),把它傳遞給前端 def a_b_num(a, b):return a + b@app.route("/") def index():return render_template("index.html", tag=a_b_num)if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)前端代碼:
<body> {{ tag }} <br> {#傳入2個參數(shù)#} {{ tag(99,1) }} </body>刷新頁面,效果如下:
看到結(jié)果就是函數(shù)加()執(zhí)行得到的結(jié)果
還可以定義全局函數(shù),無需后端傳遞給前端,Jinja2直接就可以執(zhí)行的函數(shù)
后端代碼:
from flask import Flask from flask import render_templateapp = Flask(__name__)@app.template_global() # 定義全局模板函數(shù) def a_b_sum(a, b):return a + b@app.template_filter() # 定義全局模板函數(shù) def a_b_c_sum(a, b, c):return a + b + c@app.route("/") def index():return render_template("index.html", tag="")if __name__ == '__main__':app.run("0.0.0.0", 5000, debug=True)前端代碼:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body>{#函數(shù)#}{{ a_b_sum(99,1) }}<br>{#過濾器#}{{ 1 | a_b_c_sum(197,2) }}</body> </html>兩個函數(shù)的調(diào)用方式不太一樣
尤其是@app.template_filter()它的調(diào)用方式比較特別,這是兩個Flask中的特殊裝飾器
刷新頁面,效果如下:
模板服用block
如果我們前端頁面有大量重復(fù)頁面,沒必要每次都寫,可以使用模板復(fù)用的方式復(fù)用模板
前端代碼:
index.html文件中的內(nèi)容
?
轉(zhuǎn)載于:https://www.cnblogs.com/Black-rainbow/p/9600039.html
總結(jié)
- 上一篇: ceph——rgw服务启不起来
- 下一篇: 抓包工具Charles基本用法