美文网首页
博客阅读数的统计三部曲【二】-阅读计数的分离

博客阅读数的统计三部曲【二】-阅读计数的分离

作者: yhxt | 来源:发表于2018-03-08 15:28 被阅读0次

博客阅读数的统计三部曲【一】-3种方式中讲到的3种方式,其模型都是在blog应用下models.py里面写的,这样耦合性太强,不利于以后给其他应用的拓展
这节讲的是将阅读计数的功能单独创建出一个app应用,打包发后便于其他项目的拓展使用

app应用的分离

Github源码地址:请点这里

image.png

1.此方法是将阅读计数功能分离出来,独立作为一个app引用,便于打包在线安装供其他项目中的使用

其中使用的功能方法详见Django官方文档“The contenttypes framework”(内容类型框架)

具体页面链接地址:Django官网文档

image.png
image.png

2.首先使用命令新建独立应用

python manage.py startapp read_statistics

接下来将read_statistics应用添加到settings.py的apps里面,如下图:

image.png

3.创建read_statistics应用下的models.py模型

具体参照Django官方文档: https://docs.djangoproject.com/en/2.0/ref/contrib/contenttypes/

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


class ReadNum(models.Model):
    read_num=models.IntegerField(default=0,verbose_name='阅读数')
    content_type = models.ForeignKey(ContentType, on_delete=models.DO_NOTHING)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    class Meta:
        verbose_name='阅读数'
        verbose_name_plural=verbose_name

4.同步更新数据库操作

python manage.py makemigrations

python manage.py migrate

5.配置read_statistics应用下的admin.py

image.png
from django.contrib import admin
from .models import ReadNum

class ReadNumAdmin(admin.ModelAdmin):
    list_display=('id','read_num','content_object')

admin.site.register(ReadNum,ReadNumAdmin)

添加完成后Django登录管理界面

image.png image.png

6.下面在blog应用下的models.py模型里面添加获取阅读数的方法get_read_num()

注意:添加这个方法是为了在Django管理界面的blog应用下,将get_read_num添加到list_display展示列表,从而可以在博客页面直接看到该篇文章所对应的阅读数

记得引用
from django.db.models.fields import exceptions
from django.contrib.contenttypes.models import ContentType
from read_statistics.models import ReadNum

image.png
from django.db import models
from django.db.models.fields import exceptions
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from ckeditor_uploader.fields import RichTextUploadingField

from read_statistics.models import ReadNum

class Blog(models.Model):
    title=models.CharField(max_length=50,verbose_name=u'标题')
    blog_type=models.ForeignKey(Blog_type,on_delete=models.DO_NOTHING)
    content=RichTextUploadingField()
    author=models.ForeignKey(User,on_delete=models.DO_NOTHING,verbose_name='作者')
    created_time=models.DateTimeField(auto_now_add=True,verbose_name=u'创建时间')
    last_update_time=models.DateTimeField(auto_now=True,verbose_name=u'修改时间')
    is_delete=models.BooleanField(default=False,verbose_name=u'是否删除')

    # 添加方法,添加的get_read_num方法,用于在admin管理后台的blog页面显示阅读数。即在admin.py的                                                                                        BlogAdmin类的list_display添加read_num
    def get_read_num(self):
        # 返回该篇文章的阅读数,此处如果该文章还没有阅读数,会有个异常,该异常是的默认阅读数不是0,而是-
        try:
            ct=ContentType.objects.get_for_model(Blog)
            readnum=ReadNum.objects.get(content_type=ct,object_id=self.pk)
            return readnum.read_num
        except exceptions.ObjectDoesNotExist:
            return 0
        
    class Meta:
        ordering=['-created_time']
        verbose_name='博客'
        verbose_name_plural=verbose_name

    def __str__(self):
        return self.title

7.再将上面get_read_num()方法添加到blog应用下面的admin.py的list_display列表

image.png

完成后,打开Django管理页面的博客,便可以看到每篇文章get_read_num的阅读数,如下图:

image.png

8.在bolg应用下的views.py,处理用于前台页面阅读数展示的逻辑关系

image.png
from django.contrib.contenttypes.models import ContentType
from read_statistics.models import ReadNum

def blog_detail(request,blog_pk):
    """博客详情页"""
    blog=get_object_or_404(Blog,pk=blog_pk) # 根据传入blog_pk的ID来找到具体对应博客文章

    # 获取cookie:根据获取cookie的key值'blog_%s_readed' % blog_pk,判断是否存在,不存在则阅读数                                                                                                                                +1
    if not request.COOKIES.get('blog_%s_read' % blog_pk):
        ct=ContentType.objects.get_for_model(Blog)

        if ReadNum.objects.filter(content_type=ct,object_id=blog.pk).count():
            # 记录存在,则查询并阅读数+1,保存
            readnum=ReadNum.objects.get(content_type=ct,object_id=blog.pk)
        else:
            # 对应记录不存在,则创建并阅读数+1,保存(这样就会在阅读数管理页面点击后保存对应文章以及阅读数)
            readnum=ReadNum(content_type=ct,object_id=blog.pk)
        readnum.read_num += 1    #点击该篇文章,阅读数自增1
        readnum.save()  

    pre_blog=Blog.objects.filter(id__gt=blog.id).last() # 博客的上一篇文章
    next_blog=Blog.objects.filter(id__lt=blog.id).first()   # 博客的下一篇文章
    response=render(request,'blog/blog_detail.html',{'blog':blog,'pre_blog':pre_blog,'next_blog':next_blog})    #响应
    
    # 设置cookie,打开过这篇文章即写入cookie,key是'blog_%s_readed' % blog_pk,value是'true'
    response.set_cookie('blog_%s_read' % blog_pk,'true')
    return response

9.最后在html页面,使用get_read_num方法获取阅读数的数据

image.png

相关文章

网友评论

      本文标题:博客阅读数的统计三部曲【二】-阅读计数的分离

      本文链接:https://www.haomeiwen.com/subject/hvdyfftx.html