上面的代码还是具有一个缺点:功能单一,无法统计某一天的阅读数;
# read_statistics/models.py
from django.utils import timezone
...
# 新增模块
class ReadDetail(models.Model):
date = models.DateField(default=timezone.now)
read_num = models.IntegerField(default=0)
content_type = models.ForeignKey(ContentType, on_delete=models.DO_NOTHING)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
展示在admin中:
# admin.py
from .models import ReadNum, ReadDetail
...
@admin.register(ReadDetail)
class ReadDetailAdmin(admin.ModelAdmin):
list_display = ('date', 'read_num', 'content_object')
在utils.py中通过ReadDetail.objects.filter(...)来统计判断:
# utils.py
from .models import ReadNum,ReadDetail
from django.utils import timezone
......
from django.utils import timezone
def read_statistics_once_read(request, obj):
ct = ContentType.objects.get_for_model(obj)
key = "%s_%s_read" % (ct.model, obj.pk)
if not request.COOKIES.get(key):
# 这里将之前的if-else判断换作了get_or_create方法,如果有则加之,没有创建一个
# 总阅读数 +1
readnum, created = ReadNum.objects.get_or_create(content_type=ct, object_id=obj.pk)
readnum.read_num += 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
# utils.py
import datetime
from django.db.models import Sum
...
def get_seven_days_read_data(content_type):
"""
用于从数据库中提取表中某天的阅读量
"""
today = timezone.now().date()
dates = []
read_nums = []
for i in range(7, 0, -1):
date = today - datetime.timedelta(days=i) # timedelta表示一个差值,这里的差值为i
dates.append(date.strftime('%m/%d')) # 这里因为返回前端的应该是包含字符串的列表而不是整型数字,所以转换一下放在列表中
read_details = ReadDetail.objects.filter(content_type=content_type, date=date)
# 使用聚合计算进行求和显示在后台Read Num列
result = read_details.aggregate(read_num_sum=Sum('read_num'))
read_nums.append(result['read_num_sum'] or 0) # 为了防止没有阅读量的显示为None,这里使用or 0从而使其将none的变为0
return dates, read_nums
修改处理方法:
# mysite/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)
# 将从后端获取到的数据显示在前端
context = {}
context['dates'] = dates
context['read_nums'] = read_nums
return render(request,'home.html',context) # 注意,这里再pycharm中找不到home.html文件
修改home.html(先试验一下,位置一会修改)
在随便看标题下面增加p标签,用来显示阅读量:
{% block content %}
欢迎访问我的博客
{{ read_nums }}
{% endblock %}
首页登录效果:
但是很不美观!使用图表最好,我们这里使用highcharts:地址 :https://www.highcharts.com.cn/
使用方法:
方法:参照1分支上手Highcharts:
首先需要引入 Highcharts
Highcharts 最基本的运行只需要一个 JS 文件,即 highcharts.js,以使用 CDN 文件为例,对应的代码是:
{% block header_extends %}
{% endblock %}
然后通过 Highcharts 的初始化函数 Highcharts.chart 来创建图表,该函数接受两个参数,第一个参数是 DOM 容器的 Id,第二个参数是图表配置,源代码如下:
第一个 Highcharts 图表
分支上手:直接增加header位置和容器引入(read_num的p标签下面),因为不想要坐标轴和标签,所以对text设置为none,然后labels设置为false,横隔线换成虚线,去掉图例,版权信息,x轴分类,具体代码及其解释如下
home.html
{# 这是主页,也是博文列表页 #}
{% extends 'base.html' %} {# 导入base.html中的内容 #}
{% load static %}
{% block title %} {# 用于填充title #}
我的网站|首页
{% endblock %}
.
{% block header_extends %}
{% endblock %}
{% block nav_home_active %}active{% endblock %}
{# 这是页面内容 #}
{% block content %}
欢迎访问我的博客
{# 这里的样式我们写在了home.css中了 #}
{% endblock %}
修改home.css格式:包含修改图表的样式和home显示的
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;
}