欢迎来到Felix的博客

Do the right things! And talk is cheap,show me your code!

搭建自己的博客(十七):添加每日阅读量并使用highcharts通过图表显示

之前写了单篇博客的阅读量统计,今天添加了博客总阅读量统计,并且使用highcharts图表显示。

1、变化的部分

2、上代码:

# -*- coding: utf-8 -*-
# @Time    : 18-11-7 下午4:12
# @Author  : Felix Wang

from django.shortcuts import render_to_response
from django.contrib.contenttypes.models import ContentType
from read_statistics.utils import get_seven_days_read_data
from blog.models import Blog


def home(requests):
    blog_content_type = ContentType.objects.get_for_model(Blog)
    dates, read_nums = get_seven_days_read_data(blog_content_type)

    context = {
        'read_nums': read_nums,
        'dates': dates,
    }

    return render_to_response('home.html', context)
views.py
from django.contrib import admin
from .models import ReadNum, ReadDetail


# Register your models here.

@admin.register(ReadNum)
class ReadNumAdmin(admin.ModelAdmin):
    list_display = ('read_num', 'content_object')


@admin.register(ReadDetail)
class ReadNumAdmin(admin.ModelAdmin):
    list_display = ('date', 'read_num', 'content_object')
admin.py
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db.models.fields import exceptions
from django.utils import timezone


# Create your models here.

# 使用到了contenttype 参考网址:https://docs.djangoproject.com/en/2.1/ref/contrib/contenttypes/
class ReadNum(models.Model):
    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')

    def __str__(self):
        return str(self.read_num)


# 阅读计数扩展方法
class ReadNumExpandMethod:
    def get_read_num(self):  # 获取一对一关联的阅读数
        try:
            ct = ContentType.objects.get_for_model(self)
            readnum = ReadNum.objects.get(content_type=ct, object_id=self.pk)
            return readnum.read_num
        except exceptions.ObjectDoesNotExist as e:
            return 0


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')
models.py
# -*- coding: utf-8 -*-
# @Time    : 18-11-17 下午10:03
# @Author  : Felix Wang
import datetime
from django.contrib.contenttypes.models import ContentType
from django.db.models import Sum
from django.utils import timezone
from .models import ReadNum, ReadDetail


def read_statistics_once_read(requests, obj):
    ct = ContentType.objects.get_for_model(obj)
    key = '{}_{}_read'.format(ct.model, obj.pk)

    # 获取并处理阅读计数
    if not requests.COOKIES.get(key):
        # 总阅读量+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


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
utils.py
.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;
}
home.css
{% extends 'base.html' %}
{% load staticfiles %}


{% block header_extends %}
    <link rel="stylesheet" href="{% static 'css/home.css' %}">
    <script src="{% static 'Highcharts-6.2.0/code/highcharts.js' %}"></script>
{% endblock %}

{% block title %}
    我的博客|首页
{% endblock %}


{% block content %}

    <h1 class="home-content">欢迎访问我的博客</h1>

    <!-- 图表容器 DOM -->
    <div id="container"></div>
    <!-- 引入 highcharts.js -->
    <script>
        // 图表配置
        let options = {
            chart: {
                type: 'line' //指定图表的类型,默认是折线图(line)
            },
            title: {
                text: null // 标题
            },
            xAxis: {
                categories: {{ dates|safe }}   // x 轴分类
            },
            yAxis: {
                title: {
                    text: null // y 轴标题
                },
                labels: {
                    enabled: false
                },
                gridLineDashStyle: 'Dash',
            },
            plotOptions: {
                line: {
                    dataLabels: {
                        enabled: true
                    }
                }
            },
            credits: {
                enabled: false // 禁用版权信息
            },
            series: [{ // 数据列
                name: '阅读量', // 数据列名
                data: {{ read_nums }},// 数据
                showInLegend: false, // 设置为 false 即为不显示在图例中
            },]
        };
        // 图表初始化函数
        let chart = Highcharts.chart('container', options);
    </script>
{% endblock %}

{% block js %}
    {# 将首页这个按钮设置激活状态 #}
    <script>
        $(".nav-home").addClass("active").siblings().removeClass("active");
    </script>
{% endblock %}
home.html

3、解释

这里使用了图表框架highcharts,官网:官方文档

posted @ 2018-11-18 22:15  寂静的天空  阅读(209)  评论(0编辑  收藏  举报
个人感悟: 一个人最好的镜子就是自己,你眼中的你和别人眼中的你,不是一回事。有人夸你,别信;有人骂你,别听。一根稻草,扔街上就是垃圾;捆上白菜就是白菜价;捆上大闸蟹就是大闸蟹的价。 一个人,不狂是没有出息的,但一直狂,肯定是没有出息的。雨打残花风卷流云,剑影刀光闪过后,你满脸冷酷的站在珠峰顶端,傲视苍生无比英武,此时我问你:你怎么下去? 改变自己就是改变自己的心态,该沉的时候沉下去,该浮的时候浮上来;不争名夺利,不投机取巧,不尔虞我诈;少说、多听、多行动。人每所谓穷通寿夭为命所系,岂不知造物之报施,全视人之自取。 座佑铭:每一个不曾起舞的日子,都是对生命的辜负。