當前位置:
首頁 > 最新 > 手把手教你用Django搭建博客(五)

手把手教你用Django搭建博客(五)

作者:楊學光

博客:http://zmrenwu.com/

9、博客文章詳情頁

首頁展示的是所有文章的列表,當用戶看到感興趣的文章時,他點擊文章的標題或者繼續閱讀的按鈕,應該跳轉到文章的詳情頁面來閱讀文章的詳細內容。現在讓我們來開發博客的詳情頁面,有了前面的基礎,開發流程都是一樣的了:首先配置 URL,即把相關的 URL 和視圖函數綁定在一起,然後實現視圖函數,編寫模板並讓視圖函數渲染模板。

設計文章詳情頁的 URL

回顧一下我們首頁視圖的 URL,在 blogurls.py 文件里,我們寫了:

首頁視圖匹配的 URL 去掉域名後其實就是一個空的字元串。對文章詳情視圖而言,每篇文章對應著不同的 URL。比如我們可以把文章詳情頁面對應的視圖設計成這個樣子:當用戶訪問 /post/1/ 時,顯示的是第一篇文章的內容,而當用戶訪問 /post/2/ 時,顯示的是第二篇文章的內容,這裡數字代表了第幾篇文章,也就是資料庫中 Post 記錄的 id 值。下面依照這個規則來綁定 URL 和視圖:

Django 使用正則表達式來匹配用戶訪問的網址。這裡整個正則表達式剛好匹配我們上面定義的 URL 規則。這條正則表達式的含義是,以 post/ 開頭,後跟一個至少一位數的數字,並且以 / 符號結尾,如 post/1/、 post/255/ 等都是符合規則的,[0-9]+ 表示一位或者多位數。此外這裡表示命名捕獲組,其作用是從用戶訪問的 URL 里把括弧內匹配的字元串捕獲並作為關鍵字參數傳給其對應的視圖函數。比如當用戶訪問 post/255/ 時(注意 Django 並不關心域名,而只關心去掉域名後的相對 URL),被括起來的部分匹配 255,那麼這個 255 會在調用視圖函數 detail 時被傳遞進去,實際上視圖函數的調用就是這個樣子:。我們這裡必須從 URL 里捕獲文章的 id,因為只有這樣我們才能知道用戶訪問的究竟是哪篇文章。

可能上述的正則表達式你有點難以理解,關於正則表達式的部分並非 Django 相關的內容,而是 Python 的內容。Django 只是在這裡使用了 Python 處理正則表達式的 re 模塊。因此如果想更好地理解 Python 中正則表達式的相關知識,請自行查看 Python 官方文檔中 re 模塊的文檔。

此外我們通過告訴 Django 這個 urls.py 模塊是屬於 blog 應用的,這種技術叫做視圖函數命名空間。我們看到 blogurls.py 目前有兩個視圖函數,並且通過 name 屬性給這些視圖函數取了個別名,分別是 index、detail。但是一個複雜的 Django 項目可能不止這些視圖函數,例如一些第三方應用中也可能有叫 index、detail 的視圖函數,那麼怎麼把它們區分開來,防止衝突呢?方法就是通過 app_name 來指定命名空間,命名空間具體如何使用將在下面介紹。如果你忘了在 blogurls.py 中添加這一句,接下來你可能會得到一個 NoMatchReversed 異常。

為了方便地生成上述的 URL,我們在類里定義一個方法,注意本身是一個 Python 類,在類中我們是可以定義任何方法的。

注意到 URL 配置中的,我們設定的在這裡派上了用場。看到這個函數,它的第一個參數的值是,意思是 blog 應用下的的函數,由於我們在上面通過告訴了 Django 這個 URL 模塊是屬於 blog 應用的,因此 Django 能夠順利地找到 blog 應用下 name 為 detail 的視圖函數,於是函數會去解析這個視圖函數對應的 URL,我們這裡 detail 對應的規則就是這個正則表達式,而正則表達式部分會被後面傳入的參數替換,所以,如果的 id(或者 pk,這裡 pk 和 id 是等價的) 是 255 的話,那麼函數返回的就是 /post/255/ ,這樣 Post 自己就生成了自己的 URL。

編寫 detail 視圖函數

接下來就是實現我們的視圖函數了:

視圖函數很簡單,它根據我們從 URL 捕獲的文章 id(也就是 pk,這裡 pk 和 id 是等價的)獲取資料庫中文章 id 為該值的記錄,然後傳遞給模板。注意這裡我們用到了從 django.shortcuts 模塊導入的方法,其作用就是當傳入的 pk 對應的 Post 在資料庫存在時,就返回對應的,如果不存在,就給用戶返回一個 404 錯誤,表明用戶請求的文章不存在。

編寫詳情頁模板

接下來就是書寫模板文件,從下載的博客模板(如果你還沒有下載,請點擊這裡下載)中把 single.html 拷貝到 templateslog 目錄下(和 index.html 在同一級目錄),然後改名為 detail.html。此時你的目錄結構應該像這個樣子:

在 index 頁面博客文章列表的標題繼續閱讀按鈕寫上超鏈接跳轉的鏈接,即文章對應的詳情頁的 URL,讓用戶點擊後可以跳轉到 detail 頁面:

這裡我們修改兩個地方,第一個是文章標題處:

我們把 a 標籤的 href 屬性的值改成了 {{ post.getabsoluteurl }}。回顧一下模板變數的用法,由於 getabsoluteurl 這個方法(我們定義在 Post 類中的)返回的是對應的 URL,因此這裡 {{ post.getabsoluteurl }} 最終會被替換成該自身的 URL。

同樣,第二處修改的是繼續閱讀按鈕的鏈接:

模板繼承

我們看到 index.html 文件和 detail.html 文件除了 main 標籤包裹的部分不同外,其它地方都是相同的,我們可以把相同的部分抽取出來,放到 base.html 里。首先在 templates 目錄下新建一個 base.html 文件,這時候你的項目目錄應該變成了這個樣子:

把 index.html 的內容全部拷貝到 base.html 文件里,然後刪掉 main 標籤包裹的內容,替換成如下的內容。

這裡 block 也是一個模板標籤,其作用是佔位。比如這裡的 {% block main %}{% endblock main %} 是一個佔位框,main 是我們給這個 block 取的名字。下面我們會看到 block 標籤的作用。同時我們也在 aside 標籤下加了一個 {% block toc %}{% endblock toc %} 佔位框,因為 detail.html 中 aside 標籤下會多一個目錄欄。當 {% block toc %}{% endblock toc %} 中沒有任何內容時,{% block toc %}{% endblock toc %} 在模板中不會顯示。但當其中有內容是,模板就會顯示 block 中的內容。

在 index.html 里,我們在文件最頂部使用繼承 base.html,這樣就把 base.html 里的代碼繼承了過來,另外在 {% block main %}{% endblock main %} 包裹的地方填上 index 頁面應該顯示的內容:

這樣 base.html 里的代碼加上 {% block main %}{% endblock main %} 里的代碼就和最開始 index.html 里的代碼一樣了。這就是模板繼承的作用,公共部分的代碼放在 base.html 里,而其它頁面不同的部分通過替換 {% block main %}{% endblock main %} 佔位標籤里的內容即可。

如果你對這種模板繼承還是有點糊塗,可以把這種繼承和 Python 中類的繼承類比。base.html 就是父類,index.html 就是子類。index.html 繼承了 base.html 中的全部內容,同時它自身還有一些內容,這些內容就通過 「覆寫」 {% block main %}{% endblock main %}(把 block 看做是父類的屬性)的內容添加即可。

detail 頁面處理起來就簡單了,同樣繼承 base.html ,在 {% block main %}{% endblock main %} 里填充 detail.html 頁面應該顯示的內容,以及在 {% block toc %}{% endblock toc %} 中填寫 base.html 中沒有的目錄部分的內容。不過目前的目錄只是佔位數據,我們在以後會實現如何從文章中自動摘取目錄。

修改 article 標籤下的一些內容,讓其顯示文章的實際數據:

再次從首頁點擊一篇文章的標題或者繼續閱讀按鈕跳轉到詳情頁面,可以看到預期效果了!

總結

本章節的代碼位於:Step8: blog detail view(https://github.com/zmrenwu/django-blog-tutorial/tree/Step8_blog-detail-view)

如果遇到問題,請通過下面的方式尋求幫助。

更多Django 教程,請訪問追夢人物的博客(http://zmrenwu.com/)

10、支持 Markdown 語法和代碼高亮

為了讓博客文章具有良好的排版,顯示更加豐富的格式,我們使用 Markdown 語法來書寫我們的博文。Markdown 是一種 HTML 文本標記語言,只要遵循它約定的語法格式,Markdown 的渲染器就能夠把我們寫的文章轉換為標準的 HTML 文檔,從而讓我們的文章呈現更加豐富的格式,例如標題、列表、代碼塊等等 HTML 元素。由於 Markdown 語法簡單直觀,不用超過 5 分鐘就可以掌握常用的標記語法,因此大家青睞使用 Markdown 書寫 HTML 文檔。下面讓我們的博客也支持使用 Markdown 書寫。

安裝 Python Markdown

將 Markdown 格式的文本渲染成標準的 HTML 文檔是一個複雜的工作,好在已有好心人幫我們完成了這些工作,我們直接使用即可。首先安裝 Markdown,這是一個 Python 第三方庫,激活虛擬環境,然後使用命令安裝即可。

在 detail 視圖中渲染 Markdown

將 Markdown 格式的文本渲染成 HTML 文本非常簡單,只需調用這個庫的方法即可。我們書寫的博客文章內容存在的屬性里,回到我們的詳情頁視圖函數,對的的值做一下渲染,把 Markdown 文本轉為 HTML 文本再傳遞給模板:

這樣我們在模板中展示 {{ post.body }} 的時候,就不再是原始的 Markdown 文本了,而是渲染過後的 HTML 文本。注意這裡我們給渲染函數傳遞了額外的參數,它是對 Markdown 語法的拓展,這裡我們使用了三個拓展,分別是 extra、codehilite、toc。extra 本身包含很多拓展,而 codehilite 是語法高亮拓展,這為我們後面的實現代碼高亮功能提供基礎,而 toc 則允許我們自動生成目錄(在以後會介紹)。

來測試一下效果,進入後台,這次我們發布一篇用 Markdown 語法寫的測試文章看看,你可以使用以下的 Markdown 測試代碼進行測試,也可以自己書寫你喜歡的 Markdown 文本。假設你是 Markdown 新手參考一下這些教程,一定學一下,保證你可以在 5 分鐘內掌握常用的語法格式,而以後對你寫作受用無窮。可謂充電五分鐘,通話 2 小時。以下是我學習中的一些參考資料:

Markdown——入門指南(http://www.jianshu.com/p/1e402922ee32/)

Markdown 語法說明 (簡體中文版)(http://www.appinn.com/markdown/)

markdown

列表項1

列表項2

列表項3`

這是一段引用

如果你發現無法顯示代碼塊,即代碼無法換行,請檢查代碼塊的語法是否書寫有誤。代碼塊的語法如上邊的測試文本中最後一段所示。

你可能想在文章中插入圖片,目前能做的且推薦做的是使用外鏈引入圖片。比如將圖片上傳到七牛雲這樣的雲存儲伺服器,然後通過 Markdown 的圖片語法將圖片引入。Markdown 引入圖片的語法為:。

safe 標籤

我們在發布的文章詳情頁沒有看到預期的效果,而是類似於一堆亂碼一樣的 HTML 標籤,這些標籤本應該在瀏覽器顯示它本身的格式,但是 Django 出於安全方面的考慮,任何的 HTML 代碼在 Django 的模板中都會被轉義(即顯示原始的 HTML 代碼,而不是經瀏覽器渲染後的格式)。為了解除轉義,只需在模板標籤使用過濾器即可,告訴 Django,這段文本是安全的,你什麼也不用做。在模板中找到展示博客文章主體的 {{ post.body }} 部分,為其加上 safe 過濾器,{{ post.body|safe }},大功告成,這下看到預期效果了。

safe 是 Django 模板系統中的過濾器(Filter),可以簡單地把它看成是一種函數,其作用是作用於模板變數,將模板變數的值變為經過濾器處理過後的值。例如這裡 {{ post.body|safe }},本來 {{ post.body }} 經模板系統渲染後應該顯示 body 本身的值,但是在後面加上 safe 過濾器後,渲染的值不再是body 本身的值,而是由 safe 函數處理後返回的值。過濾器的用法是在模板變數後加一個 | 管道符號,再加上過濾器的名稱。可以連續使用多個過濾器,例如 {{ var|filter1|filter2 }}。

代碼高亮

程序員寫博客免不了要插入一些代碼,Markdown 的語法使我們容易地書寫代碼塊,但是目前來說,顯示的代碼塊里的代碼沒有任何顏色,很不美觀,也難以閱讀,要是能夠像我們的編輯器里一樣讓代碼高亮就好了。雖然我們在渲染時使用了 codehilite 拓展,但這只是實現代碼高亮的第一步,還需要簡單的幾步才能達到我們的最終目的。

安裝 Pygments

首先我們需要安裝 Pygments,激活虛擬環境,運行:安裝即可。

搞定了,雖然我們除了安裝了一下 Pygments 什麼也沒做,但 Markdown 使用 Pygments 在後台為我們做了很多事。如果你打開博客詳情頁,找到一段代碼段,在瀏覽器查看這段代碼段的 HTML 源代碼,可以發現 Pygments 的工作原理是把代碼切分成一個個單詞,然後為這些單詞添加 css 樣式,不同的詞應用不同的樣式,這樣就實現了代碼顏色的區分,即高亮了語法。為此,還差最後一步,引入一個樣式文件來給這些被添加了樣式的單詞定義顏色。

引入樣式文件

在項目的 blogstaticlogcsshighlights 目錄下應該能看到很多 .css 樣式文件,這些文件是用來提供代碼高亮樣式的。選擇一個你喜歡的樣式文件,在 base.html 引入即可(別忘了使用 static 模板標籤)。比如我比較喜歡 github.css 的樣式,那麼引入這個文件:

這裡 + 號表示添加這行代碼。好了,看看效果,大功告成,終於可以愉快地貼代碼了。

注意:如果你按照教程中的方法做完後發現代碼依然沒有高亮,請依次檢查以下步驟:

確保在渲染文本時添加了拓展,詳情見上文。

確保安裝了 Pygments。

確保代碼塊的 Markdown 語法正確,特別是指明該代碼塊的語言類型,具體請參見上文中 Markdown 的語法示例。

在瀏覽器端代碼塊的源代碼,看代碼是否被 pre 標籤包裹,並且代碼的每一個單詞都被 span 標籤包裹,且有一個 class 屬性值。如果沒有,極有可能是前三步中某個地方出了問題。

確保用於代碼高亮的樣式文件被正確地引入,具體請參見上文中引入樣式文件的講解。

有些樣式文件可能對代碼高亮沒有作用,首先嘗試用 github.css 樣式文件做測試。

總結

本章節的代碼位於:Step9: markdown and code highlight supported(https://github.com/zmrenwu/django-blog-tutorial/tree/Step9_markdown-and-code-highlight-supported)

如果遇到問題,請通過下面的方式尋求幫助。

更多Django 教程,請訪問追夢人物的博客(http://zmrenwu.com/)

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 天善智能 的精彩文章:

手把手教你用Django搭建博客(三)

TAG:天善智能 |

您可能感興趣

手把手教你用Kaggle開啟機器學習之旅
手把手教你用Python庫Keras做預測
手把手教你用Cloud AutoML做毒蜘蛛分類器
手把手教你用Python創建簡單的神經網路
手把手教你用Python進行Web抓取
啥是佩琪?手把手教你用SolidWorks繪製小豬佩奇
手把手教你用Python進行回歸
手把手教你用Keras進行多標籤分類
教你用 Python和Keras 建立自己的 AlphaZero
教你用Python和Keras建立自己的AlphaZero
教你用SolidWorks繪製小豬佩奇
美國孩子的資源國內孩子照樣用!手把手教你用Raz kids在線閱讀網
Meta2教你用雙手「把玩」超跑
手把手教你用Python實現「坦克大戰」,(附詳細代碼!)
擁有自己第一個區塊鏈——手把手教你用python搭建
米家APP支持Siri:手把手教你用Siri控制米家智能設備
教你用Python解析HTML
教你用Keras和CNN建立模型識別神奇寶貝!
時尚博主Annabelle Fleur,教你用唯美浪漫的連衣裙,詮釋別樣風情
教你用iPhone備忘錄畫菠蘿