使⽤echarts做⼀个可视化报表(⼀)
前段时间利⽤django+vue编写了⼀个构造测试数据的平台,⽬前已经把各个系统常⽤的构造数据请求放到了平台上。
为了更直观的观察这个平台的使⽤情况,利⽤echarts做了⼀个可视化的报表,最终效果如下
本篇来介绍下报表从构思到实现的过程
我的需求:
1、本次打算做2张表,⼀个以周为维度,统计每天在平台上构造数据的次数(前者使⽤折线图、后者使⽤饼图);
2、以系统为维度,统计每个系统构造数据的次数;
根据需求,拆解下我要做的事情:
1、在数据库⾥创建⼀张表,记录创建数据过程;
2、添加后端逻辑,每构造⼀条数据(前端每发起⼀次创建数据的请求),便向表⾥插⼊⼀条记录;
3、后端新增视图函数,通过查询数据库,把数据返回给前端报表;
4、前端处理后端返回的数据,传给echarts,把数据展⽰出来;
⼀、Django连接mysql数据库并创建表
1、把django默认数据库配置,由sqlite3改为mysql
打开 settings.py,定位到DATABASES配置项
DATABASES = {
'default': {
'ENGINE': 'django.sql',
'OPTIONS': {
'init_command': "SET sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,"
"ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'",
},  # 连接到数据库时要使⽤的其他参数。可⽤参数取决于您的数据库后端
'NAME': 'data_factory',  # 要使⽤的数据库的名称(先到mysql数据库创建⼀个库)
'USER': 'root',
'PASSWORD': '12345678',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
2、由于后⾯我是⽤pymysql来操作数据库的,所以需要配置⼀下,使django能够通过pymysql操作数据库
打开django项⽬根⽬录下__init__py
import pymysql
pymysql.install_as_MySQLdb()
3、打开models.py,利⽤django⾃带的模型来创建⼀张表(也可以⾃⼰在数据库中建好)
from django.db import models
# Create your models here.
class DataFactory(models.Model):
id = models.AutoField
class_name = models.CharField(max_length=50)
class_id = models.CharField(max_length=50)
start_time = models.DateTimeField(auto_now=False)
end_time = models.DateTimeField(auto_now=False)
这张表定义了5个字段
id表⽰数据的⾃增编号;
class_name表⽰数据类型名称,⽤来区分是哪个系统创建的数据;
class_id表⽰数据类型id;
start_time表⽰数据开始创建的时间;
end_time表⽰数据创建完成的时间;
上述字段是我⾃⼰定义的,可以根据需要⾃⼰进⾏修改
定义好模型后,需要把表映射到数据库中,执⾏以下命令
先执⾏
python manage.py makemigrations app
再执⾏
python manage.py migrate
这样在数据库中就创建好了⼀张表
⼆、修改django视图⽂件,向数据库插⼊数据
关于如何利⽤django 模型models向数据插⼊数据,可以参考下⾯⼀篇博客:
因为我打算每创建成功⼀条数据,就向数据库⾥插⼊⼀条数据,这条数据需要包含:数据类型名称、数据类型id、开始创建时间、创建成功时间所以我需要定义上述字段的值,然后插⼊库⾥
dels import DataFactory
def create_draft_bill(contract_code, num, money):
"""
创建【草稿】账单
:param money:
:param contract_code:
:param num:
:return:
"""
start_time = w()  # 数据开始创建的时间
data = ate_contract_bill(contract_code, num, money)
end_time = w()  # 数据创建结束时间
df = DataFactory(class_name="合同", class_id="1", start_time=start_time, end_time=end_time)  # 执⾏后,向数据库插⼊⼀条数据
df.save()
return data
如上是我定义的⼀个创建账单的⽅法,每当创建成功⼀条账单时,要把这条记录插⼊数据库。
我把 DataFactory模型导进来,然后分别定义了开始、结束时间、数据名称等,调⽤模型把数据插⼊库并保存即可。
三、新增视图⽅法供前端调⽤
由于我把报表放在了⼀个单独的页⾯,期望每当打开这个页⾯时,就展⽰图表,所以这⾥⾯发⽣了2件事:
1、打开报表页⾯时,向后端发送请求获取数据;
2、拿到数据后,前端把数据渲染到页⾯的报表中;
因为有2个表,所以我打算写2个视图函数分别来提供对应的数据
折线图
折线图的横轴为⽇期:【周⼀】~【周⽇】,纵轴为数量
所以我要查到当前周的数据,并把⽇期与周⼏做⼀个映射,最终 sql 如下
select case dayofweek(date_format(start_time, '%Y-%m-%d'))
when 1 then '周⽇'
when 2 then '周⼀'
when 3 then '周⼆'
when 4 then '周三'
when 5 then '周四'
when 6 then '周五'
when 7 then '周六'
end as week
, count(*) as count from app_datafactory where yearweek(date_format(start_time, '%Y-%m-%d'))=yearweek(now())
group by week;  # 按照周纬度统计
查出来的效果如下
这⾥有个问题,当这⼀天有数据时,则可以查出这条记录;当这⼀天没数据时,并不是显⽰类似【周三 
0】,⽽是直接没有这条记录
这种不能直接返到前端,需要把0的情况处理下
最终的折线图对应的视图⽅法如下
def query_value_statistics(request):
"""折线图数据"""
conn = t(host="localhost", user="root", password="12345678", port=3306, db="data_factory",
charset='utf8')  # 链接数据库
cursor = conn.cursor()  # 不能共⽤⼀个线程池,⼀个⽅法链接⼀个mysql
sql = "select case dayofweek(date_format(start_time, '%Y-%m-%d')) " \
"when 1 then '周⽇' " \
"when 2 then '周⼀' " \
"when 3 then '周⼆' " \
"when 4 then '周三' " \
"when 5 then '周四' " \
"when 6 then '周五' " \
"when 7 then '周六' " \
"end as week, " \
"count(*) as count " \
"from app_datafactory " \
"where yearweek(date_format(start_time, '%Y-%m-%d'))=yearweek(now()) group by week;"# yearweek(xx,mode=1),表⽰周⼀是⼀周的第⼀天;默认周⽇是第⼀天# print(sql)
conn.ping(reconnect=True)
t = cursor.fetchall()
cursor.close()  # 关闭游标
conn.close()  # 关闭连接
dict_value = {} # 定义⼀个空字典
for i in t:
j = {i[0]: i[1]}
dict_value.update(j)  # 遍历从数据库查到的数据,把每组数据都追加的字典中,最后dict_value形如{"周⼆":xx, "周四":xx, "周六":xx}
week = {"周⼀": 0, "周⼆": 0, "周三": 0, "周四": 0, "周五": 0, "周六": 0, "周⽇": 0}  # 定义⼀个字典,每天的数据为0
week.update(dict_value)  # 把dict_value字典合并到week字典中,这样有数据的⽇期正常显⽰数据,⽆数据的⽇期显⽰0
statistics_data = [] # 定义⼀个空列表
for t in week.items():  # 把字典中的数据处理为⼀个个⼩的字典,形如{"周⼀": 3},依次追加到列表中
statistics_data.append({
"name": t[0],
"value": t[1]
})
data = {
"code": "200",
"data": statistics_data
}
return JsonResponse(data, json_dumps_params={'ensure_ascii': False})
最终的 statistics_data 打印效果如下
[{'name': '周⼀', 'value': 12}, {'name': '周⼆', 'value': 4}, {'name': '周三', 'value': 0}, {'name': '周四', 'value': 0}, {'name': '周五', 'value': 0}, {'name': '周': 0}, {'name': '周⽇', 'value': 0}]
饼图
饼图是统计每个系统构造数据的数量,sql如下
select class_name, count(*) from app_datafactory group by class_name;
视图函数如下
def pie_statistics(request):
"""饼图数据"""
conn = t(host="localhost", user="root", password="12345678", port=3306, db="data_factory",
charset='utf8')  # 链接数据库
cursor = conn.cursor()
values = []
sql1 = "select class_name, count(*) from app_datafactory group by class_name;"    conn.ping(reconnect=True)
t = cursor.fetchall()
for i in t:
block = {
"value": i[1],
"name": i[0]
}
values.append(block)
cursor.close()  # 关闭游标
conn.close()  # 关闭连接
data = {
"code": "200",
"data": values
}
return JsonResponse(data, json_dumps_params={'ensure_ascii': False})
values打印结果如下
[{'value': 44, 'name': '合同'}, {'value': 2, 'name': '项⽬运营'}, {'value': 26, 'name': '线索商机'}]
四、前端引⼊echarts,渲染数据
关于如何再vue中使⽤echarts,这⾥不做赘述,重点写⼀下报表前端处理逻辑,新建⼀个 statistics.vue
1、折线图
(1)引⼊折线图相关的echart代码
html代码中留出⼀个div容器,存放折线图
<div id="main1" ></div>
在script标签下先引⼊echarts包
import * as echarts from 'echarts'
在methods下新建⼀个⽅法,存放折线图echarts相关代码
echarts_test(data) {
let myChart1 = echarts.ElementById('main1'));
// 指定图表的配置项和数据
let val = data.map(x => x.value)
/
/ console.log(val)
let option1 = {
// title: {  //图表的标题
//  text: '每⽇创建数据汇总',
//  left: 'center',
//  show: false
// },
tooltip: {
trigger: 'axis',
// axisPointer: {
//  type: 'cross'
/
/ }
},
grid:{  //折线图在当前容器的位置调整
x:22, //左侧距离左边的距离
y:4,  //顶部最⾼点距离顶部的位置
x2:50, // 右侧距离右侧的距离
y2:20,  //距离底部距离
borderWidth:1
},
color: ['#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
xAxis: {
type: 'category',
data: ['周⼀', '周⼆', '周三', '周四', '周五', '周六', '周⽇'],
// axisPointer: {  //配置show为true,显⽰此轴的axisPointer
//  show: true
// }
},
yAxis: {
type: 'value'
},
series: [
{
name: "创建数据",
smooth: false,  // 控制是否为平滑曲线(false为折线)
data: val,
type: 'line',
areaStyle: { //区域填充样式 /zh/option.html#series-line.areaStyle
color:  // 线性渐变填充
{
type: 'linear',
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [{
offset: 0, color: 'white' // 0% 处的颜⾊
}, {
offset: 1, color: 'green' // 100% 处的颜⾊
}],
global: false// 缺省为 false
}
}
}
]
};
这个⽅法传了⼀个data参数,这个就是数据源,即后端返回的数据;django前端模板
使⽤ map ⽅法提取其中的value ,如 let val = data.map(x => x.value)
(2)在methods下再新建⼀个⽅法,发送请求,获取折线图数据
query_value_statistics() {
this.$(":8000/data_factory/query_value_statistics",
{
// timeout: 10000,
params:{
}
})
.
then(response =>{
let datas= response.data.data;
console.log("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")            console.log(datas)
// console.log(datas[0]["name"])
// console.log(datas[0].name)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。