# Python Flask 資訊之芽 梁安哲 2022/05/15 --- ## 大家好久不見 超級貓貓星際漫遊3 有解出來嗎 --- ## 課程大綱 1. 基礎網路知識 2. Flask 基本架構 3. Routing 路由 4. Template 模板 5. Form 表單 6. Deploy 部屬 --- ## 課程資料 下載: https://github.com/maowman/py-flask 順便複習上周的內容。 --- ## 基礎網路知識 ---- ### 我們怎麼看到網頁的 ---- ![](https://i.imgur.com/Okt0EQz.jpg) ---- ### 假設你今天想要訪問`http://www.example.com/` ![](https://i.imgur.com/K2Dvbds.png) ---- ### DNS(Domain Name System) ![](https://i.imgur.com/HQLHChp.png) ---- ### 利用 HTTP/HTTPS 請求網頁內容 ![](https://i.imgur.com/PTiZgzk.png) ---- ### 接收檔案 1. 程式檔 (Code files): HTML , CSS , Javascript , webassembly 2. 資產檔 (Asset): 圖片 , 影片 , 音樂 ... ![](https://i.imgur.com/srCExD0.png) ---- ### 渲染頁面 ![](https://i.imgur.com/XQGAszj.jpg) ---- ### 那Python去哪裡了? ---- ### 前端、後端? 前端是瀏覽器上運行的程式碼。由於瀏覽器上只能執行HTML、CSS、Javascript、webassembly,因此前端只以這四種語言構成。 後端是伺服器上運行的程式碼。基本上可以使用任何程式語言。 ---- ### Why 框架 1. 提供函式庫、應用程式架構 2. 易於維護、更新 3. 其他人也在用 ---- ### Which 框架 ![](https://i.imgur.com/BLLOc5c.png) [source](https://blog.back4app.com/backend-frameworks/) --- ## Flask 基本架構 ---- ### 前置作業 1. 安裝套件 `pip install flask` 2. 準備一個獨立的資料夾裝所有檔案 ---- ### Hello Sprout ! ``` python= from flask import Flask app = Flask(__name__) @app.route("/") def hello_sprout(): return "<h1>Hello, Sprout! My name is 超級貓貓男</h1>" if __name__ == "__main__": app.run() ``` ---- ### 初始化 ``` python= from flask import Flask app = Flask(__name__) ``` ---- ### 建立路由(route)與頁面(view) ``` python= @app.route("/") def hello_sprout(): return "<h1>Hello, Sprout! My name is 超級貓貓男</h1>" ``` ---- ### 執行網路應用程式 ```python= if __name__ == "__main__": app.run() ``` ---- ### 另外一個方法 1. 設定環境變數。 - Windows cmd: ```set FLASK_APP=sprout-1``` - Windows Powershell: ```$env:FLASK_APP = "sprout-1"``` - Mac/Linux: ```export FLASK_APP=sprout-1``` 2. 執行```flask run``` ---- ![](https://i.imgur.com/hxoVg1e.png) ---- ![](https://i.imgur.com/xKoKDRz.png) ---- ### 現在是...練習時間 讓伺服器顯示自己的名字。 執行的時候使用```app.run(host="0.0.0.0")```。 ---- ### 補充說明 ``` <h1>Hello, Sprout! My name is 超級貓貓男</h1> ``` 這東西超怪對吧 ---- ### 看看資芽官網 ```html= <div id="back"> <img class="logo" src="/spt/index_bk1.png"></img> <div id="nav"> <ul class="rside"> <li class="plan"><a href="javascript:reload_page('/spt/')">計劃</a></li> <li class="about"><a href="javascript:reload_page('/spt/about/')">關於</a></li> <li class="qa"><a href="javascript:reload_page('/spt/qa/')">Q&amp;A</a></li> </ul> <ul class="lside"> <li class="rule"><a href="javascript:reload_page('/spt/rule/')">規則</a></li> <li class="poll"><a href="javascript:reload_page('/spt/poll/')">評價</a></li> <li class="indiv"><a href="javascript:reload_page('/spt/indiv/');">個人</a></li> </ul> </div> <div class="foot"> <span>訊息公告暨粉絲專頁: <a href="https://www.facebook.com/ntucsiesprout"><u>資訊之芽培訓計畫</u></a></span><br> <span>電子郵件地址: <a href="mailto:sprout@csie.ntu.edu.tw">sprout@csie.ntu.edu.tw</a></span><br> <span></span><br> </div> </div> <div id="main"></div> <div id="overlay"> <img src="/spt/ring-alt.svg" id="loading"></img> </div> ``` ---- ### HTML ![](https://i.imgur.com/HhX59e9.png) ref: https://developer.mozilla.org/en-US/docs/Glossary/Element 因為我們是教Python,所以不會太深入講。有興趣的學員可以參考[這裡](https://www.w3schools.com/html/)。 --- ## Routing 路由 ---- ![](https://i.imgur.com/TJoMHXn.png) ![](https://i.imgur.com/rL5DKtH.png) ![](https://i.imgur.com/5frAL59.png) 網站上可以有很多頁面(view),可以通過不同路由(route)存取 ---- ```python= @app.route("/lecturer") def lecturer(): return '<blockquote class="imgur-embed-pub" lang="en" data-id="a/5Hh8HRm" data-context="false" ><a href="//imgur.com/a/5Hh8HRm"></a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>' @app.route("/price") def fee(): return "<p>兩個階段都1700</p>" ``` ---- ### 動態路由 ```python= @app.route("/student/<studentName>") def hello_student(studentName): return f"<h1>Hello, {studentName}!</h1>" ``` ---- ### HTTP 協定 ```python= @app.route("/secret") def getSecret(): try: inputPassword = request.args.get("password") if (password != inputPassword ): raise Exception("Password incorrect") return "<h1>我的房子還蠻大的</h1>" except Exception as e: return f"403 Forbidden : {e}" , 403 ``` ---- #### HTTP 有用的小知識 parameters ![](https://i.imgur.com/vU7pzy4.png) ---- status code ![](https://i.imgur.com/vAZH1qr.png) ---- ### Redirect ```python= @app.route("/rick") def rickroll(): return redirect("https://www.youtube.com/watch?v=dQw4w9WgXcQ") ``` ---- ### 現在是...練習時間 做一個網站顯示造訪人次 --- ## Template 模板 ---- ### 前置作業 1. 建立名為```templates```的資料夾放模板檔案(一字不差) ---- ### 邏輯與頁面分離 ```python= @app.route("/") def index(): return render_template("index.html") ``` ```html= <h1>Hello Sprout!</h1> ``` ---- ### Jinja2 模板引擎 動態渲染網頁內容 ---- ### 變數 ```python= @app.route("/jay") def jaySayHi(): return render_template("jay.html" , longName = "阿傑" , shortName = "傑哥") ``` ```html= <h1>對了,我叫{{ longName }},我也常來這裡玩,痾,他們都叫我{{ shortName }}。</h1> ``` ---- ### 條件 ```python= @app.route("/adult") def adult(): age = 0 try: age = int( request.args.get("age")) except Exception as e: print(e) return render_template("adult.html" , age = age ) ``` ```html= <h1>都{{ age }}歲了還那麼害羞</h1> {% if age > 18 %} <h1>還可以教你登大人喔</h1> {% else %} <h1>但是你不能登大人。</h1> {% endif %} ``` ---- ### 迴圈 ```python= @app.route("/store") def store(): cart = {"酒":10 , "麵包":20 , "南瓜":887414} return render_template("store.html" , cart = cart ) ``` ```html= <h1>什麼都可以拿嗎杰哥?</h1> {%for item , quantity in cart.items() %} <p>{{item}} 買了 {{quantity}} 個。</p> {% endfor %} ``` ---- ### 繼承 ```html= {% block title %} <h1>國立臺灣大學</h1> <p> 國立臺灣大學是一所積極新創、學科齊全、學術實力雄厚、辦學特色鮮明,在國際上具有重要影響力與競爭力的大學,在多個學術領域具有非常前瞻的科技實力,擁有世界一流的實驗室與師資力量,各種排名均位於全球前列。歡迎大家報考國立臺灣大學。 </p> <a href="{{url_for("ntu")}}">返回主頁</a> {% endblock %} {% block content %} {% endblock %} ``` ---- ```python= @app.route("/ntu") def ntu(): return render_template("ntu.html") ``` ```html= {% extends "ntuBase.html" %} {% block title %} {{super()}} <style> h1{ color: red; } </style> {% endblock %} {% block content %} <p>國立臺灣大學前身為日治時期之「臺北帝國大學」(創立於日本昭和3年、西元1928年、民國17年)。當時首任校長為幣原坦總長;至民國34年(1945年)二次世界大戰結束,日本投降、臺灣光復,同年11月15日我政府完成接收臺北帝國大學,改制更名為「國立臺灣大學」,由羅宗洛博士任首任校長。</p> {% endblock %} ``` ---- 安裝套件```pip install xlrd``` ```python= @app.route("/ntu/<departmentCode>") def department(departmentCode): workbook = xlrd.open_workbook_xls("dpt_code.xls") worksheet = workbook[0] info = f"{departmentCode} 沒有這個科系" for row , code in enumerate(worksheet.col(1)): if (code.value == departmentCode): info = f"{departmentCode}-{worksheet.cell_value(row , 2)} {worksheet.cell_value(row , 6)}" return render_template("department.html" , info = info) ``` ```html= {% extends "ntuBase.html" %} {% block title %} {{super()}} {% endblock %} {% block content %} <p>{{info}}</p> {% endblock %} ``` ---- ### 現在是...練習時間 嘗試利用前面的內容,製作一個高中學校代碼查詢系統。 可以參考```99hscode.xls```。 --- ## Form 表單 ---- ### 前置作業 1. 安裝套件 `pip install flask-wtf` ---- ### 我們可能需要什麼? 資料雙向的流通 ---- ### HTTP method 1. GET 從伺服器拿資料。 2. POST 把資料給伺服器。 ---- ### Form ```python= from flask_wtf import FlaskForm from wtforms import StringField , SubmitField , IntegerField from wtforms.validators import DataRequired class rollcallForm(FlaskForm): name = StringField("你的名字:" , validators=[DataRequired()]) email = StringField("你的電子信箱:" , validators=[DataRequired()]) studentId = IntegerField("你的學號:" , validators=[DataRequired()]) message = StringField("其他建議:") submit = SubmitField("送出") ``` ---- ```html= <h2>資訊之芽簽到表單</h2> <h1>Hello {{name}}!</h1> <form method="POST"> {{ form.hidden_tag() }} <div> {{form.name.label}} {{form.name()}} </div> <div> {{form.email.label}} {{form.email()}} </div> <div> {{form.studentId.label}} {{form.studentId()}} </div> <div> {{form.message.label}} {{form.message()}} </div> <div> {{form.submit()}} </div> </form> ``` ---- ### Session & Flash ```python= @app.route("/", methods=["GET", "POST"]) def index(): if session.get("name") is None: flash("歡迎來到資訊之芽!") session["name"] = "資芽新學員" form = rollcallForm() if form.validate_on_submit(): session["name"] = form.name.data print(form.data) return redirect(url_for("index")) return render_template("sproutForm.html", form=form, name=session.get("name")) @app.route("/clear") def clear(): session.clear() return redirect(url_for("index")) ``` ```html= <a href="{{url_for("clear")}}">清除Session</a> ``` ---- ### 現在是...練習時間 用一個頁面顯示同一個學員在同一個 Session 的簽到記錄 --- ## Deploy 部屬 ---- ### 試試看用不同的電腦連接到自己的網站 ---- ### pythonanywhere ![](https://i.imgur.com/iqGyT06.png) ---- ![](https://i.imgur.com/g9wXsje.png) ---- ![](https://i.imgur.com/HzF5y6w.png) ---- ![](https://i.imgur.com/AQnSE3D.png) ---- ![](https://i.imgur.com/msNFeI4.png) ---- ![](https://i.imgur.com/HN0balx.png) ---- ![](https://i.imgur.com/fZjETHM.png) ---- ![](https://i.imgur.com/axuUv2u.png) ---- ![](https://i.imgur.com/OmMJ0SN.png) ---- ![](https://i.imgur.com/c4TIvYG.png) 網頁非常好 ---- ### 參考事項 1. https://help.pythonanywhere.com/pages/Flask/ --- ## The sky is the limit 出於時間因素考量,只能很粗淺的介紹。 可以試著自己從頭到尾設計一個網路應用程式。 ---- ### 延伸學習資料 1. SQL資料庫 https://flask-sqlalchemy.palletsprojects.com/en/2.x/ 2. Email發送 https://pythonhosted.org/Flask-Mail/ 3. 一堆酷東西 https://www.fullstackpython.com/flask-extensions-plug-ins-related-libraries.html 4. 編教材時用的工具書 https://www.books.com.tw/products/0010793455?sloc=main --- # 謝謝大家
{"metaMigratedAt":"2023-06-17T00:27:09.055Z","metaMigratedFrom":"Content","title":"Python Flask","breaks":true,"contributors":"[{\"id\":\"9714f580-8aea-4592-8613-b6e594740378\",\"add\":11637,\"del\":1672}]"}
    816 views