如果知道每篇文章的浏览量,管理员就可以了解到访问者对文章的喜好程度,方便后续推出相关内容文章,同时对热门博客的统计和阅读趋势图打好基础。针对阅读统计功能,前前后后我一共想到了三种方法,各种方法都有利有弊。
采用该模型字段计数
1.修改Post模型read_num
2.优化:设置cookie判断是否用户多次点击response.set_cookie()
优点:简单 缺点:1.后台编辑博客可能影响数据 2.功能单一,无法统计某一天的阅读数量3.具体实现:
在Post模型类中直接定义一个read_num的字段名
read_num = models.IntegerField(default=0)
然后可以通过对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()
具体实现:
在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 = '阅读'
通过objects的filter方法来过滤当前博客是否有阅读的记录,如不存在记录,则创建新的readnum计数对象
if ReadNum.objects.filter(post=post).count(): # 存在记录 readnum = ReadNum.objects.get(post=post)else: # 不存在记录 readnum = ReadNum(post=post)readnum.read_num += 1readnum.save()
阅读计数表就算是建好了,还需要将阅读数量加到后台的每篇文章中,在Post模型类中添加该方法
def get_read_num(self): try: return self.readnum.read_num except exceptions.ObjectDoesNotExist: return 0
将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 GenericForeignKeyfrom django.contrib.contenttypes.models import ContentType
2.新增ReadNum模型表,创建read_num这个字段名
from django.db import modelsfrom django.contrib.contenttypes.fields import GenericForeignKeyfrom django.contrib.contenttypes.models import ContentTypeclass 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()
4.解决后台计数对象没创建时的解决办法,新增一个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): ...
5.将方法加入到blog/amdin.py中的list_display中
list_display = ('id', 'title', 'created_time', 'modified_time', 'category', 'author', 'get_read_num')
以上就是文章阅读计数的简单方法,这三种方法的共同缺点就是功能单一,无法统计某一天的阅读数量,下一篇内容将对阅读计数内容进行优化,增加日期的阅读量查询