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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

Diango博客--17.统计各个分类和标签下的文章数

發(fā)布時(shí)間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Diango博客--17.统计各个分类和标签下的文章数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 0.思路引導(dǎo)
    • 1.Model 回顧
    • 2.數(shù)據(jù)庫(kù)數(shù)據(jù)聚合
    • 3.使用 Annotate
    • 4.在模板中引用新增的屬性

0.思路引導(dǎo)

在我們的博客側(cè)邊欄有分類列表和標(biāo)簽列表,顯示博客已有的全部文章分類。現(xiàn)在想在分類名和標(biāo)簽名后顯示該分類或者標(biāo)簽下有多少篇文章,該怎么做呢?最優(yōu)雅的方式就是使用 django 的 annotate 方法。

1.Model 回顧

回顧一下我們的 model 代碼,django 博客有一個(gè) Post 和 Category 模型,分別表示文章和分類:

文件位置:blog/models.py

class Post(models.Model):title = models.CharField('標(biāo)題', max_length=70)body = models.TextField('正文')category = models.ForeignKey(Category, verbose_name='分類', on_delete=models.CASCADE)# 其它屬性...def __str__(self):return self.titleclass Category(models.Model):name = models.CharField('分類名', max_length=100)

我們知道從數(shù)據(jù)庫(kù)取數(shù)據(jù)都是使用模型管理器 objects 的方法實(shí)現(xiàn)的。比如獲取全部分類是:Category.objects.all() ,假設(shè)有一個(gè)名為 test 的分類,那么獲取該分類的方法是:Category.objects.get(name=‘test’) 。

objects 除了 all、get 等方法外,還有很多操作數(shù)據(jù)庫(kù)的方法,而其中有一個(gè) annotate 方法,該方法可以幫我們實(shí)現(xiàn)本文所關(guān)注的統(tǒng)計(jì)分類下的文章數(shù)量的功能。

2.數(shù)據(jù)庫(kù)數(shù)據(jù)聚合

annotate 方法在底層調(diào)用了數(shù)據(jù)庫(kù)的數(shù)據(jù)聚合函數(shù),下面使用一個(gè)實(shí)際的數(shù)據(jù)庫(kù)表來(lái)幫助我們理解 annotate 方法的工作原理。

在 Post 模型中我們通過(guò) ForeignKey 把 Post 和 Category 關(guān)聯(lián)了起來(lái),這時(shí)候它們的數(shù)據(jù)庫(kù)表結(jié)構(gòu)就像下面這樣:

Post 表:
Category 表:


1)當(dāng) Django 要查詢某篇 post 對(duì)應(yīng)的分類時(shí),比如 post 1,首先查詢到它分類的 id 為 1,然后 Django 再去 Category 表找到 id 為 1 的那一行,這一行就是 post 1 對(duì)應(yīng)的分類。

2)反過(guò)來(lái),如果要查詢 category 1 對(duì)應(yīng)的全部文章呢?category 1 在 Category 表中對(duì)應(yīng)的 id 是 1,Django 就在 Post 表中搜索哪些行的 category_id 為 1,發(fā)現(xiàn)前 3 行都是,把這些行取出來(lái)就是 category 1 下的全部文章了。

3)同理,這里 annotate 做的事情就是把全部 Category 取出來(lái),然后去 Post 查詢每一個(gè) Category 對(duì)應(yīng)的文章,查詢完成后只需算一下每個(gè) category id 對(duì)應(yīng)有多少行記錄,這樣就可以統(tǒng)計(jì)出每個(gè) Category 下有多少篇文章了。

4)把這個(gè)統(tǒng)計(jì)數(shù)字保存到每一條 Category 的記錄就可以了(當(dāng)然并非保存到數(shù)據(jù)庫(kù),在 Django ORM 中是保存到 Category 的實(shí)例的屬性中,每個(gè)實(shí)例對(duì)應(yīng)一條記錄)。

3.使用 Annotate

以上是原理方面的分析,具體到 Django 中該如何用呢?在我們的博客中,獲取側(cè)邊欄的分類列表的方法寫(xiě)在模板標(biāo)簽 get_categories 里,因此我們修改一下這個(gè)函數(shù),具體代碼如下:

文件位置:blog/templatetags/blog_extras.py

from django.db.models.aggregates import Count from blog.models import Category@register.inclusion_tag('blog/inclusions/_categories.html', takes_context=True) def show_categories(context):category_list = Category.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)return {'category_list': category_list,}

1)這個(gè) Category.objects.annotate 方法和 Category.objects.all 有點(diǎn)類似,它會(huì)返回?cái)?shù)據(jù)庫(kù)中全部 Category 的記錄,但同時(shí)它還會(huì)做一些額外的事情,在這里我們希望它做的額外事情就是去統(tǒng)計(jì)返回的 Category 記錄的集合中每條記錄下的文章數(shù)。

2)代碼中的 Count 方法為我們做了這個(gè)事,它接收一個(gè)和 Categoty 相關(guān)聯(lián)的模型參數(shù)名(這里是 Post,通過(guò) ForeignKey 關(guān)聯(lián)的),然后它便會(huì)統(tǒng)計(jì) Category 記錄的集合中每條記錄下的與之關(guān)聯(lián)的 Post 記錄的行數(shù),也就是文章數(shù),最后把這個(gè)值保存到 num_posts 屬性中。

3)此外,我們還對(duì)結(jié)果集做了一個(gè)過(guò)濾,使用 filter 方法把 num_posts 的值小于 1 的分類過(guò)濾掉。因?yàn)?num_posts 的值小于 1 表示該分類下沒(méi)有文章,沒(méi)有文章的分類我們不希望它在頁(yè)面中顯示。

同理,tags 也可以做同樣的操作。

@register.inclusion_tag('blog/inclusions/_tags.html', takes_context=True) def show_tags(context):tag_list = Tag.objects.annotate(num_posts=Count('post')).filter(num_posts__gt=0)return {'tag_list': tag_list,}

4.在模板中引用新增的屬性

現(xiàn)在在 Category 和 Tag 列表中每一項(xiàng)都新增了一個(gè) num_posts 屬性記錄該 Category 下的文章數(shù)量,我們就可以在模板中引用這個(gè)屬性來(lái)顯示分類下的文章數(shù)量了。

文件位置:templates/blog/inclusions/_categories.html

<div class="widget widget-category"><h3 class="widget-title">分類</h3><ul>{% for category in category_list %}<li><a href="{% url 'blog:category' category.pk %}">{{ category.name }} <span class="post-count">({{ category.num_posts }})</span></a></li>{% empty %}暫無(wú)分類!{% endfor %}</ul> </div>

文件位置:templates/blog/inclusions/_tags.html

<div class="widget widget-tag-cloud"><h3 class="widget-title">標(biāo)簽云</h3><ul>{% for tag in tag_list %}<li><a href="{% url 'blog:tag' tag.pk %}">{{ tag.name }} <span class="post-count">({{ tag.num_posts }})</a></li>{% empty %}暫無(wú)標(biāo)簽!{% endfor %}</ul> </div>

也就是在模板中通過(guò)模板變量 {{ category.num_posts }}以及 {{ tag.num_posts }}顯示 num_posts 的值。

開(kāi)啟開(kāi)發(fā)服務(wù)器,可以看到分類名后正確地顯示了該分類下的文章數(shù)了,而沒(méi)有文章分類則不會(huì)在分類列表中出現(xiàn)。

效果展示如下:

總結(jié)

以上是生活随笔為你收集整理的Diango博客--17.统计各个分类和标签下的文章数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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