美文网首页
博客阅读数的统计三部曲(三)——图表展示

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

作者: yhxt | 来源:发表于2018-03-04 20:41 被阅读0次

图表展示阅读数

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

[TOC]

1.创建ReadDetail模型类

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

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,做如下操作:


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自带的管理后台,看下是都添加成功,成功后如下图所示:

image.png image.png

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

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

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管理页面阅读详情,则会根据上面的判断进行数据改变

image.png

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

- 打开Django的官网文章

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

Django2.0文档-get_or_creat()

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 修改


image.png

read_statistics/utils.py 最终优化后


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)

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


image.png 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文件,进行如下操作:


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})

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


image.png

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


image.png

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


image.png

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


image.png

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

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

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

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页面

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

<script src="http://cdn.hcharts.cn/highcharts/highcharts.js"></script>

<h3 class="home-content">欢迎访问我的网站,随便看</h3>
    <!-- 图表容器 DOM -->
    <div id="container"></div>
    <script>
        // 图表配置
        var options = {
            chart: { type: 'line' },
            title: { text: null },
            xAxis: {
                categories: {{ dates|safe }},   // x 轴分类
                tickmarkPlacement: 'on',
            },
            yAxis: {
                title: { text: null },
                labels:{ enabled: false },
                gridLineDashStyle: 'Dash',
            },
            series: [{                              // 数据列
                name: '阅读量',                     // 数据列名
                data: {{ read_nums }}               // 数据
            }],
            plotOptions: {
                line: {
                    dataLabels: {
                        enabled: true
                    }
                }
            },
            legend: { enabled: false },
            credits: { enabled: false },
        };
        // 图表初始化函数
        var chart = Highcharts.chart('container', options);
    </script>

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


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;
}

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


image.png

相关文章

网友评论

      本文标题:博客阅读数的统计三部曲(三)——图表展示

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