Flask[1]

  • 陳柏安
  • 建資38th 社長&網管
  • 興趣
    • 打電動(最近玩Apex)
    • 看小說
    • 睡覺(?
  • 一樣繼續推銷社網
  • 有沒有人要教我算法

講師介紹

還沒有個人網站 退幹做吧

Instagram

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

上完了 噎

Made with Slides.com