日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《Flask 入门教程》第 6 章:模板优化

發(fā)布時間:2023/12/31 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Flask 入门教程》第 6 章:模板优化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這一章我們會繼續(xù)完善模板,學(xué)習(xí)幾個非常實用的模板編寫技巧,為下一章實現(xiàn)創(chuàng)建、編輯電影條目打下基礎(chǔ)。

自定義錯誤頁面

為了引出相關(guān)知識點,我們首先要為 Watchlist 編寫一個錯誤頁面。目前的程序中,如果你訪問一個不存在的 URL,比如 /hello,Flask 會自動返回一個 404 錯誤響應(yīng)。默認(rèn)的錯誤頁面非常簡陋,如下圖所示:



在 Flask 程序中自定義錯誤頁面非常簡單,我們先編寫一個 404 錯誤頁面模板,如下所示:

templates/404.html:404 錯誤頁面模板

<!DOCTYPE html> <html lang="en"> <head><meta charset="utf-8"><title>{{ user.name }}'s Watchlist</title><link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css"> </head> <body><h2><img alt="Avatar" class="avatar" src="{{ url_for('static', filename='images/avatar.png') }}">{{ user.name }}'s Watchlist</h2><ul class="movie-list"><li>Page Not Found - 404<span class="float-right"><a href="{{ url_for('index') }}">Go Back</a></span></li></ul><footer><small>&copy; 2018 <a href="http://helloflask.com/tutorial">HelloFlask</a></small></footer> </body> </html>復(fù)制代碼

接著使用 app.errorhandler() 裝飾器注冊一個錯誤處理函數(shù),它的作用和視圖函數(shù)類似,當(dāng) 404 錯誤發(fā)生時,這個函數(shù)會被觸發(fā),返回值會作為響應(yīng)主體返回給客戶端:

app.py:404 錯誤處理函數(shù)

@app.errorhandler(404) # 傳入要處理的錯誤代碼 def page_not_found(e): # 接受異常對象作為參數(shù)user = User.query.first()return render_template('404.html', user=user), 404 # 返回模板和狀態(tài)碼復(fù)制代碼

提示 和我們前面編寫的視圖函數(shù)相比,這個函數(shù)返回了狀態(tài)碼作為第二個參數(shù),普通的視圖函數(shù)之所以不用寫出狀態(tài)碼,是因為默認(rèn)會使用 200 狀態(tài)碼,表示成功。

這個視圖返回渲染好的錯誤模板,因為模板中使用了 user 變量,這里也要一并傳入?,F(xiàn)在訪問一個不存在的 URL,會顯示我們自定義的錯誤頁面:



編寫完這部分代碼后,你會發(fā)現(xiàn)兩個問題:

  • 錯誤頁面和主頁都需要使用 user 變量,所以在對應(yīng)的處理函數(shù)里都要查詢數(shù)據(jù)庫并傳入 user 變量。因為每一個頁面都需要獲取用戶名顯示在頁面頂部,如果有更多的頁面,那么每一個對應(yīng)的視圖函數(shù)都要重復(fù)傳入這個變量。
  • 錯誤頁面模板和主頁模板有大量重復(fù)的代碼,比如 <head> 標(biāo)簽的內(nèi)容,頁首的標(biāo)題,頁腳信息等。這種重復(fù)不僅帶來不必要的工作量,而且會讓修改變得更加麻煩。舉例來說,如果頁腳信息需要更新,那么每個頁面都要一一進(jìn)行修改。

顯而易見,這兩個問題有更優(yōu)雅的處理方法,下面我們來一一了解。

模板上下文處理函數(shù)

對于多個模板內(nèi)都需要使用的變量,我們可以使用 app.context_processor 裝飾器注冊一個模板上下文處理函數(shù),如下所示:

app.py:模板上下文處理函數(shù)

@app.context_processor def inject_user(): # 函數(shù)名可以隨意修改user = User.query.first()return dict(user=user) # 需要返回字典,等同于return {'user': user}復(fù)制代碼

這個函數(shù)返回的變量(以字典鍵值對的形式)將會統(tǒng)一注入到每一個模板的上下文環(huán)境中,因此可以直接在模板中使用。

現(xiàn)在我們可以刪除 404 錯誤處理函數(shù)和主頁視圖函數(shù)中的 user 變量定義,并刪除在 render_template() 函數(shù)里傳入的關(guān)鍵字參數(shù):

@app.context_processor def inject_user():user = User.query.first()return dict(user=user)@app.errorhandler(404) def page_not_found(e):return render_template('404.html'), 404@app.route('/') def index():movies = Movie.query.all()return render_template('index.html', movies=movies)復(fù)制代碼

同樣的,后面我們創(chuàng)建的任意一個模板,都可以在模板中直接使用 user 變量。

使用模板繼承組織模板

對于模板內(nèi)容重復(fù)的問題,Jinja2 提供了模板繼承的支持。這個機(jī)制和 Python 類繼承非常類似:我們可以定義一個父模板,一般會稱之為基模板(base template)。基模板中包含完整的 HTML 結(jié)構(gòu)和導(dǎo)航欄、頁首、頁腳都通用部分。在子模板里,我們可以使用 extends 標(biāo)簽來聲明繼承自某個基模板。

基模板中需要在實際的子模板中追加或重寫的部分則可以定義成塊(block)。塊使用 block 標(biāo)簽創(chuàng)建, {% block 塊名稱 %}作為開始標(biāo)記,{% endblock %} 或 {% endblock 塊名稱 %} 作為結(jié)束標(biāo)記。通過在子模板里定義一個同樣名稱的塊,你可以向基模板的對應(yīng)塊位置追加或重寫內(nèi)容。

編寫基礎(chǔ)模板

下面是新編寫的基模板 base.html:

templates/base.html:基模板

<!DOCTYPE html> <html lang="en"> <head>{% block head %}<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{{ user.name }}'s Watchlist</title><link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"><link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">{% endblock %} </head> <body><h2><img alt="Avatar" class="avatar" src="{{ url_for('static', filename='images/avatar.png') }}">{{ user.name }}'s Watchlist</h2><nav><ul><li><a href="{{ url_for('index') }}">Home</a></li></ul></nav>{% block content %}{% endblock %}<footer><small>&copy; 2018 <a href="http://helloflask.com/tutorial">HelloFlask</a></small></footer> </body> </html>復(fù)制代碼

在基模板里,我們添加了兩個塊,一個是包含 <head></head> 內(nèi)容的 head 塊,另一個是用來在子模板中插入頁面主體內(nèi)容的 content 塊。在復(fù)雜的項目里,你可以定義更多的塊,方便在子模板中對基模板的各個部分插入內(nèi)容。另外,塊的名字沒有特定要求,你可以自由修改。

在編寫子模板之前,我們先來看一下基模板中的兩處新變化。

第一處,我們添加了一個新的 <meta> 元素,這個元素會設(shè)置頁面的視口,讓頁面根據(jù)設(shè)備的寬度來自動縮放頁面,讓移動設(shè)備擁有更好的瀏覽體驗:

<meta name="viewport" content="width=device-width, initial-scale=1.0">復(fù)制代碼

第二處,新的頁面添加了一個導(dǎo)航欄:

<nav><ul><li><a href="{{ url_for('index') }}">Home</a></li></ul> </nav>復(fù)制代碼

導(dǎo)航欄對應(yīng)的 CSS 代碼如下所示:

nav ul {list-style-type: none;margin: 0;padding: 0;overflow: hidden;background-color: #333; }nav li {float: left; }nav li a {display: block;color: white;text-align: center;padding: 8px 12px;text-decoration: none; }nav li a:hover {background-color: #111; }復(fù)制代碼

編寫子模板

創(chuàng)建了基模板后,子模板的編寫會變得非常簡單。下面是新的主頁模板(index.html):

templates/index.html:繼承基模板的主頁模板

{% extends 'base.html' %}{% block content %} <p>{{ movies|length }} Titles</p> <ul class="movie-list">{% for movie in movies %}<li>{{ movie.title }} - {{ movie.year }}<span class="float-right"><a class="imdb" href="https://www.imdb.com/find?q={{ movie.title }}" target="_blank" title="Find this movie on IMDb">IMDb</a></span></li>{% endfor %} </ul> <img alt="Walking Totoro" class="totoro" src="{{ url_for('static', filename='images/totoro.gif') }}" title="to~to~ro~"> {% endblock %}復(fù)制代碼

第一行使用 extends 標(biāo)簽聲明擴(kuò)展自模板 base.html,可以理解成“這個模板繼承自 base.html“。接著我們定義了 content塊,這里的內(nèi)容會插入到基模板中 content 塊的位置。

提示 默認(rèn)的塊重寫行為是覆蓋,如果你想向父塊里追加內(nèi)容,可以在子塊中使用 super() 聲明,即 {{ super() }}。

404 錯誤頁面的模板類似,如下所示:

templates/index.html:繼承基模板的 404 錯誤頁面模板

{% extends 'base.html' %}{% block content %} <ul class="movie-list"><li>Page Not Found - 404<span class="float-right"><a href="{{ url_for('index') }}">Go Back</a></span></li> </ul> {% endblock %}復(fù)制代碼

添加 IMDb 鏈接

在主頁模板里,我們還為每一個電影條目右側(cè)添加了一個 IMDb 鏈接:

<span class="float-right"><a class="imdb" href="https://www.imdb.com/find?q={{ movie.title }}" target="_blank" title="Find this movie on IMDb">IMDb</a> </span>復(fù)制代碼

這個鏈接的 href 屬性的值為 IMDb 搜索頁面的 URL,搜索關(guān)鍵詞通過查詢參數(shù) q 傳入,這里傳入了電影的標(biāo)題。

對應(yīng)的 CSS 定義如下所示:

.float-right {float: right; }.imdb {font-size: 12px;font-weight: bold;color: black;text-decoration: none;background: #F5C518;border-radius: 5px;padding: 3px 5px; }復(fù)制代碼

現(xiàn)在,我們的程序主頁如下所示:



本章小結(jié)

本章我們主要學(xué)習(xí)了 Jinja2 的模板繼承機(jī)制,去掉了大量的重復(fù)代碼,這讓后續(xù)的模板編寫工作變得更加輕松。結(jié)束前,讓我們提交代碼:

$ git add . $ git commit -m "Add base template and error template" $ git push復(fù)制代碼

提示 你可以在 GitHub 上查看本書示例程序的對應(yīng) commit:cfc08fa。

進(jìn)階提示

  • 本章介紹的自定義錯誤頁面是為了引出兩個重要的知識點,因此并沒有著重介紹錯誤頁面本身。這里只為 404 錯誤編寫了自定義錯誤頁面,對于另外兩個常見的錯誤 400 錯誤和 500 錯誤,你可以自己試著為它們編寫錯誤處理函數(shù)和對應(yīng)的模板。
  • 因為示例程序的語言和電影標(biāo)題使用了英文,所以電影網(wǎng)站的搜索鏈接使用了 IMDb,對于中文,你可以使用豆瓣電影或時光網(wǎng)。以豆瓣電影為例,它的搜索鏈接為 movie.douban.com/subject_sea…,對應(yīng)的 href 屬性即 https://movie.douban.com/subject_search?search_text={{ movie.title }}。
  • 因為基模板會被所有其他頁面模板繼承,如果你在基模板中使用了某個變量,那么這個變量也需要使用模板上下文處理函數(shù)注入到模板里。
  • 本書主頁 & 相關(guān)資源索引:http://helloflask.com/tutorial。

總結(jié)

以上是生活随笔為你收集整理的《Flask 入门教程》第 6 章:模板优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。