先看最终画面:

后台代码:
from django.shortcuts import render,HttpResponse
from app1 import models
from datetime import datetime,date,timedelta
def columnsChart(request):
#统计所有来访公司来访次数的by month推移图(柱状堆叠图)
#要画图第一步,获取行名和列名
#列名: 获取visitCus中 所有来访公司的名字
#行名: 获取所有数据库中的月份
#数据:获取所有来访公司在数据库表中的count
#首先获取列名:所有公司名称
companys = models.VisitCusInfo.objects.values("visitCompany__companyName").distinct()
cols=[]
for company in companys:
if company["visitCompany__companyName"] not in cols:
cols.append(company["visitCompany__companyName"])
print(cols)
#再来获取行名及数据
dates = models.VisitCusInfo.objects.values("auditDate") #by客户稽核时间
#对获取到的时间格式整理成by month,只获取月份
rows = []
for row in dates:
month = row['auditDate'].strftime("%Y-%m")
if month not in rows:
rows.append(month)
rows.sort()
print(rows)
#by月份 by公司获取每个公司访问次数
#Echarts官网source参考: 获取legend
# legend: {
# data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他']
# },
legend_data=cols
#获取x轴数据,Echarts官网示例
# xAxis : [
# {
# type : 'category',
# data : ['周一','周二','周三','周四','周五','周六','周日']
# }
x_data = rows
#获取数据内容,Echarts官网示例:
# series : [
# {
# name:'直接访问',
# type:'bar',
# stack: '广告',
# data:[320, 332, 301, 334, 390, 330, 320]
# },
# {
# name:'邮件营销',
# type:'bar',
# stack: '广告',
# data:[120, 132, 101, 134, 90, 230, 210]
# },
series=[]
#rows存的是日期,cols存的是公司名
for com in cols:
serie = {"name":com,"type":"bar","stack":"访问次数","data":None}
series_data = []
for row in rows:
cnt = models.VisitCusInfo.objects.filter(auditDate__year=row[0:4],auditDate__month=row[5:7],visitCompany__companyName=com).values("visitCompany__companyName").count()
series_data.append(cnt)
serie["data"]=series_data
series.append(serie)
#柱子宽度可以在这里设置,注意必须加在最后一个 'bar' 系列上才会生效,并且是对此坐标系中所有 'bar' 系列生效。
series[-1]['barWidth']="40%"
print(series)
#最新访客信息
visits = models.VisitCusInfo.objects.all().order_by("-auditDate")\
.values_list("auditDate","visitCompany__companyName","visitTopic","visitPerson")[0:6]
#画饼图:最近12个月客户稽核次数 by 客户名
#需要获取两个数据 1 公司名:legend_data 2 每个公司稽核次数series_data
companyNames = cols.copy()
series_data = []
#print(companyNames)
for name in companyNames:
thisDate = datetime.date(datetime.now())
deltMonth = thisDate+timedelta(days=-365)
print(deltMonth)
cnt = models.VisitCusInfo.objects.filter(visitCompany__companyName=name,
auditDate__gt=deltMonth).values_list("visitCompany__companyName").count()
series_data.append({"name":name,"value":cnt})
print(companyNames)
print(series_data)
return render(request,"charts/visitChart.html",{
"series":series,
"x_data":x_data,
"legend_data":legend_data,
"visits":visits,
"companyNames":companyNames,
"series_data":series_data
})
前台HTML JS代码:
{#<!DOCTYPE html>#}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>visitCharts</title>
<script src="/static/js/echarts.js"></script>
<link rel="stylesheet" href="../static/css/amazeui.min.css" />
<link rel="stylesheet" href="../static/css/admin.css" />
<style>
table{
font-size: 14px;
}
#chart1{
width: 1000px;
height: 400px;
}
.top_div{
width: 50%;
height: 400px;
float: left;
}
#news{
padding: 3%;
}
a:hover{
color: blue;
}
a{
color: black;
}
</style>
</head>
<body>
<div style="width: 1000px;height: 300px">
<div id = "news" class="top_div">
<table class="am-table am-table-striped am-table-hover am-nbfc">
<thead>
{# <tr>最新客户来访信息</tr>#}
<tr>
<td>CTC客户最新来访信息</td>
{# <td>Topic</td>#}
{# <td>QS</td>#}
</tr>
</thead>
<tbody>
{% for visit in visits %}
<tr style="text-align: left">
<td>
<a href="/visitCus.html/">{{ visit.0 |date:"Y-m-d"}}
 
{{ visit.1 }}
|  {{ visit.2 }}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div id = "chart2" class="top_div">
<span>asdfasdf</span>
</div>
</div>
<div id="chart1"></div>
</body>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('chart2'));
option = {
title : {
//text: 'CTC客户稽核',
subtext: 'CTC各客户稽核占比',
x:'left'
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)" //鼠标悬停显示百分比
//formatter: '{b}:{c}<br/>{b}:{c}'
},
legend: {
type: 'scroll',
orient: 'vertical',
right: 10,
top: 20,
bottom: 20,
data: {{ companyNames|safe }}
//selected: data.selected
},
series : [
{
name: '客户稽核次数',
type: 'pie',
radius : '55%',
center: ['40%', '50%'],
data: {{ series_data|safe }},
// formatter: '{b}\n{c}%', //显示百分比
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
normal:{
label:{
show: true,
position: 'top',
formatter: '{b} \n({c},{d}%)'
}
}
}
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
<script>
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('chart1'));
//app.title = '堆叠柱状图';
option = {
title: {
subtext: 'CTC客户稽核统计'
},
tooltip : {
trigger: 'axis',
axisPointer : { // 坐标轴指示器,坐标轴触发有效
type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
//data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎','百度','谷歌','必应','其他']
data:{{ legend_data|safe }}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis : [
{
type : 'category',
data:{{ x_data|safe }}
//data : ['周一','周二','周三','周四','周五','周六','周日']
}
],
yAxis : [
{
type : 'value',
max: 5
}
],
series:{{ series|safe }},
dataZoom: [
{ // 这个dataZoom组件,默认控制x轴。
type: 'slider', // 这个 dataZoom 组件是 slider 型 dataZoom 组件
start: 20, // 左边在 10% 的位置。
end: 100 // 右边在 60% 的位置。
},
{ // 这个dataZoom组件,默认控制x轴。
type: 'inside', // 这个 dataZoom 组件是 inside 型 dataZoom 组件
start: 20, // 左边在 10% 的位置。
end: 100 // 右边在 60% 的位置。
}
],
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</html>
url:
"""ctcqs URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from app1.views import views
from app1.views import cusLinkbook,visitCustomers,fileDownload,issueViews,cusSopViews
from app1.views import qsMemberViews,cusInfo,issueNameViews,issueDeptViews,csvdownload,csvupload
from app1.views.charts import issueChart,visitChart
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
path('visitCus.html/', visitCustomers.auditCus),
path('cusLinkbook.html/', cusLinkbook.index),
path('addCus.html/', cusLinkbook.addCus),
path('editCus.html/', cusLinkbook.editCus),
path('delCus.html/', cusLinkbook.delCus),
path('seleCus.html/', cusLinkbook.seleCus),
path('addVisitCus.html/', visitCustomers.addVisitCus),
path('fileDownload/', fileDownload.fileDown),
path('editVisitCus.html/', visitCustomers.editVisitCus),
path('delVisitCus.html/', visitCustomers.delVisitCus),
path('seleVisitCus.html/', visitCustomers.seleVisitCus),
path('seleVisitCus.html/', visitCustomers.seleVisitCus),
path('issueIndex.html/', issueViews.issueIndex),
path('addIssue.html/', issueViews.addIssue),
path('editIssue.html/', issueViews.editIssue),
path('seleIssue.html/', issueViews.seleIssue),
path('delIssue.html/', issueViews.delIssue),
path('fileDownloadIssue/', fileDownload.fileDownloadIssue),
path('cusSopIndex.html/', cusSopViews.cusSopIndex),
path('addCusSop.html/', cusSopViews.addCusSop),
path('editCusSop.html/', cusSopViews.editCusSop),
path('seleCusSop.html/', cusSopViews.seleCusSop),
path('delCusSop.html/', cusSopViews.delCusSop),
path('fileDownloadSop/', fileDownload.fileDownloadSop),
path('addQsMember.html/', qsMemberViews.addQsMember),
path('qsMemberIndex.html/', qsMemberViews.qsMemberIndex),
path('delQsMember.html/', qsMemberViews.delQsMember),
path('editQsMember.html/', qsMemberViews.editQsMember),
path('addCusInfo.html/', cusInfo.addCusInfo),
path('cusInfoIndex.html/', cusInfo.cusInfoIndex),
path('editCusInfo.html/', cusInfo.editCusInfo),
path('delCusInfo.html/', cusInfo.delCusInfo),
path('issueNameIndex.html/', issueNameViews.issueNameIndex),
path('addIssueName.html/', issueNameViews.addIssueName),
path('editIssueName.html/', issueNameViews.editIssueName),
path('delIssueName.html/', issueNameViews.delIssueName),
path('addIssueDept.html/', issueDeptViews.addIssueDept),
path('editIssueDept.html/', issueDeptViews.editIssueDept),
path('delIssueDept.html/', issueDeptViews.delIssueDept),
path('issueDeptIndex.html/', issueDeptViews.IssueDeptIndex),
path('downloadSopCsv/', csvdownload.downloadSopCsv),
path('downloadQs/', csvdownload.downloadQs),
path('downloadVisitCus/', csvdownload.downloadVisitCus),
path('downloadIssue/', csvdownload.downloadIssue),
path('downloadCusLinkbook/', csvdownload.downloadCusLinkbook),
path('uploadIssue/', csvupload.uploadIssue),
path('downloadIssueFormat/', csvdownload.downloadIssueFormat),
path('chart.html/', views.chart),
path('visitChart.html/', visitChart.columnsChart),
path('issueChart.html/', issueChart.chart1),
]

本文展示了一个基于Django框架的客户稽核数据可视化应用,通过柱状堆叠图和饼图展示了不同客户每月的访问次数及过去一年的稽核次数分布。利用ECharts进行数据可视化,从数据库中提取客户名称、访问日期等信息,生成动态图表。
1330

被折叠的 条评论
为什么被折叠?



