开发记录-阅读排行/评论排行

1、说明

这两个功能的实现是跟最新文章、分类、标签云等实现是相同的,采用的是自定义模板标签。

之前也没有记录过,趁这次机会记录下原理,以评论排行为例。

2、模型关系

以下面的为例

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    text = models.TextField()

3、基本流程

  1. 创建自定义模板标签
  2. 创建标签页
  3. 在base模板中引用

4、步骤

4.1 创建自定义模板标签

  • 在应用(我的是blog应用)下创建,templatetagspython软件包。
  • templatetags创建blog_tags.py文件,用于存放自定义模板标签代码。
  • 编写模板标签代码

  • 导入 template 模块

  • 实例化了一个 template.Library
  • 将函数 comment_rank 装饰为 register.inclusion_tag。这样就可以在模板中使用语法 {% comment_rank %} 调用这个函数了

标签代码:

from django import template
from django.db.models.aggregates import Count
from ..models import Post

register = template.Library()


@register.inclusion_tag('……/_comment_rank.html', takes_context=True)
def comment_rank(context, num=6):
     # 使用 annotate 计算每篇文章的评论数量,并添加为一个新字段 comment_count
    annotated_posts = Post.objects.annotate(comment_count=Count('comment'))

    # 使用 filter 过滤掉评论数量小于等于 0 的文章
    posts_with_comments = annotated_posts.filter(comment_count__gt=0)

    # 使用 order_by 获取评论数量前5的文章
    top_posts_with_comments = posts_with_comments.order_by('-comment_count')[:num]

    return {
        'post_list': top_posts_with_comments,
    }

4.2 创建模板标签页

<div class="widget widget-recent-posts">
  <h3 class="widget-title">评论排行榜</h3>
  <ul>
    {% for post in post_list %}
      <li>
        <a href="{{ post.get_absolute_url }}">{{ post.title }}({{ post.comment_count }})</a>
      </li>
    {% empty %}
      暂无文章!
    {% endfor %}
  </ul>
</div>
  • post_list就是comment_rank函数的返回。

4.3 base模板引用

……
{% load blog_extras %}
<!DOCTYPE html>
<html>
<head>
  ……
</head>

<body>
……
    <div class="container">
        <div class="row">
                <aside class="col-md-4">
                    {% comment_rank %}
                </aside>
         </div>
    </div>
……
</body>
</html>
  • 导入自定义模板标签:{% load blog_extras %},同加载静态文件一样
  • 使用自己写的自定义模板标签:{% comment_rank %},comment_rank 就是函数名。

5、register.inclusion_tag装饰器

在Django中,@register.inclusion_tag 是一个装饰器,用于创建自定义的模板标签,也称为 inclusion tags。inclusion tags 允许您在模板中插入重复的 HTML 片段,并将其封装在一个单独的模板中。这样可以在多个页面上重复使用相同的代码块,使得模板更加灵活和可重用。

在模板中调用这个自定义标签时,Django 将调用相应的 Python 函数,并将函数返回的上下文(context)与指定的模板进行渲染,然后将渲染结果插入到模板中。

当在模板中使用 {% my_custom_tag %} 标签时,Django 将调用 my_custom_tag 函数,并将返回的 HTML 片段插入到模板中,从而实现代码重用和模板灵活性。

请注意,使用 inclusion tags 时,您可以向自定义标签传递参数,以便在 Python 函数中处理不同的数据和逻辑,并在模板中根据需要进行渲染。有关更多关于 inclusion tags 的信息,请参阅 Django 官方文档:https://docs.djangoproject.com/en/stable/howto/custom-template- tags/#inclusion-tags

在Django中,@register.inclusion_tag 装饰器提供了一个可选参数 takes_context。这个参数用于控制自定义 inclusion tag 在模板中获取上下文(context)的方式。

默认情况下,takes_context 参数为 False,这意味着自定义 inclusion tag 只接受从模板传递的参数,而不会获取整个模板的上下文。

如果将 takes_context 参数设置为 True,自定义 inclusion tag 将会获取整个模板的上下文,而不仅仅是从模板传递的参数。

在自定义 inclusion tag 的 Python 函数中,如果 takes_context 参数为 True,则第一个参数必须命名为 context,用于接收模板上下文。如果 takes_context 参数为 False,则第一个参数可以命名为任意值。

'……/_comment_rank.html':模板标签页面,该函数的返回会传递到这里面

ps:来自chatgpt的解释


发表评论

评论列表,共 0 条评论

    暂无评论