如果在網頁中輸入了非預期的 URL,或是做出非預期的動作時,正常會出現 404 Not Found
對吧!不過有些網站的 404 Not Found
就是做得跟其他網站不一樣,不單單只是出現簡單的文字而已,有些甚至還有圖片以及按鈕對吧。
那我們要如何再產生這樣的錯誤時,自動出現這樣精美的畫面呢?或是更進一步,由我們定義如果出現了某些行為,就自動地提出錯誤並處裡呢?
既然前面提到了 404 那我就用 404 來實際做個範例吧。
首先,又是使用我們前面的架構來舉例:
ithome
├── static # 改回這樣比較清楚吧
│ └── logo.svg
├── templates
│ ├── res
│ │ └── home.html
│ ├── base.html
│ ├── index.html
│ └── page_not_found.html # 新增它
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock
先來製作個簡單的 404 Not Found
的畫面吧。
page_not_found.html
{% extends 'base.html' %}
{% block title %}
Error
{% endblock %}
{% block img %}
<img src={{ url_for('static', filename='logo.svg' ) }} />
{% endblock %}
{% block content %}
{% if error %}
<p>{{ error }}</p>
{% endif %}
<a href={{ url_for('index') }}><button>Index</button></a>
{% endblock %}
然後再 app.py
寫一個處裡 404 錯誤的 function 就可以了。
app.py
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html', error=error)
這樣寫裝士氣的話就可以再產生 404 錯誤的時候,有個單獨的頁面去顯示錯誤,而不再只是簡單的文字而已。就像這樣:
看到這裡,就對錯誤處理有個大概的了解了吧。裝飾器 errorhandler 是指定如果抓到什麼樣的錯誤就進行下面 function 的動作。
那如果要更進一步,主動產生錯誤的話怎麼辦呢?
其實 Flask 有一個 abort 的 function 可以主動產生錯誤。那就接著上面的架構再增加一個主動提出 401 錯誤的 url,實作大概長這樣:
app.py
@app.route('/xyz')
def abc():
abort(401)
大概就是這樣。
那如果要回應的不僅僅是只有頁面,甚是還有 HTTP 的標頭,或是包含狀態碼,那又要如何回應呢?讓我們使用前面的錯誤處裡來舉例:
@app.errorhandler(404)
def page_not_found(error):
response = make_response(render_template('res/page_not_found.html', error=error), 404)
response.headers['ABC'] = 'A value'
return response
如果直接 return render_template
的話,雖然可以設定到有關標頭或狀態碼,但如果要設定的項目較多,會變成非常長,所以有必要先建立一包回應的東西,再將所有設定都設好,最後再進行回傳,
使用 make_response
便是製作回應包,第一個參數便是要回應的內容,第二個則是狀態碼,而下面便是設定標頭了。
如果按下 F12 打開 Network
,就可以看到回傳標頭的狀態碼是 404,以及設定好的標頭。像這樣:
如果接不設定就會像這樣:
那麼就大概這樣,如果做好錯誤處理,便可以避免意外的中斷;做好回應,便可以在後面設定更多東西。
大家掰~掰~