Files
Obsidian-Main/03. Programming/Flask.md
Awin Huang c847c7f07d vault backup: 2022-09-28 19:13:41
Affected files:
.obsidian/workspace
03. Programming/COM/20210726 - COM Interface.md
03. Programming/DB/MySQL.md
03. Programming/DB/sqlite.md
03. Programming/Design Pattern.md
03. Programming/FFMPEG/00. Introduction.md
03. Programming/FFMPEG/01. Setup.md
03. Programming/FFMPEG/FFMpeg.md
03. Programming/Flask.md
03. Programming/Media Foundation/20210604 - Windows media foundation.md
03. Programming/OpenCV.md
03. Programming/OpenGL.md
03. Programming/Python/argparse.ArgumentParser.md
03. Programming/Python/decorator.md
03. Programming/Python/logging.md
03. Programming/Python/opencv.md
03. Programming/Python/subprocess.md
03. Programming/Python/threading.md
03. Programming/Python/tkinter.md
03. Programming/Python/檢測工具.md
03. Programming/QT/Dropdown button.md
03. Programming/QT/QVariant.md
03. Programming/QT/Qt.md
03. Programming/UML.md
03. Programming/演算法.md
04. 資料收集/99. templates/blogHeader.md
04. 資料收集/99. templates/date.md
04. 資料收集/99. templates/front matter.md
04. 資料收集/99. templates/note.md
04. 資料收集/99. templates/table.md
04. 資料收集/99. templates/thisWeek.md
04. 資料收集/99. templates/日記.md
04. 資料收集/99. templates/讀書筆記.md
04. 資料收集/Linux/CLI/cut.md
04. 資料收集/Linux/CLI/scp.md
04. 資料收集/Linux/CLI/timedatectl.md
04. 資料收集/Linux/Programming.md
04. 資料收集/Linux/Ubuntu.md
04. 資料收集/Tool Setup/Hardware/RaspberryPi.md
04. 資料收集/Tool Setup/Software/Chrome.md
04. 資料收集/Tool Setup/Software/Obisidian.md
04. 資料收集/Tool Setup/Software/SublimeText.md
04. 資料收集/Tool Setup/Software/VirtualBox.md
04. 資料收集/Tool Setup/Software/Visual Studio Code.md
04. 資料收集/Tool Setup/Software/Windows Setup.md
04. 資料收集/Tool Setup/Software/Windows Terminal.md
04. 資料收集/Tool Setup/Software/freefilesync.md
04. 資料收集/Tool Setup/Software/vim.md
04. 資料收集/名言佳句.md
04. 資料收集/架站/Gitea.md
04. 資料收集/架站/HTTP Server/Apache.md
04. 資料收集/架站/HTTP Server/Nginx/Reverse Proxy(Layer4).md
04. 資料收集/架站/Pelican blog.md
04. 資料收集/架站/Proxmox VE.md
04. 資料收集/架站/SWAG Reverse proxy.md
04. 資料收集/架站/Storj.md
04. 資料收集/架站/Trojan.md
04. 資料收集/每週外食.md
04. 資料收集/科技/802.11.md
04. 資料收集/科技/HDR Sensor.md
04. 資料收集/科技/量子電腦.md
04. 資料收集/科技/鋰電池.md
04. 資料收集/興趣嗜好/RC/Traxxas Sledge.md
04. 資料收集/興趣嗜好/RC/好盈電變調整中立點.md
04. 資料收集/興趣嗜好/RC/差速器調教教學.md
04. 資料收集/興趣嗜好/模型/舊化作例.md
04. 資料收集/興趣嗜好/軍武/虎式.md
04. 資料收集/讀書筆記/20201201 - 學習如何學習.md
04. 資料收集/讀書筆記/20201218 - Kotlin權威2.0.md
04. 資料收集/讀書筆記/20201224 - 寫作是最好的自我投資.md
04. 資料收集/讀書筆記/20210119 - 中產悲歌.md
04. 資料收集/讀書筆記/20210220 - 最高學習法.md
04. 資料收集/讀書筆記/20210320 - 最高學以致用法.md
04. 資料收集/讀書筆記/20210406 - 精準購買.md
04. 資料收集/讀書筆記/20210723 - 高手學習.md
04. 資料收集/讀書筆記/20220526 - 深入淺出設計模式.md
04. 資料收集/讀書筆記/20220619 - 精確的力量.md
04. 資料收集/軟體工具/IPFS.md
04. 資料收集/軟體工具/MkDocs.md
04. 資料收集/軟體工具/Obsidian.md
04. 資料收集/軟體工具/docker.md
04. 資料收集/軟體工具/git/apply.md
04. 資料收集/軟體工具/git/submodule.md
04. 資料收集/軟體工具/youtube-dl.md
04. 資料收集/面試準備/技术面试最后反问面试官的话.md
2022-09-28 19:13:41 +08:00

206 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 執行
### Linux
```bash
export FLASK_APP=RobotRunAutoServer.py
export FLASK_DEBUG=1
flask run --reload
```
### Windows
```
set FLASK_APP=RobotRunAutoServer.py
set FLASK_DEBUG=1
flask run --reload
```
## 路由
```python
@app.route('/')
def index():
return 'Index Page'
@app.route('/query/<SOMETHING>', methods=['GET', 'POST'])
def query(SOMETHING):
return 'Hello, {}!'.format(SOMETHING)
```
## 靜態檔案
```
url_for('static', filename='style.css')
```
## 模板
```python
from flask import render_template
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
```
依照 Flask 的慣例,它會在 templates 資料夾內去找模板檔,而 templates 資料夾的位置會根據這支 web app 是模組或是套件而有所不同。
如果是模組:
```
/application.py
/templates
/hello.html
```
如果是套件:
```
/application
/__init__.py
/templates
/hello.html
```
## 存取 request 資料
客戶端傳來的資料都放在 `request` 這個全域變數內web app 利用 `request` 提供的資訊與客戶端互動。
客戶端的 HTTP 方法存放在 `request``method` 屬性內,而 form 就存放在 `request``form` 屬性內。示例:
```Python
from flask import request
from flask import render_template
@app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'], request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username / password'
# the code below is executed if the request method was GET or the credentials were invalid
return render_template('login.html', error=error)
```
如果 `form` 屬性不存在,伺服器端會引發 `KeyError` 錯誤,客戶端則會收到 HTTP 400 錯誤。
如果是要取用 `URL` 參數,則使用 `args` 屬性內的 `get()` 方法:
```Python
searchword = request.args.get('key', '')
```
如果是要取用客戶端上傳的檔案,先確定在前端 HTML 表單的設定正確的屬性 `enctype="multipart/form-data"`,瀏覽器才會正確的把檔案上傳。調用 `request``files` 屬性就可以調用到檔案:
```Python
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
```
`files` 本身是個 dictionary所以必須呼叫它裡面的 key 才會接到真正的檔案,這個 `file` 物件的行為就像標準的 Python `file` 物件,但它有個 `save()` 方法讓我們把檔案存到自己想要的路徑。
如果想要沿用客戶端上傳的檔名,則調用 `filename` 屬性,但由於檔名的不可預知,可能會有安全風險,最好用 Werkzeug 的 `secure_filename()` 方法過濾掉:
```Python
from flask import request
from werkzeug.utils import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
```
如果是要讀取 cookie 就調用 `request` 物件的 `cookies` 屬性,如果是要設置 cookie 就用 `response` 物件的 `set_cookie()` 方法。
`request``cookies` 也是一個 dictionary裡面放了所有可以調用的 cookie。
但是如果想使用 session 的話Flask 有提供更完善的 session 機制可以利用,不要手工用 cookie 來管理 session。
讀取 cookie 的範例:
```Python
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a KeyError if the cookie is missing.
```
存入 cookie 的範例:
```Python
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp
```
## 重導頁面與錯誤頁面
要重導使用 `redirect()` 方法,要中斷並報錯用 `abort()` 方法:
```Python
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
```
如果不想使用 Flask 預設的陽春錯誤頁,則利用 `errorhandler()` 修飾子來做客製:
```Python
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
```
注意到 `return` 那行最後面的 `404`,雖然上面的修飾子已經是 404`return` 後面還是要加 `404` Flask 才認得這是 404 錯誤頁。
## Session
Session 用來紀錄、辨識用戶的活動,實現方式是加密過的 cookie。
得先設置密鑰才能使用 session
```Python
from flask import Flask, session, redirect, url_for, escape, request
from werkzeug.utils import secure_filename
app = Flask(__name__)
# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
@app.route('/')
def index():
if 'username' in session:
return f"Logged in as {escape(session['username'])}"
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
```
前面模板的章節有說過,模板引擎會幫我們把表單的 HTML 過濾掉,而在這裡沒有使用模板引擎,所以手動調用了 `escape()` 方法來濾掉 HTML 碼。
最後附註一點,瀏覽器可能會限制單一 cookie 容量,如果發現某個值應該要有卻調用不出來的話,想想看是不是超過 cookie 的容量上限了。
## Log 紀錄
Flask app 物件有使用 Python 內建的 `logger` 模組,可以簡單調用:
```Python
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')
```