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

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

作者: 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