阅读计数统计和显示

1.简单计数方法的缺点

1>后台编辑博客可能影响数据

2>功能单一,无法统计某一天的阅读数

为了解决统计某一天博客的阅读数量的信息,我们需要新创建一个模型,里面包含日期。

from django.utils import timezone
class ReadDetail(models.Model):
date = models.DateField(default=timezone.now) #具体到某一天用DateField timezone用于获取时间
read_num = models.IntegerField(default=0)

# 将您的模型ForeignKey 设为ContentType 通过ContentType找到具体的模型
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField() # 记录对应模型的主键值 该字段可以存储您将要关联的模型中的主键值
# 给您的模型一个 GenericForeignKey,并为其传递上述两个字段的名称。如果将这些字段分别命名
# 为“ content_type”和“ object_id”,则可以忽略这些-这些是默认字段名称 GenericForeignKey。
content_object = GenericForeignKey('content_type', 'object_id')


若要统计一天的阅读量,可以细化到每一篇博客的阅读上面去,阅读时,当天的阅读数+1
get_or_create默认值= None** kwargs
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
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)
if not request.COOKIES.get(key):
#总阅读数+1
#get_or_create(默认值= None,** kwargs)一种查找具有给定对象的便捷方法kwargs(如果模型的所有字段均具有默认值,则为空),
# 并在必要时创建一个对象。
#返回的元组,其中是检索到的对象或创建的对象,并且是一个布尔值,指定是否创建了新对象。(object, created)objectcreated
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

然后我们要在前端展示我们的阅读前7天数据,在计数的工具文件中写个获取数据的方法,我们传入content_type可以统计多种模型,首先我们获取日期,
然后筛选出数据,再求和
from django.utils import timezone
from django.db.models import Sum
from .models import ReadNum,ReadDetail
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)
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_nums.append(result['read_num_sum'] or 0)
return dates,read_nums


在home的视图中调用该方法
from django.shortcuts import render
from read_statistics.utils import get_seven_days_read_data
from django.contrib.contenttypes.models import ContentType
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)



使用图表显示数据
后台+前端 后台提供数据,前端使用数据
用highcharts,https://www.highcharts.com.cn/ 里面有使用教程
在home界面引入该图表的js,之后复制一个简单图表进行修改。图表的位置通过css修改
{% extends 'base.html' %}
{% load staticfiles %}

{% block 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>
<script>
// 图表配置
var options = {
chart: {type: 'line'}, //指定图表的类型,默认是折线图(line)
title: {text: null }, // 标题
xAxis: {
categories: {{ dates|safe }}, // x 轴分类
tickmarkPlacement: 'on'
},
yAxis: {
title: {text: null }, // y 轴标题
//是否启用Labels。x,y轴默认值都是true,如果想禁用(或不显示)Labels,设置该属性为false即可。
labels:{ enabled: false}, //坐标轴刻度标签,坐标轴标签(分类)。Labels常用属性有enabled、formatter、step、staggerLines
gridLineDashStyle: 'Dash', //坐标轴网格线,网格线线条样式。和Css border-style类似,常用的有:Solid、Dot、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 %}




posted @ 2020-10-19 21:54  十方劫  阅读(199)  评论(0编辑  收藏  举报