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、基本流程
- 创建自定义模板标签
- 创建标签页
- 在base模板中引用
4、步骤
4.1 创建自定义模板标签
- 在应用(我的是blog应用)下创建,
templatetags
python软件包。 - 在
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 条评论
暂无评论