搭建本身的博客(十七):添加每日閱讀量並使用highcharts經過圖表顯示

以前寫了單篇博客的閱讀量統計,今天添加了博客總閱讀量統計,而且使用highcharts圖表顯示。css

一、變化的部分html

二、上代碼:django

# -*- 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

三、解釋app

這裏使用了圖表框架highcharts,官網:官方文檔框架

相關文章
相關標籤/搜索