蒋振飞的博客 - 网站搭建 (第08天) 阅读计数优化   
正在加载蒋振飞的博客...
V3.0
蒋振飞的博客

网站搭建 (第08天) 阅读计数优化

发布时间: 2018年07月27日 发布人: 蒋振飞 热度: 714 ℃ 评论数: 0

一、前言

上篇写了几个简单的阅读计数功能实现,其缺点都是无法统计某一天的阅读数量,也就无法根据日期来对热门博客进行排行。所以最好还是重建一个带有日期字段名的模型表,这就可以根据日期条件来筛选博客的阅读次数了,比较方便统计。

二、新建ReadDetail模型类

ReadNum继续保留,再建一个ReadDetail模型类。

from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class ReadDetail(models.Model):
    """
        根据日期计数的模型类
        继承model.Model模型类
    """
    read_num = models.IntegerField(default=0)
    date = models.DateField(default=timezone.now)

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    class Meta:
        verbose_name = '阅读记录'
        verbose_name_plural = '阅读记录'
        ordering = ['-date']

三、阅读逻辑处理

做到这一步,就应该对read_num的数值进行计数了。这个计数还不能每次点击进入read_num都会增加,否则这个数值就没有意义了,应当是只要是同一个用户在段时间重复进入多次,数值只会变化+1,而不是每次进入都会增加。因为这个状态是不涉及重要信息的,所以直接用cookie来进行状态保持的记录就可以了,通过request.COOKIES.get(key)来获取key的值,如果获取不到,则说明用户还未点击这篇博客,可以对read_num进行+1逻辑处理。同时当没有ReadNum或ReadDetail的实例对象时,就要创建,这里可以使用get_or_create方法,返回两个参数。

from django.contrib.contenttypes.models import ContentType

def read_statistics_once_read(request, obj):
    """
        作用:阅读+1的处理逻辑功能
        request:请求对象
        obj:post实例对象
    """
    ct = ContentType.objects.get_for_model(obj)
    key = "%s_%s_read" % (ct.model, obj.pk)
    if not request.COOKIES.get(key):
        # 如果使用get_or_create就能省略上面一大段,可以简化
        readnum, created = ReadNum.objects.get_or_create(content_type=ct, object_id=obj.pk)

        # 总阅读计数+1
        readnum.read_num += 1
        readnum.save()

        # 当天阅读数+1
        date = timezone.now().date()
        readdetail, created = ReadDetail.objects.get_or_create(content_type=ct, object_id=obj.pk, date=date)
        readdetail.read_num += 1
        readdetail.save()
    return key

上面是对每篇博客阅读+1的处理,可以看到该函数返回了一个key,通过对key赋值可以实现状态保持。下面代码还有上一篇和下一篇博客的逻辑部分,这里也顺便贴出来了。

def detail(request, pk):
    """
        作用:显示当前选择文章内容
        request:请求对象
        pk:每篇文章的pk值
    """
    # 接收了一个pk值,这个值是在url中传递的主键,利用该主键可以找到文章的对象
    # get_object_or_404的用法是(模型名,get方法)
    post = get_object_or_404(Post, pk=pk)
    post_all_list = Post.objects.all()

    # read_statistics_once_read是在read_statistics应用中的方法,表示计数+1
    read_cookie_key = read_statistics_once_read(request, post)

    # 在django中不能使用>=或<=,所以django自定义了__gt和__lt
    # 目的:得出创建时间比当前博客创建时间较晚的所有博客列表的最后一篇博客,也就是当前博客的上一篇
    # 因为博客是按照创建时间的先后来排序的:即先创建的靠后,那么上一篇博客创建时间晚于当前博客
    previous_post = Post.objects.filter(created_time__gt=post.created_time).last()

    # 目的:得出创建时间比当前博客创建时间较早的所有博客列表的第一篇博客,也就是当前博客的下一篇
    # 因为博客是按照创建时间的先后来排序的:即先创建的靠后,那么上一篇博客创建时间早于当前博客
    next_post = Post.objects.filter(created_time__lt=post.created_time).first()

    context = ({'article': post.body, 'title': post.title,
                'author': post.author, 'created_time': post.created_time,
                'category': post.category, 'previous_post': previous_post,
                'next_post': next_post, 'read_num': post.get_read_num,
                'user': request.user, 'post_id': post.id, 'post': post,
               })
    response = render(request, 'blog/detail.html', context)
    # 第一个参数是键,键值,和过期时间
    response.set_cookie(read_cookie_key, 'true')  # 阅读cookie标记
    return response

到这里就基本就是阅读计数优化的全部内容。

打赏 蒋振飞

取消

感谢您的支持,我会继续努力的!

扫码支持
一分也是爱     一块不嫌多

点击 支付宝 或 微信 打赏蒋振飞

打开支付宝扫一扫,即可进行扫码打赏哦

评论列表