图表展示阅读数
- 统计某一天的阅读数,从而实现一周阅读数的统计展示
[TOC]
1.创建ReadDetail模型类
首先在read_statistics应用下面models.py创建一个ReadDetail模型类,用于记录阅读详情,基本字段类似ReadNum类模型
代码片段,如下:
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,做如下操作:
代码片段如下:
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自带的管理后台,看下是都添加成功,成功后如下图所示:
4.utils.py里面添加当日文章阅读数量统计
在read_statistics应用下面utils.py里面做当日文章阅读数的判断统计,具体说明详见代码中的说明:
代码片段:
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管理页面阅读详情,则会根据上面的判断进行数据改变
** 根据Django官网get_or_create()方法,对utils.py里面方法进行整理简化**
- 打开Django的官网文章
打开Django的官网文档,搜索get_or_create(),找到对应文档说明:
Django2.0文档-get_or_creat()
- 整理优化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 修改
read_statistics/utils.py 最终优化后
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)
因为每天的阅读数是按照每篇文章来计数的,所以要计算一天的文章阅读数,就需要对这天的阅读数进行聚合计算
代码片段: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文件,进行如下操作:
代码: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})
再打开模版下面,添加显示标签
启动服务器,打开首页进行查看:
显示数据为None,因为暂时还没有前7天的数据,需要对utils.py里面返回数据进行修改,添加若不存在数据则返回数据为0
修改后刷新页面,显示如下:
7.使用图表进行数据展示
后台提供数据,前台使用数据进行展示即可,这里我们前台数据展示使用Highcharts.js来完成图表的展示功能
由于在使用Highcharts.js过程中,还需要横坐标的数据,即前7天日期的数据,所以,需要在read_statistics/utils.py文件里get_seven_days_read_data()方法返回日期数据的列表dates
代码: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页面
代码: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
欢迎访问我的网站,随便看
打开网站首页,显示效果如下:
再对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;
}
再次打开页面,展示最终效果如下所示: