博客阅读数的统计三部曲(三)——图表展示

图表展示阅读数

  • 统计某一天的阅读数,从而实现一周阅读数的统计展示

[TOC]

1.创建ReadDetail模型类

首先在read_statistics应用下面models.py创建一个ReadDetail模型类,用于记录阅读详情,基本字段类似ReadNum类模型

博客阅读数的统计三部曲(三)——图表展示_第1张图片
image.png

代码片段,如下:

read_statistics/models.py

+ from django.utils import timezone

class ReadDetail(models.Model):
    '''阅读详情-每日阅读数'''
+    date=models.DateField(default=timezone.now,verbose_name='阅读时间')
    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

2.同步模型到数据库

1. python manage.py makemigrations
2. python manage.py migrate

3.添加应用到admin.py

添加ReadDetail模型到Django管理后台,打开read_statistics应用下面admin.py,做如下操作:


博客阅读数的统计三部曲(三)——图表展示_第2张图片
image.png

代码片段如下:

read_statistics/admin.py

from django.contrib import admin
+from .models import ReadNum,ReadDetail

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

+class ReadDetailAdmin(admin.ModelAdmin):
+    list_display=('id','date','read_num','content_object')

admin.site.register(ReadNum,ReadNumAdmin)
+admin.site.register(ReadDetail,ReadDetailAdmin)

添加完成后,可以启动服务,登录Django自带的管理后台,看下是都添加成功,成功后如下图所示:

博客阅读数的统计三部曲(三)——图表展示_第3张图片
image.png
博客阅读数的统计三部曲(三)——图表展示_第4张图片
image.png

4.utils.py里面添加当日文章阅读数量统计

在read_statistics应用下面utils.py里面做当日文章阅读数的判断统计,具体说明详见代码中的说明:

博客阅读数的统计三部曲(三)——图表展示_第5张图片
image.png

代码片段:

read_statistics/utils.py

+from django.utils import timezone
from django.contrib.contenttypes.models import ContentType
from .models import ReadNum,ReadDetail

def read_statistics_once_read(request,obj):
    ct=ContentType.objects.get_for_model(obj)
    key="%s_%s_read" % (ct.model,obj.pk)
    # 获取cookie:根据获取cookie的key值'blog_%s_readed' % blog_pk,判断是否存在,不存在则阅读数+1
    if not request.COOKIES.get(key):
        # 阅读总数
        if ReadNum.objects.filter(content_type=ct,object_id=obj.pk).count():
            # 记录已经存在,则获取并阅读数+1,保存
            readnum=ReadNum.objects.get(content_type=ct,object_id=obj.pk)
        else:
            # 对应记录不存在,则创建并阅读数+1,保存(这样就会在阅读数管理页面点击后保存对应文章以及阅读数)
            readnum=ReadNum(content_type=ct,object_id=obj.pk)
        readnum.read_num += 1    #点击该篇文章,阅读数自增1
        readnum.save()


+        date=timezone.now().date()
        # 按照日期的阅读数
+        if ReadDetail.objects.filter(content_type=ct,object_id=obj.pk,date=date).count():
            # 记录已经存在,则获取并阅读数+1,保存
            +readDetail=ReadDetail.objects.get(content_type=ct,object_id=obj.pk,date=date)
+        else:
            # 对应记录不存在,则创建并阅读数+1,保存(这样就会在阅读详情管理页面点击后保存对应文章以及阅读数)            +readDetail=ReadDetail(content_type=ct,object_id=obj.pk,date=date)
+        readDetail.read_num += 1
+        readDetail.save()
    return key

下面查看Django管理页面阅读详情,则会根据上面的判断进行数据改变

博客阅读数的统计三部曲(三)——图表展示_第6张图片
image.png

** 根据Django官网get_or_create()方法,对utils.py里面方法进行整理简化**

- 打开Django的官网文章

打开Django的官网文档,搜索get_or_create(),找到对应文档说明:

Django2.0文档-get_or_creat()

博客阅读数的统计三部曲(三)——图表展示_第7张图片
image.png

- 整理优化utils.py

修改utils.py里面read_statistics_once_read()方法的判断,使用Django官网提供的get_or_creat()方法进行判断

get_or_create()方法说明:
get_or_create()方法会返回一个元组,自动判断对象是否存在,存在则+1,找不到不存在则创建,后面的created参数是标记该对象是否是创建,如果创建则为True

使用 get_or_create()方法可与一步完成判断,即可将原有的判断代码进行如下修改:

read_statistics/utils.py 修改


博客阅读数的统计三部曲(三)——图表展示_第8张图片
image.png

read_statistics/utils.py 最终优化后


博客阅读数的统计三部曲(三)——图表展示_第9张图片
image.png

read_statistics/utils.py 代码:

from django.utils import timezone
from django.contrib.contenttypes.models import ContentType
from .models import ReadNum,ReadDetail

def read_statistics_once_read(request,obj):
    ct=ContentType.objects.get_for_model(obj)
    key="%s_%s_read" % (ct.model,obj.pk)

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

        # 阅读总数+1
        readnum, created = ReadNum.objects.get_or_create(content_type=ct,object_id=obj.pk)
        readnum.read_num += 1    #点击该篇文章,阅读数自增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

5.获取7天的阅读数据

在utils.py里面新建根据传入的类型参数来获取前7天get_seven_days_read_data()函数

时间计算说明:
import datetime
today-datetime.timedelra(days-1) #昨天
today-datetime.timedelra(days-2) #前天 > .....
根据上面的规律可以依次找出之前的时间来,所以可以使用for循环来找出前7天的时间:
for i in range(7,0,-1):
# 获取前7天的数据
date=today-datetime.timedelra(days=i)

因为每天的阅读数是按照每篇文章来计数的,所以要计算一天的文章阅读数,就需要对这天的阅读数进行聚合计算


博客阅读数的统计三部曲(三)——图表展示_第10张图片
image.png
博客阅读数的统计三部曲(三)——图表展示_第11张图片
image.png

代码片段:read_statistics/utils.py

import datetime
from django.utils import timezone
from django.db.models import Sum

def get_seven_days_read_data(content_type):
    '''获取前7天阅读数据,根据传入类型获取相应类型前7天阅读数'''
    read_nums=[]
    today=timezone.now().date() #当天时间
    for i in range(7,0,-1):
        # 获取前7天的数据
        date=today-datetime.timedelta(days=i)
        read_details=ReadDetail.objects.filter(content_type=content_type,date=date)  #查询某天的阅读详情对象
        result=read_details.aggregate(read_num_sum=Sum('read_num'))  #根据read_num字段求和Sum('read_num'),并保存在read_num_sum变量中
        read_nums.append(result['read_num_sum'] or 0) #取出result中read_num_sum变量,添加到read_nums列表中;如果是正确取前面的,如果是没有数据,则取0
    return read_nums

6.对前7天阅读数进行显示

打开yhsite目录下面的views.py文件,进行如下操作:


博客阅读数的统计三部曲(三)——图表展示_第12张图片
image.png

代码:yhsite/views.py

from django.shortcuts import render
from django.contrib.contenttypes.models import ContentType
from read_statistics.utils import get_seven_days_read_data
from blog.models import Blog

def home(request):
    blog_content_type=ContentType.objects.get_for_model(Blog) #获取文件类型
    read_nums=get_seven_days_read_data(blog_content_type)     #查询该文件类型下前7天的阅读数

    return render(request,'home.html',{'read_nums':read_nums})

再打开模版下面,添加显示标签


博客阅读数的统计三部曲(三)——图表展示_第13张图片
image.png

启动服务器,打开首页进行查看:


博客阅读数的统计三部曲(三)——图表展示_第14张图片
image.png

显示数据为None,因为暂时还没有前7天的数据,需要对utils.py里面返回数据进行修改,添加若不存在数据则返回数据为0


博客阅读数的统计三部曲(三)——图表展示_第15张图片
image.png

修改后刷新页面,显示如下:


博客阅读数的统计三部曲(三)——图表展示_第16张图片
image.png

7.使用图表进行数据展示

后台提供数据,前台使用数据进行展示即可,这里我们前台数据展示使用Highcharts.js来完成图表的展示功能

由于在使用Highcharts.js过程中,还需要横坐标的数据,即前7天日期的数据,所以,需要在read_statistics/utils.py文件里get_seven_days_read_data()方法返回日期数据的列表dates

博客阅读数的统计三部曲(三)——图表展示_第17张图片
image.png

代码:read_statistics/utils.py

def get_seven_days_read_data(content_type):
    '''获取前7天阅读数据,根据传入类型获取相应类型前7天阅读数'''
    dates=[]         # 前7天的日期列表
    read_nums=[]     # 前7天日期的阅读数列表
    today=timezone.now().date() #当天时间
    for i in range(7,0,-1):
        # 获取前7天的数据
        date=today-datetime.timedelta(days=i)
        dates.append(date.strftime('%m/%d'))
        read_details=ReadDetail.objects.filter(content_type=content_type,date=date)  #查询某天的阅读详情对象
        result=read_details.aggregate(read_num_sum=Sum('read_num'))  #根据read_num字段求和Sum('read_num'),并保存在read_num_sum变量中
        read_nums.append(result['read_num_sum'] or 0) #取出result中read_num_sum变量,添加到read_nums列表中,如果当天没有数据显示0
    return dates,read_nums

再在yhsite/viwes.py里面添加dates的返回数据到前台home.html页面

博客阅读数的统计三部曲(三)——图表展示_第18张图片
image.png

代码:yhsite/views.py

from django.shortcuts import render
from django.contrib.contenttypes.models import ContentType
from read_statistics.utils import get_seven_days_read_data
from blog.models import Blog

def home(request):
    blog_content_type=ContentType.objects.get_for_model(Blog) #获取文件类型
    dates,read_nums=get_seven_days_read_data(blog_content_type)     #查询该文件类型下前7天的阅读数

    return render(request,'home.html',{'dates':dates,'read_nums':read_nums})

代码片段:home.html



欢迎访问我的网站,随便看

打开网站首页,显示效果如下:


博客阅读数的统计三部曲(三)——图表展示_第19张图片
image.png

再对home.css进行调整,让页面显得美观一些

h3.home-content {
    font-size: 222%;
    text-align: center;
    margin-top: 4em;
    margin-bottom: 2em;
}

div#container {
    margin: 0 auto;
    height: 20em;
    min-width: 20em;
    max-width: 30em;
}

再次打开页面,展示最终效果如下所示:


博客阅读数的统计三部曲(三)——图表展示_第20张图片
image.png

你可能感兴趣的:(博客阅读数的统计三部曲(三)——图表展示)