Python Flask 入門指南: 輕量級網頁框架教學

文章推薦指數: 80 %
投票人數:10人

from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello, World!" 步驟三: 終端機指令執行. $ flask run. 出現「Running on http:// ... Devs.tw寫程式討論區 全部貼文 原創發表 系列文章 貢獻者 社群 FB社團 FB粉專   發佈文章 建立系列 登入 註冊   Devs.tw是讓工程師寫筆記、網誌的平台。

歡迎您隨手紀錄、寫作,方便日後搜尋! 尤川豪 Enoxs chenjenping JuenTingShie thomaschu Enoxs   ·  6月前 7貼文  ·  1留言 PythonFlask入門指南:輕量級網頁框架教學 5行程式碼架設網站 Youtube:PythonFlask入門指南:輕量級網頁框架教學|前端x後端|5行程式碼架設網站【GammaRay軟體工作室】 目錄 前言:五行程式碼 PythonFlask-HelloWorld 網頁模版-Html回傳 資料交換-Form表單提交與Ajax資料交換 開發配置-外網訪問與熱部署 前言:五行程式碼 PythonFlask是一種輕量級的網頁框架,只要五行程式碼,就可以架設網頁伺服器: 步驟一:安裝Flask套件 $pipinstallFlask 步驟二:將以下代碼存檔為app.py fromflaskimportFlask app=Flask(__name__) @app.route("/") defhello(): return"Hello,World!" 步驟三:終端機指令執行 $flaskrun 出現「Runningonhttp://127.0.0.1:5000/(PressCTRL+Ctoquit)」的文字 瀏覽器訪問127.0.0.1:5000,出現HelloWorld,代表架設完成! Whatdoes"micro"mean? 在Flask的官網,對於「micro」有這樣的定義: 輕量並不代表缺少功能,而是在保持核心簡單的情況下,留有擴展空間。

做法就是不為你事先做出決定,只會包含「你需要的一切,而沒有你不需要的」。

PythonFlask入門指南 除了說明上述五行程式碼代表的含義,還會延伸幾項後端開發常見的配置: URL路由-註解註冊 Html回傳-網頁模版 WebAPI-資料交換 從Flask入門網站開發,可以帶你快速的了解,網頁框架通常會具備的功能,以及累積網站開發後端的知識。

對於後續要了解Python在網路領域,相關的技術與應用,例如:爬蟲的原理或者資料庫的數據分析, 都可以大幅提升學習的效率。

源代碼,下載 章節中的程式碼範例 gitlab:https://gitlab.com/GammaRayStudio/DevelopmentGroup/Python/FlaskSE PythonFlask-HelloWorld Python版本建議3.4以上,內置的pip工具可以節省很多時間 HelloWorld範例 fromflaskimportFlask app=Flask(__name__) @app.route("/") defhello(): return"Hello,World!" 第一行:fromflaskimportFlask 另外一種更常見的import方式,可以簡化第二行的建構式宣告。

方法一: importFlask app=flask.Flask(__name__) 方法二: fromflaskimportFlask app=Flask(__name__) 方法二為官網的範例。

第二行:app=Flask(__name__) Flask類別初始化時傳入的__name__參數,代表當前模組的名稱。

是固定用法,以便讓Flask知道在哪裡尋找資源。

(例如:模板和靜態文件) 第三行:@app.route("/") 裝飾器是告訴Flask,哪個URL應該觸發我們的函式。

斜線代表的就是網站的根目錄,可以疊加。

例如:新增一個/hello的位址 @app.route("/") @app.route("/hello") defhello(): return"Hello,World!" 網站訪問首頁與/hello,呈現的同樣是hello函式,回傳的HelloWorld文字。

defhello()::被觸發的函式第四行 return"Hello,World!":函式回傳的文字字串,也等於WebAPI回傳的內容。

第五行 flaskrun指令 官方範例,檔名為app.py使用的是flaskrun指令,可以直接啟動網站。

在日常的開發中,可以再加上python的main方法, 執行app.run()函式,執行網頁伺服器的啟動動作。

調整後:hello-world.py #savethisasapp.py importflask app=flask.Flask(__name__) @app.route("/") @app.route("/hello") defhello(): return"Hello,World!" if__name__=='__main__': app.run() 註冊路由 除了固定的導向位址,URL也可以成為函式接收的參數 routing.py @app.route('/data/appInfo/',methods=['GET']) defqueryDataMessageByName(name): print("type(name):",type(name)) return'String=>{}'.format(name) 代表接收name參數為字串型態 訪問:http://127.0.0.1:5000/data/appInfo/FlaskSE 打印:type(name): 網頁:String=>FlaskSE @app.route('/data/appInfo/id/',methods=['GET']) defqueryDataMessageById(id): print("type(id):",type(id)) return'int=>{}'.format(id) 訪問:http://127.0.0.1:5000/data/appInfo/id/5 打印:type(id): 網頁:int=>5 @app.route('/data/appInfo/version/',methods=['GET']) defqueryDataMessageByVersion(version): print("type(version):",type(version)) return'float=>{}'.format(version) 訪問:http://127.0.0.1:5000/data/appInfo/version/1.01 打印:type(version): 網頁:float=>1.01 網頁模版-Html回傳 PythonFlask使用Jinja2的模板引擎 最簡單的網頁格式 @app.route('/text') deftext(): return'

HelloWorld

' 網頁顯示:H1大標題的HelloWorld元素 簡單的格式還可以,複雜一點,回傳html檔案會較為理想。

templates資料夾 在python執行檔的目錄下,創建templates資料夾,html檔案放置於此 /render.py /templates /home.html /page.html /static.html render.py @app.route('/home') defhome(): returnrender_template('home.html') templates/home.html Home

MyWebsiteText

TextTextText TextTextText TextTextText TextTextText TextTextText TextTextText TextTextText TextTextText TextTextText

訪問:http://127.0.0.1:5000/home 網頁: Jinja2模板引擎 API返回網頁時,可以做更多的事情 先看完整的程式碼,接續有說明。

render.py fromflaskimportFlask,render_template app=Flask(__name__) @app.route('/text') deftext(): return'

HelloWorld

' @app.route('/home') defhome(): returnrender_template('home.html') @app.route('/page/text') defpageText(): returnrender_template('page.html',text="PythonFlask!") @app.route('/page/app') defpageAppInfo(): appInfo={#dict 'id':5, 'name':'Python-Flask', 'version':'1.0.1', 'author':'Enoxs', 'remark':'Python-WebFramework' } returnrender_template('page.html',appInfo=appInfo) @app.route('/page/data') defpageData(): data={#dict '01':'TextTextText', '02':'TextTextText', '03':'TextTextText', '04':'TextTextText', '05':'TextTextText' } returnrender_template('page.html',data=data) @app.route('/static') defstaticPage(): returnrender_template('static.html') if__name__=='__main__': app.run() templates/page.html Template-Page

Template-Page

{{text}}

{%ifappInfo!=undefined%}

AppInfo:

id:{{appInfo.id}}

name:{{appInfo.name}}

version:{{appInfo.version}}

author:{{appInfo.author}}

remark:{{appInfo.remark}}

{%endif%} {%ifdata!=undefined%}

Data:

{%forkey,valueindata.items()%} {{key}} {{value}} {%endfor%} {%endif%}

API附帶參數:@app.route('/page/text') render.py @app.route('/page/text') defpageText(): returnrender_template('page.html',text="PythonFlask!") render_template()函式:第二個參數可以附帶資料內容 templates/page.html

Template-Page

{{text}}

text參數:使用兩個大括號{{text}}就可以將資料顯示在畫面上 API字典型態與頁面條件式:@app.route('/page/app') render.py @app.route('/page/app') defpageAppInfo(): appInfo={#dict 'id':5, 'name':'Python-Flask', 'version':'1.0.1', 'author':'Enoxs', 'remark':'Python-WebFramework' } returnrender_template('page.html',appInfo=appInfo) 不同的路由路徑,傳遞相同的網頁模版: @app.route('/page/app') render_template('page.html',appInfo=appInfo) appInfo參數:字典型態的變數,將更多的資料,在同一時間傳遞。

templates/page.html {%ifappInfo!=undefined%}

AppInfo:

id:{{appInfo.id}}

name:{{appInfo.name}}

version:{{appInfo.version}}

author:{{appInfo.author}}

remark:{{appInfo.remark}}

{%endif%} 模板引擎,前端畫面條件式語法: {%ifboolean%} {%endif%} ifappInfo!=undefined:如果appInfo有資料,html標籤內容生效 {{appInfo.object}}:字典參數取用資料方法,同樣兩個大括號包覆後生效。

API:字典型態與頁面迴圈 render.py @app.route('/page/data') defpageData(): data={#dict '01':'TextTextText', '02':'TextTextText', '03':'TextTextText', '04':'TextTextText', '05':'TextTextText' } returnrender_template('page.html',data=data) 不同的路由路徑,傳遞相同的網頁模版: @app.route('/page/data') returnrender_template('page.html',data=data) data參數:字典型態的變數,與上一個相同,將更多的資料,同時間傳遞。

templates/page.html {%ifdata!=undefined%}

Data:

{%forkey,valueindata.items()%} {{key}} {{value}} {%endfor%} {%endif%} 模板引擎,前端畫面條件式語法:與上一個相同 {%ifboolean%} {%endif%} 模板引擎,for迴圈語法:將表格與參數內的資料,同時呈現出來 {%forkey,valueindata.items()%} {{key}}:迴圈key值 {{value}}:迴圈value值 {%endfor%} static資料夾 在python執行檔的目錄下,創建static資料夾,.js與.css檔案放置於此 /render.py /templates /home.html /page.html /static.html /static /script.js /style.css 前端開發的javascript與css檔案必須放在static資料夾才會生效。

static.py @app.route('/static') defstaticPage(): returnrender_template('static.html') static/script.js functionsayHello(){ alert("HelloWorld"); } templates/static.html Static-Page

Template-Page

SayHello

如果src的路徑不為static 點擊button不會有反應 終端機顯示http404,表示找不到資源 {{url_for('static',filename='script.js')}} 另外一種模板引擎的寫法,url_for是轉址的函式 第一個參數不動,調整filename參數可以使用其他資源 資料交換-Form表單提交與Ajax資料交換 結合路由註冊與網頁模版,完整實現前端與後端的資料交換 前端:示範兩種 Html-Form表單提交 jQuery-Ajax資料交換 後端:JSON格式 讀寫實際的文件,模擬資料持久化 Html-Form表單提交 同樣先看代碼,接續代碼說明 form.py fromflaskimportFlask,request,render_template,redirect,url_for app=Flask(__name__) @app.route('/form') defformPage(): returnrender_template('Form.html') @app.route('/submit',methods=['POST','GET']) defsubmit(): ifrequest.method=='POST': user=request.form['user'] print("post:user=>",user) returnredirect(url_for('success',name=user,action="post")) else: user=request.args.get('user') print("get:user=>",user) returnredirect(url_for('success',name=user,action="get")) @app.route('/success//') defsuccess(name,action): return'{}:Welcome{}~!!!'.format(action,name) if__name__=='__main__': app.run() templates/form.html Form-Submit

POST

EnterName:

GET

EnterName:

前端:Form表單提交 templates/form.html

EnterName:

GET

EnterName:

:兩個form表單元素 action:提交目標,也就是路由的URL method:http常見的提交方法,這裡分別實作get與post方法 :傳遞表單參數name :html元素,form提交按鈕 後端:網頁模版與資料接口 form.py @app.route('/form') defformPage(): returnrender_template('Form.html') form.html的路由註冊與模板回傳 fromflaskimport...,request,redirect,url_for @app.route('/submit',methods=['POST','GET']) defsubmit(): ifrequest.method=='POST': user=request.form['user'] print("post:user=>",user) returnredirect(url_for('success',name=user,action="post")) else: user=request.args.get('user') print("get:user=>",user) returnredirect(url_for('success',name=user,action="get")) @app.route('/submit',methods=['POST','GET']) @app.route('/submit',...):註冊路由為/submit @app.route(...,methods=['POST','GET']):接收POST與GET方法 request:import導入,物件的method成員,可以知道前端傳遞的是使用HTTP的哪種方法 ifrequest.method=='POST'::POST方法必須使用request.form的變數 else::GET方法必須使用request.args的變數 returnredirect(url_for('success',name=user,action="post")) import導入redirect與url_for用於接收資料成功後,轉址的功能 redirect()函式包含url_for()函式,是固定用法 url_for字串的參數為路由定義的API函式,後方的參數為要傳送的資料內容 這邊的範例,就是轉址到success()函式 接收使用者名稱name與http方法action @app.route('/success//') defsuccess(name,action): return'{}:Welcome{}~!!!'.format(action,name) suceesss()函式:回傳字串格式化的文字 完整form表單提交與接收成功後轉址流程 jQuery-Ajax資料交換 同樣先看代碼,接續代碼說明 文件結構 /ajax.py /templates /data.html /static /jquery-3.6.0.min.js /data /input.json /message.json ajax.py fromflaskimportFlask,render_template,request,jsonify,json app=Flask(__name__) @app.route('/data') defwebapi(): returnrender_template('data.html') @app.route('/data/message',methods=['GET']) defgetDataMessage(): ifrequest.method=="GET": withopen('static/data/message.json','r')asf: data=json.load(f) print("text:",data) f.close returnjsonify(data)#直接回傳data也可以,都是json格式 @app.route('/data/message',methods=['POST']) defsetDataMessage(): ifrequest.method=="POST": data={ 'appInfo':{ 'id':request.form['app_id'], 'name':request.form['app_name'], 'version':request.form['app_version'], 'author':request.form['app_author'], 'remark':request.form['app_remark'] } } print(type(data)) withopen('static/data/input.json','w')asf: json.dump(data,f) f.close returnjsonify(result='OK') if__name__=='__main__': app.run() data.html WebAPI

DATA:API

API:GET

GET

API:POST

APP_ID:

APP_NAME:

APP_VERSION:

APP_AUTHOR:

APP_REMARK:

POST

Console:

/static/jquery-3.6.0.min.js jQuery函式庫,Ajax()函式會使用到 /data/input.json 空白內容,用於寫入資料的目標檔案 /data/message.json { "appInfo":{ "id":5, "name":"Python-Flask", "version":"1.0.1", "author":"author", "remark":"Python-WebFramework" } } JSON格式資料,用於讀取資料的目標檔案 後端:網頁模版與資料接口 ajax.py @app.route('/data') defwebapi(): returnrender_template('data.html') data.html的路由註冊與模板回傳 @app.route('/data/message',methods=['GET']) defgetDataMessage(): ifrequest.method=="GET": withopen('static/data/message.json','r')asf: data=json.load(f) print("text:",data) f.close returnjsonify(data)#直接回傳data也可以,都是json格式 @app.route('/data/message',methods=['GET']):註冊路由為data/message,接收Get方法 withopen('static/data/message.json','r')asf::讀取靜態文件data資料夾下的message.json檔案 data=json.load(f):使用json物件,讀取message.json檔案內的json文字格式。

f.close:讀取完成後,關閉文件。

returnjsonify(data):data為JSON格式的字串,可以直接回傳,可以使用jsonify()函式,序列化後再進行傳遞。

@app.route('/data/message',methods=['POST']) defsetDataMessage(): ifrequest.method=="POST": data={ 'appInfo':{ 'id':request.form['app_id'], 'name':request.form['app_name'], 'version':request.form['app_version'], 'author':request.form['app_author'], 'remark':request.form['app_remark'] } } print(type(data)) withopen('static/data/input.json','w')asf: json.dump(data,f) f.close returnjsonify(result='OK') @app.route('/data/message',methods=['POST']):註冊路由為data/message,接收Get方法 data={...}:從request取得前端的提交的表單內容,儲存在字典型態的變數中 withopen('static/data/input.json','w')asf::寫入靜態文件data資料夾下的input.json檔案 json.dump(data,f):使用json物件,寫入json文字格式到input.json檔案。

f.close:讀取完成後,關閉文件。

returnjsonify(result='OK'):使用jsonify()函式,序列化JSON格式的字串,回傳resulut=OK的內容 前端:jQuery按鈕,Ajax請求Get與Post ... ... ...

Ajax會使用到jQuery的框架,導入時要注意jQuery有沒有放在static的資料夾

DATA:API

API:GET

GET

API:POST

APP_ID:

APP_NAME:

APP_VERSION:

APP_AUTHOR:

APP_REMARK:

POST

Console:

GET:GET按鈕,用來觸發Ajax訪問取得資料的API POST:POST按鈕,用來將五項輸入框的文字,透過Ajax傳遞給API :Console文字區塊,用來打印Ajax接收的資料內容 var$btnGet=$('#btnGet'); var$console=$('#console'); var$btnPost=$('#btnPost'); var$edtAppId=$('#app_id'); var$edtAppName=$('#app_name'); var$edtAppVersion=$('#app_version'); var$edtAppAuthor=$('#app_author'); var$edtAppRemark=$('#app_remark'); 使用jQuery取得Html的畫面元素 $btnGet.off('click').on('click',function(){ $.ajax({ url:'/data/message', data:{}, type:'GET', success:function(data){ $console.text(""); $console.append("data[id]:"+data.appInfo.id+"---"); $console.append("data[name]:"+data.appInfo.name+"---"); $console.append("data[version]:"+data.appInfo.version+"---"); $console.append("data[author]:"+data.appInfo.author+"---"); $console.append("data[remark]:"+data.appInfo.remark+"---"); $edtAppId.val(data.appInfo.id); $edtAppName.val(data.appInfo.name); $edtAppVersion.val(data.appInfo.version); $edtAppAuthor.val(data.appInfo.author); $edtAppRemark.val(data.appInfo.remark); }, error:function(xhr){ alert('Ajaxrequest發生錯誤'); } }); }) $btnGet.off('click').on('click',function(){}):GET按鈕點擊事件 $.ajax({}):使用jQuery的Ajax函式 url:'/data/message':訪問路徑為/data/meesage data:{}:不傳遞資料 type:'GET':使用GET方法 success:function(data){}:成功的話,觸發函式動作 $console.text("");+$console.append("..."):將資料打印在Console元件上 $edtAppXXX.val(...);:將數值內容填入到,畫面上的五個輸入框。

error:function(xhr){}:失敗的話,觸發函式動作 alert('Ajaxrequest發生錯誤');:顯示對話視窗,Ajaxrequest發生錯誤 $btnPost.off('click').on('click',function(){ $.ajax({ url:'/data/message', data:{ "app_id":$edtAppId.val(), "app_name":$edtAppName.val(), "app_version":$edtAppVersion.val(), "app_author":$edtAppAuthor.val(), "app_remark":$edtAppRemark.val(), }, type:'POST', success:function(data){ $console.text("result="); $console.append(data.result); }, error:function(xhr){ alert('Ajaxrequest發生錯誤'); } }); }); $btnPost.off('click').on('click',function(){}):POST按鈕點擊事件 $.ajax({}):使用jQuery的Ajax函式 url:'/data/message':訪問路徑為/data/meesage data:{...}:傳遞五個輸入框的文字內容 "app_id":$edtAppId.val() "app_name":$edtAppName.val() "app_version":$edtAppVersion.val() "app_author":$edtAppAuthor.val() "app_remark":$edtAppRemark.val() type:'POST':使用POST方法 success:function(data){}:成功的話,觸發函式動作 $console.text("result=");+$console.append("..."):將資料打印在Console元件上 error:function(xhr){}:失敗的話,觸發函式動作 alert('Ajaxrequest發生錯誤');:顯示對話視窗,Ajaxrequest發生錯誤 get按鈕,點擊後資料傳輸流程 post按鈕,點擊後資料傳輸流程 寫入的input.json資料內容與輸入框文字相同 開發配置-外網訪問與熱部署 補充兩個開發時,應該要知道的配置 允許外部的訪問 Debug模式 允許外部的訪問 先前的程式碼,如果試著使用,除127.0.0.1或localhost以外的網址, 例如:區域網路192.168.2.12,瀏覽器會顯示「無法連上這個網站」 Flask預設配置是不允許外部的訪問 增加配置 if__name__=='__main__': app.run('0.0.0.0') 在main方法的app.run()函式中,加上0.0.0.0的字串。

配置到產品的伺服器中,客戶端的電腦才能夠連接上網站的伺服器。

Debug模式 先前的程式碼中,任何的修改都必須要重新啟動。

(網頁的程式碼也是如此) 增加配置 if__name__=='__main__': app.run('0.0.0.0',debug=True) 在main方法的app.run()函式中,加上debug=True開啟Debug模式。

程式碼的任何修改,儲存後就會立刻生效,省去許多伺服器重新啟動的時間。

完整的程式碼 dev-config.py importflask app=flask.Flask(__name__) @app.route("/") @app.route("/hello") defhello(): return"Hello,World~!!!TextTextText~!!!" if__name__=='__main__': app.run('0.0.0.0',debug=True) 後續 第三章節Ajax資料交換,後端Python的實作是使用讀寫json的檔案,來模擬資料持久化的部分。

不過真實的後端開發,都應該會使用關聯式的資料庫,例如:MySQL、MS-SQL來進行數據的保存。

這部分,不在flask的套件裡面,必須安裝flask_sqlalchemy與相對應的pythonsql套件,才能夠進行實作。

後續會獨立說明。

參考資料 Flask官網 https://flask.palletsprojects.com/en/2.0.x/ Tutorialspoint-Flask https://www.tutorialspoint.com/flask/index.htm 程式設計 python flask 輕量級網頁框架 pythonflask   分享   共12,715次點閱 按了喜歡: 共有0則留言 還沒有人留言。

歡迎分享您的觀點、或是疑問。

您的留言 登入之後發表留言 Enoxs 7貼文  ·  1留言 查看所有文章 留言回應 × 登入之後發表留言 Close Devs.tw©2020


請為這篇文章評分?