统计评论的数量

一篇文章的火爆程度,主要通过浏览量和评论数量直观看出来的

阅读量之前实现过了,准备来实现评论数量的统计

评论模块是有一个单独的评论表,只需要给出合适的条件,过滤出所有的数据,再求和即可

from django.contrib.contenttypes.model import ContentType
from comment.models import Comment
# ...

# ...
def blog_detail(request, pk):
    """详情页"""
    # 博客模型的实例
    blog = Blog.objects.all()
    # 通过上方实例,获取其内容类型对象
    content_type = ContentType.objects.get_for_model(blog)
    # 内容类型对象作为条件,去评论表中查找
    comment_count = Comment.objects.filter(content_type=content_type,             object_id=blog.id).count()

#....
# 通过上面的代码就可以获取到当前文章的评论总数了

获取数据之后,传入模板层,就可以显示出来了

自定义模板标签

降低耦合,代码更加独立和使用更加方便

在app内创建templatetags包

创建py文件

load标签加载该文件

上方简单的实现了评论数量的统计

blog_detail在这个视图函数中,原本是用来处理博客详情页的

但是,因为阅读数量,评论数量,评论表单,评论列表等需要加入到详情页中

这个视图函数越来越冗余,功能特点不明显

不是处理博客详情页的内容吗,怎么什么都在处理了

为了降低耦合,可以使用自定义模板标签

简单示例

以上方的评论数量统计为例

首先在评论模块的文件夹下创建一个包templatetags

文件夹下含有__init__.py的文件夹下叫做

templatetags 这个文件夹名字不要打错了,不然使用不了

templatetags包下,新建py文件comment_tags.py

comment_tags.py

# 导入django的template包
from django import template

register = template.Library()

# 新建一个函数
@register.simple_tag
def get_comment_count():
    return 'test'

Library类:

用于注册模板标记和过滤器的类。
已编译的过滤器和模板标签函数存储在过滤器和标签属性中。
过滤器、simple_tag和inclusion_tag方法为将可调用项注册为标记提供了一种方便的方法。

想要展示出来

首先在模板文件顶部载入

{% load comment_tags %}

合适位置输出

<p>
    {% get_comment_count %}
</p>

效果

UTOOLS1588239235078.png

好的,现在我们就已经完成了一个自定义模板标签了

可以看到,文件名,就是在模板文件载入时填写的

需要什么数据,就调用你自己写的哪个函数即可

有参数

现在的目标就是获取相关数据,并返回即可

blog = Blog.objects.all()
# 通过上方实例,获取其内容类型对象
content_type = ContentType.objects.get_for_model(blog)
# 内容类型对象作为条件,去评论表中查找
comment_count = Comment.objects.filter(content_type=content_type,             object_id=blog.id).count()

上面是我们刚刚写的,获取数据步骤

blog这个实例,肯定是需要传到模板层的,而我们刚好需要这个实例对象来获取内容类型

所以,现在的流程就是,blog传入到模板层后,我们再去拿过来,进行相应的处理,在通过自定义模板标签返回数据

再说明下,两种方法的不同之处

之前:

所有的逻辑都放在视图函数中处理,举例:如果内容页和列表页都需要获取评论数量,那么无论怎么操作,都需要去改动 内容页视图函数列表页视图函数,视图函数处理完所有数据,再统一给模板层渲染

现在:

内容页视图函数,列表页视图函数,各自处理自己的核心逻辑,传入到模板层后,在自定义模板标签内处理其他的逻辑(例如:评论数量,阅读数量等等),处理完之后再渲染到模板

完善模板标签模块

# 导入django的template包
from django import template
from django.contrib.contenttypes.model import ContentType
from ..models import Comment


register = template.Library()

# 新建一个函数
@register.simple_tag
def get_comment_count(obj):
    # 这里的参数就是,模板中传过来的实例对象
    # 通过obj获取,内容类型
    content_type = ContentType.objects.get_for_model(obj)
    # 内容类型作为条件,取出数据
    return Comment.objects.filter(content_type=content_type, object_id=obj.id).count()

在模板文件中调用,需要传入参数(一个实例对象,本例中,就是博客文章对象)

<li>{% get_comment_count blog %}</li>

get_comment_count是方法,在后面空一格,再输入的就是参数

UTOOLS1588240199797.png

在内容页可以使用,在列表页也是直接调用即可

{% for blog in page_of_blogs.object_list %}
<div class="article">
    <a href="{% url 'blog_detail' blog.id %}">
        <h2>{{ blog.title }}</h2>
    </a>
    <!--truncate 缩短-->
    <p>{{ blog.content|striptags|truncatechars:120 }}</p>
    <p class="blog-info">
        <span class="glyphicon glyphicon-th-list"></span><a
                                                            href="{% url 'blog_list' blog.class_name_id %}">{{ blog.class_name }}</a>
        <span class="glyphicon glyphicon-calendar"></span>{{ blog.created_time|date:"Y-m-d G:n:s" }}
        <span class="glyphicon glyphicon-eye-open"></span>{{ blog.get_read_num }}
        <!-- 评论数量 -->
        <span class="glyphicon glyphicon-envelope"></span>{% get_comment_count blog %}
    </p>
</div>
{% empty %}
<p>当前暂无文章</p>
{% endfor %}

UTOOLS1588240651901.png

查询集

对于统计评论数量而言,最后获取到的就是一个数字,一个特定数据

当我们,获取到的是一个查询集的时候怎么办呢? 也很简单

以显示评论列表为例

新增get_comment_list函数

# 导入django的template包
from django import template
from django.contrib.contenttypes.model import ContentType
from ..models import Comment


register = template.Library()

# 新建一个函数
@register.simple_tag
def get_comment_count(obj):
    # 这里的参数就是,模板中传过来的实例对象
    # 通过obj获取,内容类型
    content_type = ContentType.objects.get_for_model(obj)
    # 内容类型作为条件,取出数据
    return Comment.objects.filter(content_type=content_type, object_id=obj.id).count()


@register.simple_tag
def get_comment_list(obj):
    """获取当前博文下的评论列表"""
    content_type = ContentType.objects.get_for_model(obj)
    # 内容类型作为条件,获得查询集
    return Comment.objects.filter(content_type=content_type, object_id=obj.id, parent=None)

模板文件

{% for comment in comment_list %}
<div class="comment">
    ...
</div>
{% endfor %}

原来是上面这样的

首先我们先获取查询集,并使用as关键字,设置他的别名

{% get_comment_list blog as comment_list %}
{% get_comment_list blog as comment_list %}
{% for comment in comment_list %}
<div class="comment">
    ...
</div>
{% endfor %}

好了没事了,现在这样就结束了

虽然不能对我们的方法直接进行遍历,但是我们可以设置别名,遍历这个别名即可

通过自定义模板标签,将一切与博客文章处理逻辑无关的步骤,全部丢出去

这样子就干净多了

UTOOLS1588241273392.png

Last modification:April 30th, 2020 at 06:10 pm