如果知道每篇文章的浏览量
,管理员就可以了解到访问者对文章的喜好程度
,方便后续推出相关内容文章,同时对热门博客
的统计和阅读趋势图
打好基础。针对阅读统计
功能,前前后后我一共想到了三种方法,各种方法都有利有弊。
方法一:采用该模型字段计数
1.修改Post模型read_num
2.优化:设置cookie
判断是否用户多次点击response.set_cookie()
优点:简单
缺点:1.后台编辑博客可能影响数据
2.功能单一
,无法统计某一天的阅读数量
具体实现:
1.在Post模型类中直接定义一个read_num
的字段名
read_num = models.IntegerField(default=0)
2.然后可以通过对Post属性read_num
的操作来实现阅读计数+1
的逻辑处理
post.read_num += 1
post.save()
方法二:设计功能独立的ReadNum模型数据表
1.添加read_num
字段
2.增加post
外键
3.利用ReadNum.objects.filter(post=post)来过滤当前的文章计数
对象
4.优化:设置cookie判断是否用户多次点击response.set_cookie()
具体实现:
1.在blog/models.py文件中,与定义Post类似,定义一个ReadNum
的模型类
class ReadNum(models.Model):
read_num = models.IntegerField(u'阅读次数', default=0)
post = models.OneToOneField(Post, on_delete=models.CASCADE)
def __str__(self):
return self.read_num
class Meta:
verbose_name = '阅读'
verbose_name_plural = '阅读'
2.通过objects的filter方法
来过滤当前博客是否有阅读的记录,如不存在记录,则创建新的readnum计数对象
if ReadNum.objects.filter(post=post).count():
# 存在记录
readnum = ReadNum.objects.get(post=post)
else:
# 不存在记录
readnum = ReadNum(post=post)
readnum.read_num += 1
readnum.save()
3.阅读计数表
就算是建好了,还需要将阅读数量加到后台的每篇文章中,在Post模型类中添加该方法
def get_read_num(self):
try:
return self.readnum.read_num
except exceptions.ObjectDoesNotExist:
return 0
4.将get_read_num
方法添加到admin.py的list_display中
list_display = ('id', 'title', 'created_time', 'modified_time', 'category', 'author', 'get_read_num')
方法三:设计功能独立的计数应用read_statistics
1.导入两个模块GenericForeignKey
和ContentType
(非常重要)
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
2.新增ReadNum
模型表,创建read_num
这个字段名
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class ReadNum(models.Model):
"""
单篇博客计数的模型类
继承model.Model模型类
"""
read_num = models.IntegerField(u'阅读计数', default=0)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
# 使用contenttypes模型类来找出关联blog
content_object = GenericForeignKey('content_type', 'object_id')
class Meta:
verbose_name = '阅读计数'
verbose_name_plural = '阅读计数'
ordering = ['-read_num']
3.新增utils.py
作为工具包,加入阅读计数+1的逻辑处理
ct = ContentType.objects.get_for_model(obj)
key = "%s_%s_read" % (ct.model, obj.pk)
if not request.COOKIES.get(key):
'''
if ReadNum.objects.filter(content_type=ct, object_id=obj.pk).count():
# 存在记录
readnum = ReadNum.objects.get(content_type=ct, object_id=obj.pk)
else:
# 不存在记录
readnum = ReadNum(content_type=ct, object_id=obj.pk)
'''
readnum, created = ReadNum.objects.get_or_create(content_type=ct, object_id=obj.pk)
# 计数+1
readnum.read_num += 1
readnum.save()
5.解决后台计数对象没创建时的解决办法,新增一个ReadNumExpandMethod类
class ReadNumExpandMethod(object):
"""
计数扩展类,此方法放在admin的list_display中
继承object模型类
"""
def get_read_num(self):
ct = ContentType.objects.get_for_model(self)
# 此处的一个异常处理,用来捕获没有计数对象的情况
# 例如在admin后台中,没有计数值会显示为‘-’
try:
readnum = ReadNum.objects.get(content_type=ct, object_id=self.pk)
return readnum.read_num
# 对象不存在就返回0
except exceptions.ObjectDoesNotExist:
return 0
然后让blog/models中的Post模型类继承ReadNumExpandMethod类中的方法
class Post(models.Model, ReadNumExpandMethod):
...
6.将方法加入到blog/amdin.py
中的list_display
中
list_display = ('id', 'title', 'created_time', 'modified_time', 'category', 'author', 'get_read_num')
以上就是文章阅读计数的简单方法,这三种方法的共同缺点就是功能单一
,无法统计某一天的阅读数量,下一篇内容将对阅读计数内容进行优化,增加日期的阅读量查询