上面的代码还是具有一个缺点:功能单一,无法统计某一天的阅读数;
效果如下:
需要一个专门的模型:包含日期和阅读数量
# 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')
效果如下:.../admin
如何统计汇总?然后显示在首页:
在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 %}
<h3 class="home-content">欢迎访问我的博客</h3>
<p>{{ read_nums }}</p>
{% endblock %}
首页登录效果:
但是很不美观!使用图表最好,我们这里使用highcharts:地址 :https://www.highcharts.com.cn/
使用方法:
方法:参照1分支上手Highcharts:
首先需要引入 Highcharts
Highcharts 最基本的运行只需要一个 JS 文件,即 highcharts.js,以使用 CDN 文件为例,对应的代码是:
{% block header_extends %}
<link rel="stylesheet" href="{% static 'home.css' %}">
<script src="http://cdn.highcharts.com.cn/highcharts/highcharts.js"></script>
{% endblock %}
然后通过 Highcharts 的初始化函数 Highcharts.chart 来创建图表,该函数接受两个参数,第一个参数是 DOM 容器的 Id,第二个参数是图表配置,源代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>第一个 Highcharts 图表</title></head>
<body>
<!-- 图表容器 DOM -->
<div id="container" style="width: 600px;height:400px;"></div>
<!-- 引入 highcharts.js -->
<script src="http://cdn.highcharts.com.cn/highcharts/highcharts.js"></script>
<script>
// 图表配置
var options = {
chart: {
type: 'bar' //指定图表的类型,默认是折线图(line)
},
title: {
text: '我的第一个图表' // 标题
},
xAxis: {
categories: ['苹果', '香蕉', '橙子'] // x 轴分类
},
yAxis: {
title: {
text: '吃水果个数' // y 轴标题
}
},
series: [{ // 数据列
name: '小明', // 数据列名
data: [1, 0, 4] // 数据
}, {
name: '小红',
data: [5, 7, 3]
}]
};
// 图表初始化函数
var chart = Highcharts.chart('container', options);
</script></body></html>
分支上手:直接增加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 %}
<link rel="stylesheet" href="{% static 'home.css' %}">
<script src="http://cdn.highcharts.com.cn/highcharts/highcharts.js"></script>
{% endblock %}
{% block nav_home_active %}active{% endblock %}
{# 这是页面内容 #}
{% block content %}
<h3 class="home-content">欢迎访问我的博客</h3>
<!-- 图表容器 DOM -->
<div id="container"></div> {# 这里的样式我们写在了home.css中了 #}
<script> {# 因为上面已经引入了,这里就不在引入了 #}
// 图表配置
var options = {
chart: { type: 'line' }, //指定图表的类型,默认是折线图(line)
title: { text: null }, // 标题:不需要标题
xAxis: {
// x 轴分类:采用后端发来的dates(包含字符串的列表)显示,因为直接写dates难以被识别,所以这里|safe来转义
categories: {{ dates|safe }},
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>
{% 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;
}
效果如图:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。