Django Blog 統(tǒng)計某個分類下有多少篇文章的優(yōu)雅實現(xiàn)方法

假設(shè)我們有如下的 Model :

class Article(models.Model):
    title = models.CharField('標題', max_length=200)
    body = models.TextField('正文')
    created_time = models.DateTimeField('創(chuàng)建時間', auto_now_add=True)
    
    author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者', on_delete=models.CASCADE)
    category = models.ForeignKey('Category', verbose_name='分類', on_delete=models.CASCADE)
    tags = models.ManyToManyField('Tag', verbose_name='標簽集合', blank=True)

    def __str__(self):
        return self.title

class Category(models.Model):
    name = models.CharField('分類名', max_length=30)

    def __str__(self):
        return self.name

class Tag(models.Model):
    name = models.CharField('標簽名', max_length=30)

    def __str__(self):
        return self.name

可以看到 Article 與 Author,Category 是外鍵關(guān)聯(lián)的,而和 Tag 多對多的關(guān)系。有時候我們有這樣的需求:在模板中顯示全部的 category,author,tag,同時還要對應(yīng)顯示與其關(guān)聯(lián)的 Article 數(shù)量,例如:

  • 分類一 ( 10 )
  • 分類二 ( 15 )
  • 分類三 ( 8 )

由于 Article 和 Category 外鍵關(guān)聯(lián)的,在模板中我們可以使用 {{ category_instance.article_set.count }} 取得 category_instance 這一特定分類下關(guān)聯(lián)的全部 Article 數(shù)量,但是缺點也很明顯,無法在模板標簽中傳遞參數(shù),count 方法將返回全部關(guān)聯(lián)的文章數(shù)目。有時我們想要更加精細化一點的顯示,比如統(tǒng)計某個分類下全部 Article 發(fā)表時間在某個時間點后的文章,而如果該分類對應(yīng)的文章數(shù)為 0 ,我們在模板中則不顯示該分類。看上去挺復(fù)雜的邏輯,Django 的 annote 方法一句話可以解決我們的問題。

使用:

from django.db.models.aggregates import Count

category_list = Category.objects.filter(article__created_time_gt=(2015,1,1)).annotate(
    num_articles=Count('article')).filter(num_articles__gt=0)

annote 的功能是根據(jù)某個規(guī)則給 queryset 中的每一個元素(例如我們這里的是 category)添加一個屬性。queryset 是從數(shù)據(jù)庫中查詢到的一組數(shù)據(jù)的集合,Django 將其封裝在 QuerySet 對象里。

這句話的意思的,首先對 Category 做篩選(filter),即篩選出其對應(yīng)的全部文章發(fā)表時間大于 2015年1月1日的 category記錄(article__created_time_gt=(2015,1,1)) ,然后為篩選出來的每一個條 category 記錄添加了一個屬性:num_articles(num_articles=Count('article'))),Count 方法為我們計算了每一條 catogory 下對應(yīng)的 article 數(shù)量,最后再對這組記錄篩選出對應(yīng)文章數(shù)量大于 0 的記錄,即滿足了我們上述要求。同理可以對 Author,Tag 做類似篩選。

值得注意的是第一個 filter 和 annotate 的順序不能亂,否則可能無法得到我們預(yù)期的結(jié)果。

相關(guān)文檔位于:QuerySet Method referenceAggregation

靈活使用這些方法將使我們復(fù)雜的查詢需求代碼變得更加高效和簡短。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容