国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Django 學(xué)習(xí)小組:博客開(kāi)發(fā)實(shí)戰(zhàn)第四周——標(biāo)簽云與文章歸檔

RichardXG / 2491人閱讀

摘要:本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn)博客開(kāi)發(fā)入門教程。表示降序排列,默認(rèn)是升序排列。學(xué)習(xí)小組簡(jiǎn)介學(xué)習(xí)小組是一個(gè)促進(jìn)新手互相學(xué)習(xí)互相幫助的組織。我們會(huì)將每周的詳細(xì)開(kāi)發(fā)文檔和代碼通過(guò)郵件列表發(fā)出。

本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門教程。

通過(guò)前四周的時(shí)間我們開(kāi)發(fā)了一個(gè)簡(jiǎn)單的個(gè)人 Blog,教程地址:

第一周:Django 學(xué)習(xí)小組:博客開(kāi)發(fā)實(shí)戰(zhàn)第一周教程 —— 編寫博客的 Model 和首頁(yè)面

第二周:Django 學(xué)習(xí)小組:博客開(kāi)發(fā)實(shí)戰(zhàn)第二周教程 —— 博客詳情頁(yè)面和分類頁(yè)面

第三周:Django 學(xué)習(xí)小組:博客開(kāi)發(fā)實(shí)戰(zhàn)第三周教程 —— 文章列表分頁(yè)和代碼語(yǔ)法高亮

第四周:Django 學(xué)習(xí)小組:基于類的通用視圖詳解(一)

本周我們將實(shí)現(xiàn) blog 的標(biāo)簽云和文章按時(shí)間自動(dòng)歸檔功能。

提示:在閱讀教程的過(guò)程中,如有任何問(wèn)題請(qǐng)?jiān)L問(wèn)我們項(xiàng)目的 GithHub 或評(píng)論留言以獲取幫助,本教程的相關(guān)代碼已全部上傳在 Github。如果你對(duì)我們的教程或者項(xiàng)目有任何改進(jìn)建議,請(qǐng)您隨時(shí)告知我們。更多交流請(qǐng)加入我們的郵件列表?django_study@groups.163.com 和關(guān)注我們?cè)?GithHub 上的項(xiàng)目。

本文首發(fā)于編程派微信公眾號(hào):編程派(微信號(hào):codingpy)是一個(gè)專注Python編程的公眾號(hào),每天更新有關(guān)Python的國(guó)外教程和優(yōu)質(zhì)書籍等精選干貨,歡迎關(guān)注。

標(biāo)簽云與文章歸檔在 Blog 中也是比較常見(jiàn)的功能,標(biāo)簽云顯示每篇文章的標(biāo)簽,文章歸檔顯示某個(gè)時(shí)間段內(nèi)的發(fā)表的文章,就像這樣:

下面我們來(lái)為我們的 Blog 添加類似的功能,最終會(huì)為我們的個(gè)人 blog 實(shí)現(xiàn)類似于下面這樣的效果:

標(biāo)簽云

標(biāo)簽有點(diǎn)類似于分類,只是分類由于是多對(duì)一的關(guān)系(我們規(guī)定一篇文章只有一個(gè)分類,而一個(gè)分類下可以有多篇文章),因此在我們的 model 中使用的是 ForeignKeyField 。我們規(guī)定一篇文章可以打多個(gè)標(biāo)簽,并且一個(gè)標(biāo)簽下可能會(huì)有多篇文章,是多對(duì)多的關(guān)系,因此需要使用到 ManyToManyField,其它的實(shí)現(xiàn)則和 Category(分類)十分相似。首先修改我們的 model 文件,為標(biāo)簽(tag)新建一個(gè)數(shù)據(jù)庫(kù) model,并在文章(Article)中指定它們多對(duì)多的關(guān)系:

blog/models.py

class Article(models.Model):
    """
    文章model中添加tag關(guān)系
    """
    ...
    category = models.ForeignKey("Category", verbose_name="分類", null=True, on_delete=models.SET_NULL)
    tags = models.ManyToManyField("Tag", verbose_name="標(biāo)簽集合", blank=True)
    ...

class Tag(models.Model):
    """
    tag(標(biāo)簽)對(duì)應(yīng)的數(shù)據(jù)庫(kù)model
    """
    name = models.CharField("標(biāo)簽名", max_length=20)
    created_time = models.DateTimeField("創(chuàng)建時(shí)間", auto_now_add=True)
    last_modified_time = models.DateTimeField("修改時(shí)間", auto_now=True)

    def __str__(self):
        return self.name

類似于 CategoryView,點(diǎn)擊某個(gè)標(biāo)簽可以獲取該標(biāo)簽下的全部文章,對(duì)應(yīng)的視圖函數(shù):

blog/views.py

class TagView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        """
        根據(jù)指定的標(biāo)簽獲取該標(biāo)簽下的全部文章
        """
        article_list = Article.objects.filter(tags=self.kwargs["tag_id"], status="p")
        for article in article_list:
            article.body = markdown2.markdown(article.body, extras=["fenced-code-blocks"], )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs["tag_list"] = Tag.objects.all().order_by("name")
        return super(TagView, self).get_context_data(**kwargs)

模板文件稍微小變了一下,添加了顯示標(biāo)簽的區(qū)域(由于模板文件代碼比較多,具體請(qǐng)參見(jiàn) github 項(xiàng)目中 blog/templates/blog/index.html 下的模板文件)。

同時(shí) IndexView 里也別忘了把 tag 加到 context 中,以便在模板中渲染顯示:

blog/views.py

class IndexView(ListView):
    ...
    def get_context_data(self, **kwargs):
        kwargs["category_list"] = Category.objects.all().order_by("name")
        kwargs["date_archive"] = Article.objects.archive()
        # tag_list 加入 context 里:
        kwargs["tag_list"] = Tag.objects.all().order_by("name")
        return super(IndexView, self).get_context_data(**kwargs)

配置好 url :

blog/urls.py

url(r"^tag/(?Pd+)$", views.TagView.as_view(), name="tag"),
文章歸檔

文章歸檔我們實(shí)現(xiàn)下面的需求:

在首頁(yè)會(huì)顯示已發(fā)表文章對(duì)應(yīng)的年份列表,點(diǎn)擊相應(yīng)年份會(huì)展開(kāi)該年年份下對(duì)應(yīng)的月份列表,像這樣:

實(shí)現(xiàn)思路大概如下:Django 的 ORM 為我們提供一個(gè) datetimes 函數(shù) ( datetimes 函數(shù)用法 ),可以選出數(shù)據(jù)庫(kù)中某個(gè) model 對(duì)應(yīng)的全部已去重的時(shí)間,并且可以任意指定精度。例如,我們想選出全部文章對(duì)應(yīng)的發(fā)表時(shí)間,精確到月份:

date_list = Article.objects.datetimes("created_time", "month", order="DESC")
# created_time 是 Article model 中文章發(fā)表時(shí)間,對(duì)應(yīng)的是 DatetimeField( datetimes 函數(shù)也只能用于DatetimeField ),month 即精確到月,精確到年指定為 year,天則指定為 day 即可。DESC 表示降序排列,默認(rèn)是升序排列。

# 例如有如下的一系列發(fā)表時(shí)間:
2009-01-02
2009-01-05
2009-02-02
2010-05-04
2011-06-04
2011-06-07
# 則得到的結(jié)果將是精確到月份去重后的結(jié)果:
2009-01
2009-02
2010-05
2011-06
# 這正是我們期望的結(jié)果

以這個(gè)函數(shù)為基礎(chǔ),接下來(lái)我們使用 Django 的一點(diǎn)高級(jí)技巧(自定義 Manager)來(lái)實(shí)現(xiàn)完整的功能。

什么是 Manager(管理器)?Manager 可以看成是一個(gè) model 的管理器,很多從數(shù)據(jù)庫(kù)中獲取 model 數(shù)據(jù)的方法都定義在這個(gè)類里,比如我們經(jīng)常用的 Article.objects.all()Article.objects.filter(),這里的 objects 就是一個(gè) Manager 的實(shí)例,django 為每一個(gè) model 都指定了一個(gè)默認(rèn)的 Manager ,名字叫做 objects。但現(xiàn)在 Manager 中一些默認(rèn)的方法無(wú)法滿足我們的需求了,因此我們拓展一下 Manager 的功能,為其添加一個(gè)歸檔(archive)方法,拓展一個(gè)類的最佳方式就是繼承它:

blog/models.py

class ArticleManage(models.Manager):
    """
    繼承自默認(rèn)的 Manager ,為其添加一個(gè)自定義的 archive 方法
    """
    def archive(self):
        date_list = Article.objects.datetimes("created_time", "month", order="DESC")
        # 獲取到降序排列的精確到月份且已去重的文章發(fā)表時(shí)間列表
        # 并把列表轉(zhuǎn)為一個(gè)字典,字典的鍵為年份,值為該年份下對(duì)應(yīng)的月份列表
        date_dict = defaultdict(list)
        for d in date_list:
            date_dict[d.year].append(d.month)
        # 模板不支持defaultdict,因此我們把它轉(zhuǎn)換成一個(gè)二級(jí)列表,由于字典轉(zhuǎn)換后無(wú)序,因此重新降序排序
        return sorted(date_dict.items(), reverse=True)

自定義了 Manger 后需要在 model 中顯示地指定它:

blog/models.py

class Article(models.model):
    ...
    # 仍然使用默認(rèn)的 objects 作為 manager 的名字
    objects = ArticleManager()
    ...

現(xiàn)在在視圖函數(shù)中就可以調(diào)用了:

blog/views.py

class IndexView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        article_list = Article.objects.filter(status="p")
        for article in article_list:
            article.body = markdown2.markdown(article.body, extras=["fenced-code-blocks"], )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs["category_list"] = Category.objects.all().order_by("name")
        # 調(diào)用 archive 方法,把獲取的時(shí)間列表插入到 context 上下文中以便在模板中渲染
        kwargs["date_archive"] = Article.objects.archive()
        kwargs["tag_list"] = Tag.objects.all().order_by("name")
        return super(IndexView, self).get_context_data(**kwargs)
    
# 現(xiàn)在我們的時(shí)間歸檔列表格式是這樣的:
[(2012,[09,02,01]),(2011,[12,10,06,01]),...]
# 因此在模板中我們可以這樣循環(huán)以實(shí)現(xiàn)我們預(yù)初的設(shè)計(jì):
{% for year,month_list in date_archive %}
    {{year}} 年
    {% for month in month_list %}
        {{month}}月
# 使用一些 bootstrap 的組件即可實(shí)現(xiàn)上圖一樣的效果了。

完整的模板請(qǐng)參考 github 的 blog/templates/blog/index.html 模板文件。

最后一件事就是實(shí)現(xiàn)點(diǎn)擊相應(yīng)的時(shí)間后顯示該時(shí)間下的全部已發(fā)表文章列表了,實(shí)現(xiàn)思路即通過(guò) url 把對(duì)應(yīng)的年份和月份傳給視圖函數(shù),視圖函數(shù)通過(guò)年份和月份過(guò)濾所需文章,然后再模板渲染即可,實(shí)現(xiàn)和 category 與 tag 的方式十分類似:

blog/views.py

class ArchiveView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        # 接收從url傳遞的year和month參數(shù),轉(zhuǎn)為int類型
        year = int(self.kwargs["year"])
        month = int(self.kwargs["month"])
        # 按照year和month過(guò)濾文章
        article_list = Article.objects.filter(created_time__year=year, created_time__month=month)
        for article in article_list:
            article.body = markdown2.markdown(article.body, extras=["fenced-code-blocks"], )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs["tag_list"] = Tag.objects.all().order_by("name")
        return super(ArchiveView, self).get_context_data(**kwargs)

url:

blog/urls.py

url(r"^archive/(?Pd+)/(?Pd+)$", views.ArchiveView.as_view(), name="archive"),

templates:

blog/index.html

# 詳細(xì)請(qǐng)參閱 github 上的模板文件完整代碼
{% for year,month_list in date_archive %}
    {{year}} 年
    {% for month in month_list %}
        

{{ month }} 月

接下來(lái)做什么?

我們的個(gè)人 blog 基本已經(jīng)成型了!首頁(yè)展示文章列表、標(biāo)簽云、文章歸檔、分類,文章 markdown 語(yǔ)法標(biāo)記,代碼高亮顯示,利用 django 后臺(tái),我們可以使用它來(lái)寫 blog 文章了,你可以先嘗試著找一個(gè)部署教程把 blog 部署上線。當(dāng)然我們接下來(lái)也會(huì)出如何部署的教程,敬請(qǐng)期待。下一周我們將實(shí)現(xiàn)評(píng)論功能,允許用戶對(duì)我們發(fā)表的文章進(jìn)行評(píng)論。為了學(xué)習(xí),我們將不使用第三方 app,而是重新發(fā)明輪子。

Django學(xué)習(xí)小組簡(jiǎn)介

django學(xué)習(xí)小組是一個(gè)促進(jìn) django 新手互相學(xué)習(xí)、互相幫助的組織。

小組在一邊學(xué)習(xí) django 的同時(shí)將一起完成幾個(gè)項(xiàng)目,包括:

一個(gè)簡(jiǎn)單的 django 博客,用于發(fā)布小組每周的學(xué)習(xí)和開(kāi)發(fā)文檔;

django中國(guó)社區(qū),為國(guó)內(nèi)的 django 開(kāi)發(fā)者們提供一個(gè)長(zhǎng)期維護(hù)的 django 社區(qū);

上面所說(shuō)的這個(gè)社區(qū)類似于 segmentfault 和 stackoverflow ,但更加專注(只專注于 django 開(kāi)發(fā)的問(wèn)題)。

更多的信息請(qǐng)關(guān)注我們的?github 組織,本教程項(xiàng)目的相關(guān)源代碼也已上傳到 github 上。

同時(shí),你也可以加入我們的郵件列表?django_study@groups.163.com?,隨時(shí)關(guān)注我們的動(dòng)態(tài)。我們會(huì)將每周的詳細(xì)開(kāi)發(fā)文檔和代碼通過(guò)郵件列表發(fā)出。

如有任何建議,歡迎提 Issue,歡迎 fork,pr,當(dāng)然也別忘了 star 哦!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/38019.html

相關(guān)文章

  • Django 學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)五周教程 —— 實(shí)現(xiàn)評(píng)論功能

    摘要:本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn)博客開(kāi)發(fā)入門教程。我們的評(píng)論表單放在中,評(píng)論成功后返回到原始提交頁(yè)面。學(xué)習(xí)小組簡(jiǎn)介學(xué)習(xí)小組是一個(gè)促進(jìn)新手互相學(xué)習(xí)互相幫助的組織。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門教程。 通過(guò)前四周的時(shí)間我們開(kāi)發(fā)了一個(gè)簡(jiǎn)單的個(gè)人 Blog,前幾期教程地址: 第一周:Django 學(xué)習(xí)小組:博客開(kāi)發(fā)實(shí)戰(zhàn)第一周教程 —— 編寫博客的 Mode...

    CoderStudy 評(píng)論0 收藏0
  • Django 學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)五周教程 —— 實(shí)現(xiàn)評(píng)論功能

    摘要:本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn)博客開(kāi)發(fā)入門教程。我們的評(píng)論表單放在中,評(píng)論成功后返回到原始提交頁(yè)面。學(xué)習(xí)小組簡(jiǎn)介學(xué)習(xí)小組是一個(gè)促進(jìn)新手互相學(xué)習(xí)互相幫助的組織。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門教程。 通過(guò)前四周的時(shí)間我們開(kāi)發(fā)了一個(gè)簡(jiǎn)單的個(gè)人 Blog,前幾期教程地址: 第一周:Django 學(xué)習(xí)小組:博客開(kāi)發(fā)實(shí)戰(zhàn)第一周教程 —— 編寫博客的 Mode...

    kumfo 評(píng)論0 收藏0
  • Django 學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)二周教程 —— 實(shí)現(xiàn)博客詳情頁(yè)面和分類頁(yè)面

    摘要:本節(jié)接上周的文檔學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)第一周教程編寫博客的首頁(yè)面,我們繼續(xù)給博客添加功能,以及改善前面不合理的部分。返回該視圖要顯示的對(duì)象。目前小組正在完成第一個(gè)項(xiàng)目,本文即是該項(xiàng)目第二周的相關(guān)文檔。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門教程。 上周我們完成了博客的 Model 部分,以及 Blog 的首頁(yè)視圖 IndexView。 本節(jié)接上周的文檔 Djan...

    ingood 評(píng)論0 收藏0
  • Django 學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)三周教程——文章列表分頁(yè)和代碼語(yǔ)法高亮

    摘要:本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn)博客開(kāi)發(fā)入門教程。當(dāng)分頁(yè)較多時(shí),總是顯示當(dāng)前頁(yè)及其前幾頁(yè)和后幾頁(yè)的頁(yè)碼教程中使用的是兩頁(yè),其他頁(yè)碼用省略號(hào)代替。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門教程。 摘要:前兩期教程我們實(shí)現(xiàn)了博客的 Model 部分,以及 Blog 的首頁(yè)視圖 IndexView,詳情頁(yè)面 DetailView,以及分類頁(yè)面 CategoryVi...

    Luosunce 評(píng)論0 收藏0
  • Django 學(xué)習(xí)小組博客開(kāi)發(fā)實(shí)戰(zhàn)一周教程 —— 編寫博客的 Model 與主頁(yè)面

    摘要:學(xué)習(xí)小組是由我發(fā)起的一個(gè)促進(jìn)新手互相學(xué)習(xí)互相幫助的組織。當(dāng)然如果你不喜歡英文,可以看我們的中文翻譯版本入門教程中文翻譯版。如果模板文件中有如下代碼那么渲染時(shí)就會(huì)循環(huán)渲染篇文章,并且也會(huì)被存儲(chǔ)在數(shù)據(jù)庫(kù)中文章的標(biāo)題取代。 本教程內(nèi)容已過(guò)時(shí),更新版教程請(qǐng)?jiān)L問(wèn): django 博客開(kāi)發(fā)入門教程。 本節(jié)是 Django Blog 項(xiàng)目的開(kāi)篇,是?Django 學(xué)習(xí)小組的集體學(xué)習(xí)成果。Django...

    陳江龍 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<