Flask[1]
- 陳柏安
- 建資38th 社長&網管
- 興趣
- 打電動(最近玩Apex)
- 看小說
- 睡覺(?
- 一樣繼續推銷社網
- 有沒有人要教我算法
講師介紹
還沒有個人網站 退幹做吧


Review
快一個月前的東西 允許我偷一下人家簡報
環境設置&Python語法
前端(HTML&CSS的部分)
Flask Quick Start
正式的現在才開始
首先...
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"step1. 創個py檔叫app.py
step2. 複製貼上左邊的
step3. 開terminal輸入 flask run
(不行的話用python -m flask run)
step4. enter之後點 http://127.0.0.1:5000

J個
沒意外的話你會看到這個

你已經會寫後端了
You did it ! 🥳
好啦顯然還有一段路
解釋一下剛剛幹了什麼
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"引入Flask這個class
(約等於central object)
__name__ : 目前檔案名稱
route 裝飾器:裡面放路徑
URL相同時會觸發後續的東東
hello_world() 這個函式
(管你叫他什麼 anyways )
回傳的東西會呈現在網站上
預設是HTML,所以這邊用<p></p>
這邊是「根目錄」
可以加
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "<p>Hello, World!</p>"
if __name__ == '__main__':
app.run(debug=True,port=8080)- 加了run():直接執行這個檔案會有一樣效果
- debug=True:進debug mode
- code會實時更新
error時會有醜醜的報錯頁面
__main__:「頂層程式碼環境」(官方)第一個指定的python模組or檔案
到這邊...你已經理解最基本的東西了!

不過還有得學
Routing
先補一下何謂URL
- 統一資源定位器(俗稱網址)
- 顧名思義就是地址,標示精確位置

路徑,route()裡面的就是在指定這部分
絕對路徑 v.s. 相對路徑
- 絕對路徑
- 從作業系統or網站的根目錄開始算的路徑
- e.g. https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=RDdQw4w9WgXcQ&start_radio=1
- 相對路徑
- 相對於「資料夾or網頁當前位置的路徑」
- 「./」是指當前這層目錄往下找,「../」是會回到上層
- e.g. 從index.html找style.css:「../static/style.css」

再簡單講一下Routing
Routing在網頁開發上指的是把特定URL映射到特定頁面or函式
而flask的routing是使用@app.route()
route()是一個function綁一個URL
但現代的網頁應用通常都會用到兩個以上的URL,同時名字也會取有意義的
所以通常會用很多個route()
兩個以上的URL
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "<h1>Index Page</h1>"
@app.route("/hello")
def hello():
return "<h1>Hello, World</h1>"
@app.route("/sixseven")
def sixseven():
return "<h1>liu qi</h1>"
if __name__ == "__main__":
app.run(debug=True, port=8080)


http://127.0.0.1:8080/sixseven
http://127.0.0.1:8080/
http://127.0.0.1:8080/hello
動態調整route()
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "<h1>Index Page</h1>"
@app.route("/hello/<name>")
def hello(name):
return f'Hello, {name}'
@app.route("/add/<int:a>/<int:b>")
def add(a,b):
return f'{a} + {b} = {a+b}'
if __name__ == "__main__":
app.run(debug=True, port=8080)

- 用<>包住變數
- 可以宣告變數型別(如int)
小小補充
from flask import Flask
app = Flask(__name__)
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
if __name__ == "__main__":
app.run(debug=True, port=8080)路徑的指定有一些小細節,以左為例:
如果你打/projects,他會自動幫你跳到/projects/,但如果你打/about/的話,他會認定沒對到就404

考考你
安安最近在學排列組合,所以他對階乘十分感興趣,然後他又學了flask,所以他想寫一個 /factorial/<int:a> 來幫他算階乘並且顯示算式 e.g. 6! =720,請問他該如何實作?
提示:python有個函式庫叫math,裡面什麼算式都有(當然你要用recursive、loop手刻我也不反對)

ANS
from flask import Flask
import math
app = Flask(__name__)
@app.route("/factorial/<int:a>")
def get_factorial(a):
return f'{a}! = {math.factorial(a)}'
if __name__ == '__main__':
app.run(debug=True,port=8080)
Templates
模板
模板是啥
python要生成整個HTML檔其實很麻煩,所以就用到了模板
可以想成存放靜態資料(e.g. CSS)與生成動態資料(e.g.使用者的資訊) 的檔案,省力很多
在flask裡我們會用render_template()這個函式來渲染模板(這邊是HTML)
from flask import render_template基本的模板渲染

step1. 在你的檔案夾裡創一個templates資料夾
step2. 創一個index.html
注意:資料夾一定要叫templates
step3. 進入index.html按驚嘆號後按tab
step4. 在body裡面亂打東西(不會前端的就複製我的吧:) )
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0">
<title>拳上</title>
</head>
<body>
<p>
這是一個不公平的比賽啊<br>
欸笑死人欸<br>
他剛剛打我我有退嗎<br>
我一步都沒有退欸<br>
欸你們裁判是怎麼判的啊<br>
欸不是<br>
我一步都沒有退然後判我輸喔<br>
被我打到流鼻血的贏喔<br>
有沒有邏輯啊不是啊<br>
我把他打到噴鼻血 這樣算我輸喔<br>
他打我 我一步都沒有退ㄟ<br>
啊這樣算我輸喔<br>
你們裁判怎麼判的啦<br>
好啦 我要回家了啦<br>
50萬匯給你啦 乞丐<br>
</p>
</body>
</html>index.html
step5. 在app.py引入render_template()
step6. 建立一個路徑然後對應的函式回傳render_template()後執行app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def punch():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True,port=8080)app.py
東西跑出來就代表你已經會基本的模板渲染了

動態資料的生成
要動態生成資料需要模板引擎的協助
有了模板引擎,你可以透過表達式(變數、運算子...)/陳述式(if、for...)生成動態的資料,並附著在模板上
而flask推薦的是Jinja(在pip install的時候會順便一起載)



Jinja?
顯然不是
Jinja

好啦logo真的是神社
- only for Python
- 將Python語法嵌入HTML、XML、CSV等等以文字為基礎的格式檔
- 優點:簡單好上手、算快、乾乾淨淨
- 缺點:就只支援Python、專案規模大一點性能不如某些前端框架(e.g. React、Vue),維護難度也會比較高
Jinja-表達式
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/<name>')
def sixseven(name):
l=[1,2,3,4,5,6,7]
return render_template('index.html',name=name,
l=l)
if __name__ == '__main__':
app.run(debug=True,port=8080)<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>67</title>
</head>
<body>
<h1>{{ name }}{{ 33 + 34 }}🗣️🔥🔥🔥</h1>
<p>{{ l }}</p>
<p>{{ True and False }}</p>
</body>
</html>用兩個大括號{{ ... }}括起來
app.py
index.html
Jinja-表達式

Result

Jinja-陳述式
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/<number>')
def odd_or_even(number):
numbers=[1,2,3,4,5,6,7,8]
return render_template('index.html',number=number,numbers=numbers)
if __name__ == '__main__':
app.run(debug=True,port=8080)用大括號跟百分比符號{% ... %}括起來
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Odd or Even</title>
</head>
<body>
{% if (number | int) % 2 == 0 %}
<h1>even</h1>
{% else %}
<h1>odd</h1>
{% endif %}
{% for i in numbers %}
<p>{{ i }}</p>
{% endfor %}
</body>
</html>app.py
index.html
(補充)pipe,可以將變數進行格式化轉換
有興趣的話可以看看這篇
Jinja-陳述式
Result


Jinja-註解
用大括號跟井字號{# ... #}括起來
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>註解</title>
</head>
<body>
{# 註解 #}
</body>
</html>補個靜態檔案存放
要開一個static資料夾放東西在裡面(只能叫static)

最簡單的長這樣
補個Url_for()
顧名思義 找路徑的函式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>首頁</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<p>abc</p>
</body>
</html>index.html

這邊的話是去static這個資料夾
Url_for()
顧名思義 找路徑的函式
from flask import Flask, url_for
app = Flask(__name__)
@app.route("/")
def home():
return "Hello World"
@app.route("/test")
def test():
return url_for('home') #這邊的話就是會回傳home這個function代表的路徑
if __name__ == "__main__":
app.run(debug=True, port=8080)
app.py
Jinja-模板繼承
- jinja最主要也最強大的功能
- 有一個基底的html,其他html檔可以以此為底,還可以加新東西
- 專業一點:
- 會有一個base.html,其他的html檔可以extends
- 沒有要繼承的東西會被
{% block %} 這個tag框起來

舉個🌰
{% extends "base.html" %}
{% block title %}首頁{% endblock %}
{% block content %}
<h1>Youtube 前五點閱量的影片</h1>
<ol>
<li><a href="https://reurl.cc/r0rOp1">Baby Shark Dance</a></li>
<li><a href="https://reurl.cc/0m9ML6">Despacito</a></li>
<li><a href="https://reurl.cc/A94vxd">Wheels on the Bus</a></li>
<li><a href="https://reurl.cc/gr4X94">Bath Song</a></li>
<li><a href="https://reurl.cc/ovrElV">Johny Johny Yes Papa</a></li>
</ol>
{% endblock %}index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<p>這東西沒被block框起來所以會被繼承</p>
<div>
{% block content %}這東西被block框起來了所以不會被繼承{% endblock %}
</div>
</body>
</html>base.html
{% block %} tag
extends→以哪個檔案為基底
定義block的名字
舉個🌰

index.html
block 補充
Block 不能被定義兩次
所以在重複引用的時候會要用self.(block的名字)()
{% extends "base.html" %}
{% block title %}首頁{% endblock %}
{% block content %}
<h1>self.title()</h1>
<ol>
<li><a href="https://reurl.cc/r0rOp1">Baby Shark Dance</a></li>
<li><a href="https://reurl.cc/0m9ML6">Despacito</a></li>
<li><a href="https://reurl.cc/A94vxd">Wheels on the Bus</a></li>
<li><a href="https://reurl.cc/gr4X94">Bath Song</a></li>
<li><a href="https://reurl.cc/ovrElV">Johny Johny Yes Papa</a></li>
</ol>
{% endblock %}
考考你
阿盛是知名的直播主,所以他常常要注意一堆莫名其妙的危險字眼以防止台被ban,例如黑X。今天他在後端整理出了一個list是聊天室的重點訊息,但已知裡面有一些混到「黑X」這個字,想請你幫他在前端渲染的過程中,如果內文有「黑X」就把它顯示成 [你已被管理員禁言600秒],沒的話就正常顯示純文字<p></p>。

texts=["黑豆漿","支","嚴厲斥責","紫海膽aka黑鬼","7777777","發瘋啦","阿盛知道台東有黑鬼湖嗎","超負荷OK 超負荷加油","Hey Girl翻成中文是黑鬼兒嗎","還真的 笑死"]提示:檢查子字串可以用in e.g. "abc" in text
list在這邊
ANS
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
texts=["黑豆漿","支","嚴厲斥責","紫海膽aka黑鬼","7777777","發瘋啦","阿盛知道台東有黑鬼湖嗎","超負荷OK 超負荷加油","Hey Girl翻成中文是黑鬼兒嗎","還真的 笑死"]
return render_template('index.html',texts=texts)
if __name__ == "__main__":
app.run(debug=True, port=8080)app.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>filter</title>
</head>
<body>
{% for text in texts %}
{% if "黑鬼" in text %}
<p>[你已被管理員禁言600秒]</p>
{% else %}
<p>{{ text }}</p>
{% endif %}
{% endfor %}
</body>
</html>index.html
ANS

上完了 噎
Flask[1]
By amberchen
Flask[1]
- 33