12. 分類與歸檔

本教程內(nèi)容已過時,更新版教程請訪問: Django 博客開發(fā)入門教程彤枢。

這是 Django 博客教程的第 12 篇,在閱讀此篇教程以前贷洲,請確保你已閱讀 Django 博客教程的前 11 篇:
1. Django 博客教程:前言
2. 搭建開發(fā)環(huán)境
3. 建立我們的 django 博客應(yīng)用
4. 創(chuàng)建 django 博客的數(shù)據(jù)庫模型
5. 讓 django 完成翻譯——遷移數(shù)據(jù)庫模型
6. django 博客首頁視圖
7. 真正的 django 博客首頁視圖
8. 在 django admin 后臺發(fā)布我們的文章
9. 博客文章詳情頁
10. 支持 markdown 語法和代碼高亮
11. 頁面?zhèn)冗厵?/a>

側(cè)邊欄已經(jīng)正確地顯示了最新文章列表、歸檔晋柱、分類等信息∮殴梗現(xiàn)在來完善歸檔和分類功能,當(dāng)用戶點(diǎn)擊歸檔下的某個日期或者分類下的某個分類時趣斤,跳轉(zhuǎn)到文章列表頁面俩块,顯示該日期或者分類下的全部文章。

思路和主頁文章列表的顯示是一樣的浓领,回顧一下主頁的實(shí)現(xiàn)代碼:

blog/views.py

def index(request):
    post_list = Post.objects.all()
    return render(request, 'blog/index.html', context={'post_list': post_list})

主頁視圖函數(shù)中我們通過 Post.objects.all() 獲取全部文章玉凯,而在我們的歸檔和分類視圖中,我們不再使用 all 獲取全部文章联贩,而是使用 filter 來根據(jù)條件過濾漫仆。先來看歸檔視圖:

blog/views.py

def archives(request, year, month):
    post_list = Post.objects.filter(created_time__year=year, created_time__month=month)
    return render(request, 'blog/index.html', context={'post_list': post_list})

這里我們使用了模型管理器(objects)的 filter 函數(shù)來過濾文章,由于是按照日期歸檔泪幌,因此這里根據(jù)文章發(fā)表的年和月來過濾盲厌,具體來說,就是根據(jù) created_time 的 year 和 month 屬性過濾祸泪,篩選出文章發(fā)表在對應(yīng)的 year 年 和 month 月的文章吗浩。注意這里 created_time 是 Python 的 Date 對象,其有一個 year 和 month 屬性没隘,我們在上一節(jié)的模板中使用過這個屬性懂扼。Python 中實(shí)例調(diào)用屬性的方法通常是 created_time.year,但是由于這里作為函數(shù)的參數(shù)列表右蒲,所以 django 要求我們把點(diǎn)替換成了兩個斜杠阀湿,即 created_time__year。此外由于歸檔的顯示模板和 index 是一樣的(都是顯示文章列表)瑰妄,因此我們直接渲染了index 模板陷嘴。

然后配置好 url:

blog/urls.py

from django.conf.urls import url

from . import views

app_name = 'blog'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^post/(?P<pk>[0-9]+)/$', views.detail, name='detail'),
    + url(r'^archives/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/$', views.archives, name='archives'),
]

這個 url 的正則表達(dá)式和 detail 對應(yīng)的 url 是類似的,這在之前我們講過间坐。兩個括號括起來的地方是兩個命名組參數(shù)灾挨,django 會從用戶訪問的 URL 中自動提取這兩個參數(shù)的值,然后傳遞給 archives 視圖函數(shù)眶诈。例如如果用戶訪問 /archives/2017/3/涨醋,那么 archives 視圖函數(shù)的實(shí)際調(diào)用為:archives(request, year=2017, month=3)

在模板找到歸檔列表部分的代碼,修改鏈接的 href 屬性:

templates/base.html

{% for date in date_list %}
<li>
  <a href="{% url 'blog:archives' date.year date.month %}">
    {{ date.year }} 年 {{ date.month }} 月
  </a>
</li>
{% endfor %}

這里 URL 模板標(biāo)簽的作用是解析視圖函數(shù) blog:archives 對應(yīng)的 url 格式逝撬,并把 url 格式中的年和月替換成 date.year浴骂,date.month 的值。

測試一下宪潮,點(diǎn)擊側(cè)邊欄歸檔的日期溯警,跳轉(zhuǎn)到歸檔頁面趣苏,發(fā)現(xiàn)報了個錯誤,提示沒有安裝 pytz梯轻,進(jìn)入虛擬環(huán)境食磕,使用 pip install pytz 安裝一下。

重啟一下開發(fā)服務(wù)器喳挑,再次測試彬伦,發(fā)現(xiàn)可以顯示歸檔下的文章列表了。

同樣的寫好分類頁面的視圖函數(shù):

blog/views.py

import markdown

from django.shortcuts import render, get_object_or_404

# 引入 Category 類
from .models import Post, Category

def category(request, pk):
    cate = get_object_or_404(Category, pk=pk)
    post_list = Post.objects.filter(category=cate)
    return render(request, 'blog/index.html', context={'post_list': post_list})

這里我們首先根據(jù)傳入的 pk 值(也就是被訪問的分類的 id 值)從數(shù)據(jù)庫中獲取到這個分類伊诵。get_object_or_404 函數(shù)和 detail 視圖中一樣单绑,其作用是如果用戶訪問的分類不存在,則返回一個 404 錯誤頁面以提示用戶訪問的資源不存在曹宴。然后我們通過 filter 函數(shù)過濾出了該分類下的全部文章搂橙。

url 配置:

blog/urls.py

from django.conf.urls import url

from . import views

app_name = 'blog'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^post/(?P<pk>[0-9]+)/$', views.detail, name='detail'),
    url(r'^archives/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/$', views.archives, name='archives'),
    + url(r'^category/(?P<pk>[0-9]+)/$', views.category, name='category'),
]

這個分類頁面對應(yīng)的 url 模式和文章詳情頁面對應(yīng)的 url 模式十分類似,在此就不贅述了笛坦。

修改相應(yīng)模板:

templates/base.html

{% for category in category_list %}
<li>
  <a href="{% url 'blog:category' category.pk %}">{{ category.name }}</a>
</li>
{% endfor %}

同樣区转,url 模板標(biāo)簽的用法和寫歸檔頁面時的用法是一樣的。現(xiàn)在嘗試點(diǎn)擊相應(yīng)的鏈接版扩,就可以跳轉(zhuǎn)到歸檔或者分類頁面了废离。

  • 序言:七十年代末,一起剝皮案震驚了整個濱河市礁芦,隨后出現(xiàn)的幾起案子厅缺,更是在濱河造成了極大的恐慌,老刑警劉巖宴偿,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诀豁,居然都是意外死亡窄刘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門舷胜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娩践,“玉大人,你說我怎么就攤上這事烹骨》牛” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵沮焕,是天一觀的道長吨岭。 經(jīng)常有香客問我,道長峦树,這世上最難降的妖魔是什么辣辫? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任旦事,我火速辦了婚禮,結(jié)果婚禮上急灭,老公的妹妹穿的比我還像新娘姐浮。我一直安慰自己,他們只是感情好葬馋,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布卖鲤。 她就那樣靜靜地躺著,像睡著了一般畴嘶。 火紅的嫁衣襯著肌膚如雪蛋逾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天掠廓,我揣著相機(jī)與錄音换怖,去河邊找鬼。 笑死蟀瞧,一個胖子當(dāng)著我的面吹牛沉颂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悦污,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼铸屉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了切端?” 一聲冷哼從身側(cè)響起彻坛,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎踏枣,沒想到半個月后昌屉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茵瀑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年间驮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片马昨。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡竞帽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸿捧,到底是詐尸還是另有隱情屹篓,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布匙奴,位于F島的核電站堆巧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜恳邀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一懦冰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谣沸,春花似錦刷钢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赋除,卻和暖如春阱缓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背举农。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工荆针, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人颁糟。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓航背,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棱貌。 傳聞我的和親對象是個殘疾皇子玖媚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容