django annotate 分组统计

2023-02-18 11:15:22 浏览数 (1)

annotate 用法说明文档

  • http://doc.codingdict.com/django/ref/models/querysets.html#yiyi-860(基础)
  • http://doc.codingdict.com/django/topics/db/aggregation.html#yiyi-133(聚合)

使用提供的 查询表达式 Annotate 查询集中的每个对象。查询表达式可以是一个简单的值、模型(或关联模型)字段的一个引用或对查询集中的对象一个聚合函数(平均值、和等)。

annotate() 的每个参数都是一个 annotation,它将添加到返回的 QuerySet 中每个对象。

分组统计代码

代码语言:javascript复制
@register.inclusion_tag("likes_rank.html")
def likes_rank():
    """
    显示文章的点赞排行
    :return:
    """
    article_likes_rank = cache.get("article_likes_rank")
    if not article_likes_rank:
        # values 展示 article_id, article__title 字段,以 article_id 分组统计出现的次数 liks,再用 liks 倒排序
        article_likes_rank = ArticleLike.objects.values("article_id", "article__title").annotate(
            likes=Count("article_id")).order_by("-likes")[:5]
        print(article_likes_rank)
        cache.set("article_likes_rank", article_likes_rank, CACHE_TIMEOUT_12H)

    return {"article_likes_rank": article_likes_rank}

print(article_likes_rank) 结果

代码语言:javascript复制
<QuerySet [{'article_id': 62, 'article__title': 'python 和 django 相关学习文档', 'likes': 17}, {'article_id': 148, 'article__title': 'html toastr.js 悬浮通知', 'likes': 10}, {'article_id': 9, 'article__title': '创建博客网站准备的一些材料', 'likes': 8}, {'article_id': 118, 'article__title': 'django admin 实现 增加记录 和 修改记录 展现不同的表单', 'likes': 8}, {'article_id': 150, 'article__title': 'windows 任何应用在 运行 里直接打开', 'likes': 8}]>

ArticleLike Model

代码语言:javascript复制
class ArticleLike(models.Model):
    """
    文章点赞
    """
    article = models.ForeignKey(Article, verbose_name="所属文章", related_name="like_article_set",
                                on_delete=models.DO_NOTHING)
    user = models.ForeignKey(User, related_name="like_user_set", verbose_name="点赞用户", blank=True, null=True,
                             on_delete=models.DO_NOTHING)
    ip = models.GenericIPAddressField(verbose_name="点赞 IP")
    ip_location = models.CharField(verbose_name="IP 归属地", max_length=50, blank=True, null=True)
    time_create = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    time_update = models.DateTimeField(blank=True, null=True, auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "文章点赞"
        verbose_name_plural = "文章点赞列表"

    def __str__(self):
        return "%s %s" % (self.article, self.ip)

Article Model

代码语言:javascript复制
class Article(models.Model):
    """
    文章表
    """
    title = models.CharField(max_length=128, verbose_name="标题")
    content = RichTextUploadingField(verbose_name="内容", config_name='awesome_ckeditor')
    node = models.ForeignKey(Node, verbose_name="所属节点", related_name="nods_set", on_delete=models.DO_NOTHING)
    author = models.ForeignKey(User, related_name="author_set", verbose_name="作者", on_delete=models.DO_NOTHING)
    source = models.ForeignKey(Source, verbose_name="来源", blank=True, null=True, on_delete=models.DO_NOTHING)
    tags = models.ManyToManyField(Tag, verbose_name="标签", related_name="tags_set", blank=True)
    edit_number = models.IntegerField(default=0, verbose_name="编辑次数")
    time_create = models.DateTimeField(auto_now_add=True, verbose_name="发表时间")
    time_update = models.DateTimeField(blank=True, null=True, auto_now=True, verbose_name="更新时间")
    is_show = models.BooleanField(default=True, verbose_name="显示文章")
    is_comment = models.BooleanField(default=True, verbose_name="显示临时评论")
    is_top = models.BooleanField(default=False, verbose_name="置顶文章")

    class Meta:
        verbose_name = "文章"
        verbose_name_plural = "文章列表"

    # 获取后台文本编辑器图文内容中图片url地址
    def get_contentimg_url(self):
        temp = Article.objects.filter(pk=str(self.id)).values('content')  # values获取Article数据表中的content字段内容
        html = pq(temp[0]['content'])  # pq方法获取编辑器html内容
        # print(html, "n", "----")
        img_path = pq(html)('img').attr('src')  # 截取html内容中的路径
        # print("pic", img_path)
        return img_path  # 返回第一张图片路径

    def get_absolute_url(self):
        return reverse('blog:detail', kwargs={
            "pk": self.id,
        })

    def get_full_url(self):
        site = get_current_site().domain
        url = "https://{site}{path}".format(site=site, path=self.get_absolute_url())
        return url

    def save(self, *args, **kwargs):
        self.edit_number  = 1  # 每次保存加 1
        super(Article, self).save(*args, **kwargs)

    def __str__(self):
        if len(self.title) > 15:
            title_short = self.title[:12]   '...'
        else:
            title_short = self.title
        return "%s %s %s" % (self.id, self.author, title_short)

对应模板

代码语言:javascript复制
<div class="blog-sidebar-widget blog-bor">
    <h2 class="blog-text-center blog-title"><span>LIKES RANK</span></h2>
    <ul class="am-list">
        {% for article in article_likes_rank %}
            <li>
                <a href="{% url "blog:detail" article.article_id %}"
                   title="{{ article.article__title }}"
                   onclick="MtaH5.clickStat('1',{'1':'{{ article.article__title }}'})">{{ article.article__title| capfirst }}
                    <small>
                            <span class="am-icon-thumbs-o-up am-article-meta"
                                  style="color: #10D07A"> {{ article.likes }}
                            </span>
                    </small>
                </a>
            </li>
        {% empty %}
            暂无文章
        {% endfor %}
    </ul>
</div>

0 人点赞