Django + Bootstrap - 【echart】 统计图表进阶使用-统计用户日活日增、月活月增等数据(二)

一. 前言

Bootstrap是一个流行的前端框架,而ECharts是一个流行的可视化库。
Bootstrap可以用来设计网站和应用程序的用户界面,而ECharts可以用来创建交互式和可视化的图表。
chart.js中文文档:http://www.bootcss.com/p/chart.js/docs/
二. 进阶使用
基本使用已经在前文有过相关介绍,链接:https://blog.csdn.net/qq_43030934/article/details/131540606

本文是基于Django+bootstrap+echart插件的一个进阶使用,基本的用法就不做过多介绍了

二. 效果图

1.日活日增统计

在这里插入图片描述

2. 年月数据统计

在这里插入图片描述

三. 示例代码

废话不多说了,直接上代码,

1. 前端

代码是根据相关项目编写的,大家可根据自己的项目进行参考使用

{% extends "base.html" %} {% load static %}{% block main %}{#    <script src="../../../../static/js/echarts-v5.1.2.min.js"></script>#}{% if 'is_superuser' in permissions.keys %}<!-- daily active users statistics start --><section class="section" style="padding: 100px 0 30px 0"><div class="container"><div class="row justify-content-center"><div class="col-12 text-center"><div class="section-title mb-2"><h4 class="title mb-4">用户数据统计</h4></div></div><!--end col--></div><!--end row--><div class="row mt-4 pt-2 position-relative" id="userDailyData" style="z-index: 1;"><div class="col-lg-7 col-6 mt-4 pt-2"><div class="counter-box text-center"><div id="userDailyIncrease" style="width:auto;height:400px;"></div></div><!--end counter box--></div><div class="col-lg-5 col-6 mt-4 pt-2"><div class="counter-box text-center"><div id="userBaseData" style="width:auto;height:400px;"></div></div><!--end counter box--></div></div><!--end row--><div class="feature-posts-placeholder"></div></div><!--end container--></section><!--end section--><!-- daily active users statistics End --><!-- monthly/year increase users statistics start --><section class="section" style="padding: 30px 0 100px 0"><div class="container"><div class="row mt-4 pt-2 position-relative" style="z-index: 1;"><div class="col-lg-6 col-6 mt-4 pt-2"><div class="counter-box text-center"><div id="userMonthlyIncrease" style="width:auto;height:400px;"></div></div><!--end counter box--></div><div class="col-lg-6 col-6 mt-4 pt-2"><div class="counter-box text-center"><div id="userYearIncrease" style="width:auto;height:400px;"></div></div><!--end counter box--></div></div><!--end row--><div class="feature-posts-placeholder"></div></div><!--end container--></section><!--end section--><!-- monthly/year increase users statistics  End -->{% endif %}<!-- Document change achievement Start --><section class="section  bg-light"><div class="container"><div class="row mt-4 pt-2 position-relative" id="counter" style="z-index: 1;"><div class="col-md col-6 mt-4 pt-2"><div class="counter-box text-center"><img src="{% static 'images/homepage/Asset260.svg' %}" class="avatar avatar-small" alt=""><h2 class="mb-0 mt-4"><span class="counter-value"data-count="97">{{ quarterData.requestTotal }}</span></h2><h6 class="counter-head text-muted">{{ quarterData.currentQuarter }} Change requests</h6></div><!--end counter box--></div><div class="col-md col-6 mt-4 pt-2"><div class="counter-box text-center"><img src="{% static 'images/homepage/Asset189.svg' %}" class="avatar avatar-small" alt=""><h2 class="mb-0 mt-4"><span class="counter-value"data-count="15">{{ quarterData.completed }}</span></h2><h6 class="counter-head text-muted">Completed</h6></div><!--end counter box--></div><div class="col-md col-6 mt-4 pt-2"><div class="counter-box text-center"><img src="{% static 'images/homepage/Asset192.svg' %}" class="avatar avatar-small" alt=""><h2 class="mb-0 mt-4"><span class="counter-value"data-count="98">{{ quarterData.percentageComplete }}</span>%</h2><h6 class="counter-head text-muted">Request Complete</h6></div><!--end counter box--></div></div><!--end row--><div class="feature-posts-placeholder"></div></div><!--end container--></section><!--end section--><!-- Document change achievement End -->
{% endblock %}{% block script %}<script>var MyViewVar = {userCurActiveData: {{ userCurActiveData|safe }},usersDataByDaily: {{ usersDataByDaily|safe }},usersDataByMonthly: {{ usersDataByMonthly|safe }},usersDataByYears: {{ usersDataByYears|safe }},}console.log(MyViewVar)var userDailyIncreaseChart = echarts.init(document.getElementById('userDailyIncrease'));userDailyIncreaseChart.setOption({title: {text: '日增日活',x: 'center'},// 图表图例legend: {orient: 'vertical',data: ['日活用户', '日增用户',],left: 'right',},xAxis: {name: '日',type: 'category',data: MyViewVar.usersDataByDaily.date_list,boundaryGap: false,axisLabel: {inside: false, //刻度标签是否朝内,false朝外interval: 1, // 设置标签全部显示rotate: 30, // 设置标签旋转角度maxInterval: 1000, // 设置刻度间隔},axisLine: {lineStyle: {color: '#333',type: 'solid',},}},yAxis: {name: '数量',type: 'value',axisLine: {show: true,    // 是否显示坐标轴轴线lineStyle: {color: '#333',    // 坐标轴线线的颜色type: 'solid',    // 坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)},},},tooltip: {trigger: 'axis',axisPointer: {type: 'cross'}},series: [{name: '日增用户',data: MyViewVar.usersDataByDaily.user_increase_count_list,type: 'line',itemStyle: {color: '#91CC75',},markPoint: {data: [{type: 'max', name: '最大值'},{type: 'min', name: '最小值'}]},lineStyle: {color: '#91CC75', //线颜色type: 'solid', //线的类型opacity: 0.8, //线透明度shadowBlur: 5, //阴影模糊度shadowColor: '#999', //阴影颜色shadowOffsetX: 2, //阴影X轴偏移量shadowOffsetY: 2, //阴影Y轴偏移量radius: 100 //曲线圆角半径},},{name: '日活用户',type: 'line',data: MyViewVar.usersDataByDaily.user_active_count_list,itemStyle: {color: '#FFC858',},markPoint: {data: [{type: 'max', name: '最大值'},{type: 'min', name: '最小值'}]},lineStyle: {color: '#FFC858', //线颜色},},]});var userBaseDataChart = echarts.init(document.getElementById('userBaseData'));//定义饼图数据var data = [{value: MyViewVar.userCurActiveData.dailyActiveCount, name: '日活用户'},{value: MyViewVar.userCurActiveData.monthlyActiveCount, name: '月活用户'},];//定义饼图配置项var option = {title: {text: '用户当日及当月活跃人数\n' + '用户总人数:' + MyViewVar.userCurActiveData.totalCount,x: 'center'},tooltip: {trigger: 'item',formatter: "{a} <br/>{b} : {c}<br/>" + "用户总人数:" + MyViewVar.userCurActiveData.totalCount},legend: {orient: 'vertical',left: 'right',data: ['日活用户', '月活用户']},series: [{name: '用户基础数据统计',type: 'pie',radius: ['40%', '60%'],center: ['50%', '60%'],data: data,label: {show: true,formatter: function (params) {// 计算总数var total = MyViewVar.userCurActiveData.totalCount;// 显示数据项名称和百分比return params.name + '\n' + params.value + '人' + '\n' + (params.value / total * 100).toFixed(2) + '%';}},itemStyle: {emphasis: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}},color: ['#FF8D5D', '#FFC858']}]};//渲染饼图userBaseDataChart.setOption(option);var userMonthlyIncreaseChart = echarts.init(document.getElementById('userMonthlyIncrease'));userMonthlyIncreaseChart.setOption({title: {text: '月增月活',x: 'center'},// 图表图例legend: {data: ['月活用户', '月增用户'],left: 'right',},xAxis: {name: '月',type: 'category',data: MyViewVar.usersDataByMonthly.month_list,boundaryGap: false,axisLabel: {inside: false, //刻度标签是否朝内,false朝外interval: 0, // 设置标签全部显示rotate: 30, // 设置标签旋转角度maxInterval: 1000, // 设置刻度间隔},axisLine: {lineStyle: {color: '#333',type: 'solid',},},},yAxis: {name: '数量',type: 'value',axisLine: {show: true,    // 是否显示坐标轴轴线lineStyle: {color: '#333',    // 坐标轴线线的颜色type: 'solid',    // 坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)},},},tooltip: {trigger: 'axis',},series: [{name: '月活用户',type: 'line',data: MyViewVar.usersDataByMonthly.user_active_count_list,itemStyle: {color: '#FFC858',},markPoint: {data: [{type: 'max', name: '最大值'},{type: 'min', name: '最小值'}]},lineStyle: {color: '#FFC858', //线颜色},},{name: '月增用户',data: MyViewVar.usersDataByMonthly.user_increase_count_list,type: 'line',itemStyle: {color: '#91CC75',},label: {show: true,formatter: function (params) {return params.value;}},markPoint: {data: [{type: 'max', name: '最大值'},{type: 'min', name: '最小值'}]},lineStyle: {color: '#91CC75', //线颜色},},]});var userYearIncreaseChart = echarts.init(document.getElementById('userYearIncrease'));userYearIncreaseChart.setOption({title: {text: '用户年增长及跃人数\n' + '用户总人数:' + MyViewVar.userCurActiveData.totalCount,x: 'center'},tooltip: {},legend: {orient: 'vertical',data: ['年活跃用户', '年增长用户'],left: 'right',},xAxis: {axisLine: {show: true,    // 是否显示坐标轴轴线lineStyle: {color: '#333',    // 坐标轴线线的颜色type: 'solid',    // 坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)},},data: MyViewVar.usersDataByYears.year_list,},yAxis: {name: '数量',type: 'value',axisLine: {show: true,    // 是否显示坐标轴轴线lineStyle: {color: '#333',    // 坐标轴线线的颜色type: 'solid',    // 坐标轴线线的类型(solid实线类型;dashed虚线类型;dotted点状类型)},},},series: [{name: '年活跃用户',type: 'bar',data: MyViewVar.usersDataByYears.user_active_count_list,itemStyle: {color: '#FFC858',},},{name: '年增长用户',type: 'bar',data: MyViewVar.usersDataByYears.user_increase_count_list,},],label: {show: true,position: 'top',  // 在柱形顶部显示标签formatter: '{c}',  // 数值显示格式color: '#000',  // 标签颜色fontSize: 14,  // 标签字体大小},})</script>
{% endblock %}

2. 后端代码

后端代码接口使用的技术栈是Django+ORM
代码仅供参考,大家可自行根据自己项目的业务进行参考使用

class DataStatisticsView(LoginRequiredJSONMixin, APIView):def get(self, request):permissions = get_user_permissions(request.user.id)quarterData = get_quarter_data_statistics(CP_Register)# 获取当前日期now_date = datetime.date.today()userCurActiveData = self.get_cur_user_active_data(now_date)usersDataByDaily = self.get_increase_and_active_users_by_daily(now_date)usersDataByMonthly = self.get_increase_and_active_users_by_monthly(now_date)usersDataByYears = self.get_increase_and_active_users_by_years(now_date)context = {'permissions': permissions,'quarterData': quarterData,'userCurActiveData': userCurActiveData,'usersDataByDaily': usersDataByDaily,'usersDataByMonthly': usersDataByMonthly,'usersDataByYears': usersDataByYears,}return render(request, 'teams/my_dashboard/statistics/data_statistics.html', context)def get_increase_and_active_users_by_years(self, now_date):"""数据库中按年增长及年活跃人数"""# 按年增长统计用户users_per_year = User.objects.annotate(year=ExtractYear('date_joined')).values('year').annotate(total=Count('id'))user_increase_count_list = []year_list = []for user in users_per_year:user_increase_count_list.append(user['total'])year_list.append(user['year'])# 按年统计活跃人数users_per_year = User.objects.annotate(year=ExtractYear('last_login')).values('year').annotate(total=Count('id'))user_active_count_list = []for user in users_per_year:user_active_count_list.append(int(user['total']) * ActiveCoefficient.year_active)usersDataByYears = {'user_increase_count_list': user_increase_count_list,'user_active_count_list': user_active_count_list,'year_list': year_list,}return usersDataByYearsdef get_increase_and_active_users_by_monthly(self, now_date):"""近一年用户月增及月活跃数据sqlite按当月统计一年用户的数量sql:SELECT DATE('now', 'start of month') AS end_date,DATE('now', '-12 months', 'start of month') AS start_date;SELECT strftime('%Y-%m', date_joined) AS month,COUNT(id) AS countFROM auth_userWHERE date_joined >= DATE('now', '-12 months', 'start of month')GROUP BY monthORDER BY month;"""user_increase_count_list = []user_active_count_list = []month_list = []# FIXME--bug:某月用户数量为0时无数据"""end_date = now_date.replace(day=30)start_date = (end_date - datetime.timedelta(days=365)).replace(day=1){'user_count_list': [33, 37, 30, 35, 25, 22, 11, 35, 4, 6, 1, 7], 'month_list': ['22-07', '22-08', '22-09', '22-10', '22-11', '22-12', '23-01', '23-02', '23-03', '23-04', '23-05', '23-07']}users_last_year = User.objects.filter(date_joined__range=(start_date, end_date)).annotate(month=TruncMonth('date_joined')).values('month').annotate(count=Count('id'))for user in users_last_year:user_count_list.append(user['count'])month_list.append(user['month'].strftime('%y-%m'))"""# 计算往前12个月的日期时间,计算月增月活数据for i in range(12):# 当月起始时间和月末时间month_first_day = (now_date - datetime.timedelta(days=365 * i / 12)).replace(day=1)month_last_day = (month_first_day + datetime.timedelta(days=32)).replace(day=1) - datetime.timedelta(days=1)month_increase_count = User.objects.filter(date_joined__range=(month_first_day, month_last_day)).count()month_list.append(month_first_day.strftime('%y-%m'))user_increase_count_list.append(month_increase_count)moth_active_count = int(User.objects.filter(last_login__range=(month_first_day, month_last_day)).count() * ActiveCoefficient.monthly_active)user_active_count_list.append(moth_active_count)usersDataByMonthly = {'user_increase_count_list': user_increase_count_list[::-1],'user_active_count_list': user_active_count_list[::-1],'month_list': month_list[::-1],}return usersDataByMonthlydef get_increase_and_active_users_by_daily(self, now_date):"""近一月用户日增日活数据"""# 获取一个月前日期start_date = now_date - datetime.timedelta(days=30)date_list = []user_increase_count_list = []user_active_count_list = []for i in range(1, 31):# 循环遍历获取当天日期cur_date = start_date + datetime.timedelta(days=i)next_date = start_date + datetime.timedelta(days=i + 1)day_increase_count = User.objects.filter(last_login__range=(cur_date, next_date)).count()date_list.append(cur_date.strftime('%y-%m-%d'))user_increase_count_list.append(day_increase_count)day_active_count = int(User.objects.filter(last_login__range=(cur_date, next_date)).count() * ActiveCoefficient.daily_active)user_active_count_list.append(day_active_count)dailyIncreaseUsers = {'date_list': date_list,'user_increase_count_list': user_increase_count_list,'user_active_count_list': user_active_count_list,}return dailyIncreaseUsersdef get_cur_user_active_data(self, now_date):"""当日及当月活跃数据"""# 日活用户dailyActiveCount = User.objects.filter(last_login__gte=now_date).count()# 月活用户first_day_of_month = datetime.date(now_date.year, now_date.month, 1)last_day_of_month = datetime.date(now_date.year, now_date.month + 1, 1) - datetime.timedelta(days=1)monthlyActiveCount = User.objects.filter(last_login__range=(first_day_of_month, last_day_of_month)).count()# 用户总数totalCount = User.objects.all().count()userCurActiveData = {'dailyActiveCount': int(dailyActiveCount * ActiveCoefficient.daily_active),'monthlyActiveCount': int(monthlyActiveCount * ActiveCoefficient.monthly_active),'totalCount': totalCount,'date': now_date.strftime('%Y-%m-%d'),}return userCurActiveData

utils.py

class ActiveCoefficient:daily_active = 1.5monthly_active = 1.5year_active = 3def get_user_permissions(user_id):from registration.models import UserProfileu_pro = UserProfile.objects.filter(user_id=user_id).first()permissions = OrderedDict()if u_pro.is_superuser:permissions['is_superuser'] = '超级管理员'if u_pro.is_team_leader:permissions['is_team_leader'] = '团队负责人'if u_pro.is_ele_feature_extension_admin:permissions['ele_feature_extension_admin'] = '普通管理员'if u_pro.is_es_feature_extension_admin:permissions['es_feature_extension_admin'] = '普通管理员'if u_pro.role:permissions = get_role_permission(u_pro.role.id, permissions)return permissionsdef get_quarter_data_statistics(obj):"""季度发布数据统计"""today = datetime.date.today()current_quarter = (today.month - 1) // 3 + 1# 当前年份季度current_year_quarter = str(today.year) + 'Q{}'.format(str(current_quarter))total = obj.objects.filter(schedule__startswith=current_year_quarter).count()completed_cnt = obj.objects.filter(schedule__startswith=current_year_quarter).filter(Q(decision__in=['', 'Released']) | Q(decision__isnull=True)).count()try:percentageComplete = int(completed_cnt / total * 100)except Exception as e:percentageComplete = 0logger.info('homePage error :{}'.format(e))QuarterData = {'requestTotal': total,'percentageComplete': percentageComplete,'completed': completed_cnt,'currentQuarter': 'Q{}'.format(current_quarter),}return QuarterData

以上就是Django + Bootstrap - 【echart】 统计图表进阶使用-统计用户日活日增、月活月增等数据的基本使用,希望对你有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/27829.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LT8619B 是一款HDMI转TTL或者2 PORT LVDS的芯片。

LT8619B 1. 概述 LT8619B是龙迅基于清除边缘技术的高性能HDMI接收芯片&#xff0c;符合HDMI 1.4&#xff08;高清多媒体接口&#xff09;规范。RGB 输出端口可支持 RGB888/RGB666/RGB565 格式&#xff0c;输出分辨率最高可支持 4Kx2K 分辨率。凭借可编程标量&#xff0c;LT86…

切换.net Framework 版本后,出现NuGet 包是使用不同于当前目标框架的目标框架安装的,可能需要重新安装

问题现象&#xff1a; 由于添加新的dll文件&#xff0c;依赖的.NET Framework版本与当前的不一致&#xff0c;在vs 中切换了目标框架版本后&#xff0c;运行程序&#xff0c;出现以下的warnning信息&#xff1a; 一些 NuGet 包是使用不同于当前目标框架的目标框架安装的&#…

控制对文件访问

控制对文件访问 Linux文件权限 权限文件影响目录影响r读取文件内容列出目录内容w更改文件内容创建删除目录文件x作为命令执行目录可以变成当前工作目录 命令行管理文件系统权限 更改文件和目录权限 chmod chmod WhoWhatWhich file|directoryWho (u,g,o,a代表用户&#xff…

分布式事务 Seata

分布式事务 Seata 事务介绍分布式理论Seata 介绍Seata 部署与集成Seata TC Server 部署微服务集成 Seata XA 模式AT 模式AT 模式执行过程读写隔离写隔离读隔离 实现 AT 模式 TCC 模式TCC 模式介绍实现 TCC 模式 Saga 模式Seata 四种模式对比 事务介绍 事务&#xff08;Transac…

使用GPU进行大规模并行仿真,解决强化学习采样瓶颈:CPU、GPU架构以及原理详解

强化学习的落地应用场景,我认为可以是仿真环境仿真程度高,且仿真速度快的任务场景。而这篇帖子将会将:使用 GPU 进行大规模并行仿真,解决强化学习采样瓶颈。并直接举出三个例子,展示如何对原有的仿真环境进行修改,让它们适应 GPU 并行加速。 1.强化学习论文背后的仿真环…

降级npm后,出现xxx 不是内部或外部命令解决方法

比如我安装了anyproxy npm install anyproxy -g 之后在cmd中输入anyproxy 发现 anyproxy 不是内部或外部命令解决方法. 一般出现这样的问题原因是npm安装出现了问题&#xff0c;全局模块目录没有被添加到系统环境变量。 Windows用户检查下npm的目录是否加入了系统变量P…

【JavaEE】Tomcat的安装和使用、创建Mevan项目使用Servlet写一个程序

目录 前言 一、Tomcat的下载和安装 二、写一个简单的Servlet项目 1、创建一个Maven项目 2、引入依赖 3、创建目录 4、编写Servlet代码。 5、打包程序 6、将程序部署到Tomcat上 7、验证程序运行结果 三、在IDEA上安装Smart Tomcat插件 四、Servlet中的一些常见错误 …

计算机网络 day9 DNAT实验

目录 DNAT DNAT策略的典型应用环境 DNAT策略的原理 在网关中使用DNAT策略发布内网服务器 DNAT实验&#xff1a; 实验环境&#xff1a; DNAT网络规划拓扑图&#xff1a; 步骤&#xff1a; 1、创建linux客户端Web网站&#xff08;go语言&#xff09;&#xff0c;实现Web服…

RS485远传电表有哪些功能?

RS485远传电表是一种具有远程传输功能的电表&#xff0c;可以通过RS485接口进行数据传输。它主要用于远程测量电能消耗、监测电力质量和实时控制电力负载等方面。 RS485远传电表具有多种功能&#xff0c;如&#xff1a; 1.远程测量电能消耗&#xff1a;RS485远传电表可以通过远…

Fiddler网络调试器,抓包工具供大家学习研究参考

Fiddler 是一个 http 协议调试代{过}{滤}理工具&#xff0c;它能够记录并检查所有你的电脑和互联网之间的 http 通讯&#xff0c;设置断 点&#xff0c;查看所有的“进出”Fiddler 的数据(指 cookiehtmljscss等文件)。 Fiddler 要比其他的网络调试器要更加简单&#xff0c;因为…

SQlite3数据库相关相关命令

目录 1&#xff09;系统命令 以 . 开头2&#xff09;sql语句 以 ;结尾1. 创建表格2. 插入数据3. 查看数据库记录4. 删除信息5. 更新数据6. 增加一列7. 删除一列 &#xff08;sqlite3 不支持直接删除一列&#xff09; 3&#xff09;sqlite3 数据库 C语言 API1. 打开数据库2. 关闭…

C\C++ 使用socket判断ip是否能连通

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan 简介&#xff1a; 使用socket判断ip是否能联通 效果&#xff1a; 代码&#xff1a; #include <iostream> #include <cstdlib> #include <cstdio> #include &…