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

歡迎關注,本號將持續分享本人在編程路上的各類見聞。

相關文章
相關標籤/搜索