Superset 0.28三奏曲——安装、集成ECharts和汉化

前言

第一次写博客,本着共享知识而来,为技术的发展作点小贡献。最近在研究Superset安装、集成ECharts和汉化的工做,网上关于Superset的相关文章感受挺少的,因此想写这一篇综合点的博客,来和你们共享,若有不足,请多指教。javascript

1 环境和版本

操做系统:CentOS Linux release 7.5.1804 (Core)
python版本:3.6.4(直接安装Anaconda便可)html

2 一奏曲——Superset安装(0.28版本)

Superset 0.22版本的看板中存在不少bug,好比:多个类型同样的图表加入到看板中,只有第一个图能够显示,其余同类型的图均显示不出。在最新版本中不存在,故建议安装最新版本Superset 0.28。
(1)万事开头难。首先我们得要先安装Anaconda,由于接下来须要用到pip,去这里下载安装,最新Superset支持使用python3的版本。
(2)安装superset前端

  1. pip install superset

划重点!用pip安装的最新版本Superset的目录与0.28.1版本源码有差别,实际上是不全,去这里下载源码,下载好以后,要用源码中Superset\superset\assets下的src目录替换本身安装的superset的assets下的src目录便可,这个步骤为后续集成ECharts作准备。
(3)初始化java

  1. fabmanager create-admin --app superset //建立管理员帐号python

  2. superset db upgrade //初始化数据库webpack

  3. superset load_examples //载入模板数据git

  4. superset init //初始化角色和权限github

  5. superset runserver -d -p 8088 //启动服务,端口号 8088,使用 -p 更改端口号web

最后若是浏览器进入不了登陆界面,这是由于防火墙的问题,打开就行了。
(4)后台运行superset
使用以下命令,就可让superset在后台运行,就不用每一次启动服务了。sql

  1. nohup superset runserver -d -p 8088 &

  2. tail -f nohup.out

有图有真相!
Alt
(5)安装编译前端须要的js包
这一步是为接下来的ECharts集成作准备,进入到superset\static\assets下,在命令行中输入

  1. npm install

(6)编译前端
须要的包所有安装完以后,进入superset\static\assets下,在命令行中输入

  1. npm run dev

这一步若是报错,排除语法和权限问题,是包没有安装全的缘由,必定要把包安装全才行。
我遇到的是这两个错误:在这里插入图片描述

  1. ERROR in ./src/visualizations/index.js 86:19
  2. Module parse failed: Unexpected token (86:19)
  3. You may need an appropriate loader to handle this file type.
  4. | var loadNvd3 = function () {
  5. | function loadNvd3() {
  6. > return loadVis(import( /* webpackChunkName: "nvd3_vis" */'./nvd3/adaptor.jsx'));
  7. | }
  8. |
  9. @ ./src/modules/AnnotationTypes.js 15:15-30
  10. @ ./src/chart/chartAction.js
  11. @ ./src/explore/components/ExploreViewContainer.jsx
  12. @ ./src/explore/App.jsx
  13. @ ./src/explore/index.jsx
  14. @ multi babel-polyfill ./src/explore/index.jsx

把包安装全以后,再执行npm run dev命令,编译就经过了。以后在ECharts集成时就能够看到实时编译的网页效果了。

3 二奏曲——Superset集成ECharts(重点)

Superset集成ECharts其实说来也简单,主要操做5个地方,分别是:
(1)后端文件
处理传入前端的数据格式
superset/viz.py
(2)先后端函数匹配文件
superset/static/assets/src/visualizations/index.js
(3)你的新增图表名称.js
superset/static/assets/src/visualizations/你的新增图表名称.js
(4)前端图标配置区组件设置
它是Superset左侧的GroupBy等组件的开关,需根据你新增的图表要用的数据格式选择合适的组件
superset/static/assets/src/explore/visTypes.jsx
(5)缩略图
superset/static/assets/images/viz_thumbnails
下面来举两个集成Echarts图表的例子

3.1 极坐标柱状图

(1)后端文件
进入到superset/viz.py文件中,在BaseViz类的下方和TableViz的上方加入以下代码(与其余的类似):

  1. class EchartsBarPolar(BaseViz):
  2. viz_type = 'echarts_bar_polar' #对应前端的名字
  3. is_timeseries = False
  4. def should_be_timeseries(self):
  5. fd = self.form_data
  6. conditions_met = (
  7. (fd.get('granularity') and fd.get('granularity') != 'all') or
  8. (fd.get('granularity_sqla') and fd.get('time_grain_sqla'))
  9. )
  10. if fd.get('include_time') and not conditions_met:
  11. raise Exception(_(
  12. 'Pick a granularity in the Time section or '
  13. "uncheck 'Include Time'"))
  14. return fd.get('include_time')
  15. def query_obj(self):
  16. d = super(EchartsBarPolar, self).query_obj()
  17. fd = self.form_data
  18. if fd.get('all_columns') and (fd.get('groupby') or fd.get('metrics')):
  19. raise Exception(_(
  20. 'Choose either fields to [Group By] and [Metrics] or '
  21. '[Columns], not both'))
  22. sort_by = fd.get('timeseries_limit_metric')
  23. if fd.get('all_columns'):
  24. d['columns'] = fd.get('all_columns')
  25. d['groupby'] = []
  26. order_by_cols = fd.get('order_by_cols') or []
  27. d['orderby'] = [json.loads(t) for t in order_by_cols]
  28. elif sort_by:
  29. if sort_by not in d['metrics']:
  30. d['metrics'] += [sort_by]
  31. d['orderby'] = [(sort_by, not fd.get('order_desc', True))]
  32. if 'percent_metrics' in fd:
  33. d['metrics'] = d['metrics'] + list(filter(
  34. lambda m: m not in d['metrics'],
  35. fd['percent_metrics'],
  36. ))
  37. d['is_timeseries'] = self.should_be_timeseries()
  38. return d
  39. def get_data(self, df):
  40. fd = self.form_data
  41. if not self.should_be_timeseries() and DTTM_ALIAS in df:
  42. del df[DTTM_ALIAS]
  43. return dict(
  44. records=df.to_dict(orient='records'),
  45. columns=list(df.columns),
  46. )

(2)先后端函数匹配文件
进入到superset/static/assets/src/visualizations/index.js文件中,
在export const VIZ_TYPES里新增

  1. echarts_bar_polar: 'echarts_bar_polar',

在const vizMap里新增

  1. [VIZ_TYPES.echarts_bar_polar]: () => loadVis(import(/*webpackChunkName: 'echarts_bar_polar' */ './echarts_bar_polar.js')),

(3)echarts_bar_polar.js
在superset/static/assets/src/visualizations文件夹下,放入echarts_bar_polar.js文件,代码以下:

  1. import echarts from 'echarts';
  2. import {getColorFromScheme} from '../javascripts/modules/colors';
  3. function EchartsBarPolarVis(slice, payload) {
  4. var div = d3.select(slice.selector);
  5. const sliceId = 'e_bar_polar' + slice.formData.slice_id
  6. var html = '<div id="' + sliceId + '" style="width:' + slice.width() + 'px;' + ''
  7. + 'px;height:' + slice.height() + 'px;"></div>';
  8. div.html(html);
  9. var myChart = echarts.init(document.getElementById(sliceId));
  10. var option = {
  11. angleAxis: {
  12. type: 'category',
  13. data: [],
  14. z: 10
  15. },
  16. radiusAxis: {},
  17. polar: {},
  18. series: []
  19. };
  20. myChart.setOption(option);
  21. const fd = slice.formData;
  22. const json = payload.data;
  23. const data = json;
  24. const records = data['records'];
  25. const data_column = data.columns;
  26. const metrics = fd.metrics;
  27. const group_by = fd.groupby;
  28. var legend_name = [];
  29. var axis_name = [];
  30. var series_data = [];
  31. for (var i = 0; i < records.length; i++) {
  32. axis_name.push(records[i][data_column[0]]);
  33. }
  34. for (var i = 0; i < metrics.length; i++) {
  35. legend_name.push(metrics[i]);
  36. var tmp_data = [];
  37. for (var j = 0; j < records.length; j++) {
  38. tmp_data.push(records[j][metrics[i]]);
  39. }
  40. series_data.push(
  41. {
  42. type: 'bar',
  43. data: tmp_data,
  44. coordinateSystem: 'polar',
  45. name: legend_name[i],
  46. stack: 'a'
  47. }
  48. )
  49. }
  50. var option2 = {
  51. angleAxis: {
  52. data: axis_name
  53. },
  54. series: series_data
  55. };
  56. myChart.setOption(option2);
  57. }
  58. module.exports = EchartsBarPolarVis;

(4)前端图标配置区组件设置
进入superset/static/assets/src/explore/visTypes.jsx文件中,在export const visTypes里新增以下代码:

  1. echarts_bar_polar: {
  2. label: t('Bar Polar'),
  3. showOnExplore: true,
  4. controlPanelSections: [
  5. {
  6. label: t('GROUP BY'),
  7. controlSetRows: [
  8. ['groupby'],
  9. ['metrics'],
  10. ['percent_metrics'],
  11. ['include_time'],
  12. ['timeseries_limit_metric', 'order_desc'],
  13. ],
  14. },
  15. {
  16. label: t('NOT GROUPED BY'),
  17. description: t('Use this section if you want to query atomic rows'),
  18. controlSetRows: [
  19. ['all_columns'],
  20. ['order_by_cols'],
  21. ],
  22. },
  23. {
  24. label: t('Options'),
  25. controlSetRows: [
  26. ['table_timestamp_format'],
  27. ['row_limit', 'page_length'],
  28. ['include_search', 'table_filter'],
  29. ],
  30. },
  31. ],
  32. controlOverrides: {
  33. metrics: {
  34. validators: [],
  35. },
  36. time_grain_sqla: {
  37. default: null,
  38. },
  39. },
  40. },

(5)缩略图
在superset/static/assets/images/viz_thumbnails文件夹下放入极坐标柱状图的缩略图
在这里插入图片描述
到此极坐标柱状图就集成好啦,快来看看下面的效果吧!

在这里插入图片描述

3.2 中国地图(可下钻至市级)

(1)后端文件
进入到superset/viz.py文件中,在BaseViz类的下方和TableViz的上方加入以下代码(与其余的类似):

  1. class ChinaMap(BaseViz):
  2. """ ChinaMap viz """
  3. viz_type = 'ChinaMap'
  4. verbose_name = _('ChinaMap')
  5. is_timeseries = False
  6. def get_data(self, df):
  7. form_data = self.form_data
  8. df.sort_values(by=df.columns[0], inplace=True)
  9. print(df.values.tolist())
  10. ori_data = df.values.tolist()
  11. data = [{'name' : ori_data[i][0], 'value' : ori_data[i][1]} for i in range(len(ori_data))]
  12. data_name = [ori_data[i][0] for i in range(len(ori_data))]
  13. max_data = max([ori_data[i][1] for i in range(len(ori_data))])
  14. min_data = min([ori_data[i][1] for i in range(len(ori_data))])
  15. return [data, data_name, max_data, min_data]

(2)先后端函数匹配文件
进入到superset/static/assets/src/visualizations/index.js文件中,
在export const VIZ_TYPES里新增

  1. ChinaMap: 'ChinaMap',

在const vizMap里新增

  1. [VIZ_TYPES.ChinaMap]: () => loadVis(import(/*webpackChunkName: 'ChinaMap' */ './ChinaMap.js')),

(3)ChinaMap.js
在superset/static/assets/src/visualizations文件夹下,放入ChinaMap.js文件,代码以下:

  1. import echarts from 'echarts';
  2. require('echarts/map/js/china.js');
  3. require('echarts/map/js/province/index.js');
  4. function ChinaMapVis(slice, payload) {
  5. const div = d3.select(slice.selector);
  6. const sliceId = 'echarts_slice_' + slice.formData.slice_id;
  7. const html = '<div id=' + sliceId + ' style="width:' + slice.width() + 'px;height:' + slice.height() + 'px;"></div>';
  8. div.html(html); // reset
  9. const myChart = echarts.init(document.getElementById(sliceId));
  10. const get_data = payload.data;
  11. const data_value = get_data[0];
  12. const data_name = get_data[1];
  13. const max_data = get_data[2];
  14. const min_data = get_data[3];
  15. const option = {
  16. title : {
  17. subtext:'点击进入下一级,双击返回中国地图',
  18. x:'center',
  19. bottom:'5%'
  20. },
  21. tooltip : {
  22. trigger: 'item',
  23. formatter: "{c}"
  24. },
  25. toolbox: {
  26. show: true,
  27. orient: 'vertical',
  28. left: 'right',
  29. top: 'center',
  30. feature: {
  31. dataView: {readOnly: false},
  32. restore: {},
  33. saveAsImage: {}
  34. }
  35. },
  36. visualMap: {
  37. //type: 'continuous',
  38. min: min_data,
  39. max: max_data,
  40. text:['高','低'],
  41. realtime: false,
  42. calculable: true,
  43. //right:'-15%',
  44. inRange:{
  45. color: ['#d0f4fc',
  46. '#a9dbf6',
  47. '#9cd3f4',
  48. '#93cdf3',
  49. '#83c2f0',
  50. '#6eb5ed',
  51. 'yellow']
  52. }
  53. },
  54. series : [
  55. {
  56. type : 'map',
  57. map: 'china',
  58. selectedMode: 'single',
  59. roam: 'scale',
  60. data : data_value,
  61. label: {
  62. normal: {
  63. show: true,
  64. textStyle:{color:"#b6a38a"}
  65. },
  66. emphasis: {
  67. show: true,
  68. textStyle:{color:"#ff6347"}
  69. }
  70. },
  71. itemStyle: {
  72. emphasis: {
  73. areaColor:"#2e4783",
  74. borderWidth: 0
  75. }
  76. }
  77. }
  78. ]
  79. };
  80. myChart.setOption(option);
  81. myChart.on('mouseover', function (params) {
  82. var dataIndex = params.dataIndex;
  83. console.log(dataIndex);
  84. });
  85. myChart.on('click', function (chinaParam) {
  86. if (chinaParam.name == chinaParam.name
  87. &&data_name.indexOf(chinaParam.name)>-1) {
  88. var option = myChart.getOption();
  89. option.series[0].map = chinaParam.name;
  90. myChart.setOption(option);
  91. }
  92. });
  93. myChart.on('dblclick', function (chinaParam) {
  94. if (myChart.getOption().series[0].map != 'china') {
  95. var option = myChart.getOption();
  96. option.series[0].map = 'china';
  97. myChart.setOption(option);
  98. }
  99. });
  100. }
  101. module.exports = ChinaMapVis;

(4)前端图标配置区组件设置
进入superset/static/assets/src/explore/visTypes.jsx文件中,在export const visTypes里新增以下代码:

  1. ChinaMap: {
  2. label: t('ChinaMap'),
  3. showOnExplore: true,
  4. controlPanelSections: [
  5. {
  6. label: t('GROUP BY'),
  7. controlSetRows: [
  8. ['groupby'],
  9. ['metrics'],
  10. ['percent_metrics'],
  11. ['include_time'],
  12. ['timeseries_limit_metric', 'order_desc'],
  13. ],
  14. },
  15. {
  16. label: t('NOT GROUPED BY'),
  17. description: t('Use this section if you want to query atomic rows'),
  18. controlSetRows: [
  19. ['all_columns'],
  20. ['order_by_cols'],
  21. ],
  22. },
  23. {
  24. label: t('Options'),
  25. controlSetRows: [
  26. ['table_timestamp_format'],
  27. ['row_limit', 'page_length'],
  28. ['include_search', 'table_filter'],
  29. ],
  30. },
  31. ],
  32. controlOverrides: {
  33. metrics: {
  34. validators: [],
  35. },
  36. time_grain_sqla: {
  37. default: null,
  38. },
  39. },
  40. },

(5)缩略图
在superset/static/assets/images/viz_thumbnails文件夹下放入中国地图的缩略图
在这里插入图片描述
到此中国地图就集成好啦,快来看看下面的效果吧!点击中国地图的省份能够下钻到市级,双击返回中国地图。
在这里插入图片描述
在上面的图中点击北京市,可进行下钻,双击可返回中国地图。
在这里插入图片描述

4 三奏曲——汉化

在superset/translations/zh/LC_MESSAGES安装目录下有两个文件:messages.po文件和messages.json文件,只须要把这两个文件中的英文对应的中文添上,这但是个费时的工做,而后编译便可。
(1)messages.po文件
在msgstr字段中添上对应的中文
Alt
(2)messages.json文件
在[""]中添上对应的中文
Alt
(3)设置默认语言为中文
在superset目录下有一个config.py文件,编辑它,找到BABEL_DEFAULT_LOCALE处,更改成’zh’,以下图:
Alt
(4)编译
翻译完英文以后就能够在superset目录下进行编译了 ,命令以下:

  1. pybabel compile -d translations

重启Superset便可看到汉化以后的成果啦!

5 总结

从升级安装Superset,到Superset集成ECharts,最后在汉化,这个过程总共用了七天的时间,收获仍是很大的,有了些进步,对于先后端也有了些认识。回头再看看Superset这个BI工具真的太棒了,各类图很是炫,对于数据的分析也是很是轻松。可视化是数据的一种重要的呈现形式,也是数据分析的“最后一千米”,Superset绝对算得上一名有实力的高富帅,快来使用吧!

原文连接:https://blog.csdn.net/qq_33703137/article/details/87874277

欢迎关注,本号将持续分享本人在编程路上的各类见闻。

相关文章
相关标签/搜索