上篇写了几个简单的阅读计数
,其缺点都是无法统计某一天的阅读数量,也就无法根据日期来对热门博客
进行排行。所以最好还是重建一个带有日期字段名
的模型表,这就可以根据日期条件
来筛选博客的阅读次数了,比较方便统计。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
到这里就基本就是阅读计数优化
的全部内容。