赞
踩
1、win7_64或win10_64,
2、python3.7,
3、superset0.27.0(因0.28.0目录发生变更,暂不适用)
4、.net framework4.6,
5、vc++14.0(http://go.microsoft.com/fwlink/?LinkId=691126,注意vc2015需卸载)
[global]
index-url=https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=pypi.tuna.tsinghua.edu.cn
disable-pip-version-check = true
timeout = 6000
1、安装
c: cd/ md superset cd superset pip install virtualenv #安装python虚拟环境库,py3.7自带,py -3 -m venv venvname virtualenv venv #新建虚拟环境env文件夹 cd env\scripts activate #激活虚拟环境 pip install --upgrade setuptools pip #更新pip,setuptools pip install sasl(http://www.lfd.uci.edu/~gohlke/pythonlibs/#sasl) cryptography #安装库 pip install click==6.7 colorama==0.3.9 markdown==2.6.11 flask-sqlalchemy==2.1 (numpy) pip install superset==0.27.0 pip install -r c:\requirements.txt (-r requirements-dev.txt) #安装依赖库,从github下载
python3.66不用修改,python3.7中async为关键字,修改3处:
在site-packages\superset\views\cores.js文件内: 修改变量async为async_in
2、启动服务,安装完成后执行以下命令可以使用:
cd env\lib\site-packages\superset\bin
fabmanager create-admin --app superset #创建用户
python superset db upgrade #升级数据库
python superset load_examples #加载例子
python superset init #初始化
python superset runserver -d #启动服务
npm config set registry http://registry.npm.taobao.org/ #设置npm源
npm install yarn -g #安装yarn依赖包管理工具
yarn config set registry http://registry.npm.taobao.org/ #设置yarn源
yarn add webpack@1.14.0 #添加库
yarn add webpack@3.1.2
yarn add cross-env
修改site-packages\superset\package.json: NODE_ENV前加cross-env,4处
yarn install #初始化
npm run dev | more # | 管道命令,方便查看错误,如无错误,可进行在线编译添加echarts
npm run dev 生成目录site-packages\superset\static\assets\dist,在python3.66下集成echarts生成dist目录后,覆盖到python3.7环境的dist,重启服务可以使用。
1、下载echarts,存储site-packages\superset\static\assests\src\exploer\echarts.js
2、site-packages\superset\templates\supersetbase.html: 增加一行:
<script src="/static/assests/src/exploer/controlPanels/echarts.js"></script>
3、site-packages\superset\package.json:
"dependencies": {,"echarts": "^4.1.0",} # 注意','
4、site-packages\superset\static\assets\src\visualizations\index.js,增加:
VIZ_TYPES = { echarts_funnel:'echarts_funnel',}
vizMap = { [VIZ_TYPES.echarts_funnel]:require('./echarts_funnel.js'),}
5、site-packages\superset\viz.py: 增加类class EchartsFunnelViz(BaseViz):{},如下:
class EchartsFunnelViz(BaseViz): # Funnel Chart viz_type = 'echarts_funnel' verbose_name = _('echarts_funnel') is_timeseries = False def get_data(self, df): metric = self.metric_labels[0] df = df.pivot_table( index=self.groupby, values=[metric]) df.sort_values(by=metric, ascending=False,inplace=True) df = df.reset_index() df.columns = ['name','value'] # mydata = [{'name':'p1','value':40},{'name':'p2','value':30},{'name':'p3','value':20}] #测试数据 return df.to_dict(orient='records')
6、site-packages\superset\static\assets\src\explore\vistypes.js:
在export const visTypes:{}增加新类型{ echarts_funnel: {}},如下:
echarts_funnel: { label: t('echarts_funnel'), showOnExplore: true, controlPanelSections: [ { label: t('Query'), expanded: true, controlSetRows: [ ['metric'], ['adhoc_filters'], ['groupby'], ['limit'], ], }, { label: t('Chart Options'), // 这个是额外控制选项 expanded: true, controlSetRows: [ ['pie_label_type'], ['donut', 'show_legend'], ['labels_outside'], ['color_scheme'], ], }, ], },
7、site-packages\superset\static\assets\src\visualizations: 新增加EchartsFunnel.js,如下:
import echarts from 'echarts'; function EchartsFunnel(slice, payload) { //两个参数payload就是 viz.py返回来的数据 slice不不知道从哪⾥里里来的似乎除了了编号没什什么⽤用 const div = d3.select(slice.selector); //这4⾏行行是创建⼀一个div⽤用来绑定给echats做显示的基础画板,并制定slice的id号 const sliceId = 'echarts_slice_' + slice.formData.slice_id; const html = '<div id=' + sliceId + ' style="width:' + slice.width() + 'px;height:' + slice.height() + 'px;"></div>'; div.html(html); // reset const myChart = echarts.init(document.getElementById(sliceId)); const mydata = payload.data; // const mydata = [{'name': 'RDAA201851940000000001', 'value': 1},{'name': 'RDAA201851940000000002', 'value': 1}]; var option = { title: { text: '漏漏⽃斗图', subtext: '图例例' }, tooltip: { trigger: 'item', formatter: "{a} <br/>{b} : {c}%" }, toolbox: { feature: { dataView: {readOnly: false}, restore: {}, saveAsImage: {} } }, legend: { data: mydata.name }, calculable: true, series: [ { name:'漏漏⽃斗图', type:'funnel', left: '10%', top: 60, bottom: 60, width: '80%', min: 0, max: 100, minSize: '0%', maxSize: '100%', sort: 'descending', gap: 2, label: { normal: { show: true, position: 'inside' }, emphasis: { textStyle: { fontSize: 20 } } }, labelLine: { normal: { length: 10, lineStyle: { width: 1, type: 'solid' } } }, itemStyle: { normal: { borderColor: '#fff', borderWidth: 1 } }, data:mydata } ] }; // 使⽤用刚指定的配置项和数据显示图表。 myChart.setOption(option); } // module.exports = EchartsFunnel;
8、增加图片到superset/static/assets/images/viz_thumbnails:
添加名字(echarts_funnel.png)要和vistypes.js中的名字一致
虚拟环境安装pip install --upgrade pip setuptools, pip install sasl(下载sasl文件),
删除C:\incubator-superset-0.29.0rc7\superset\static下的assets
复制C:\incubator-superset-0.29.0rc7\superset\assets到C:\incubator-superset-0.29.0rc7\superset\static下
修改 requirements.txt, 删除cryptography, 并单独安装cryptography和docs\requirements和requirements.txt
修改 requirements-dev.txt, 删除mysqlclient并单独安装, 并单独安装requirements-dev.txt
修改setup.py第18行with io.open('C:\incubator-superset-0.29.0rc7\README.md',
复制C:\incubator-superset-0.29.0rc7\superset文件夹到C:\venv\Lib\site-packages下,
并到C:\venv\Lib\site-packages下执行python c:\incubator-superset-0.29rc7\setup.py
复制.flaskenv到superset目录,并修改为:FLASK_APP=:app FLASK_ENV=development
复制src目录到asset
其它同上.
yarn add python.dotenv , # 加载flask环境变量(.flaskenv),或使用npm命令,下同
yarn install ,# 初始化依赖库
yarn run build , # 可不执行,重新使用webpack打包
npm run dev , # 可实时webpack打包, 在线修改时使用
flask1.0.2:
命令python superset runserver -d 修改为:
在superset目录下执行:
flask run -h 0.0.0.0 -p 8080 --with-threads --reload --debugger
因windows与linux不同,sqllab编辑器执行错误,需修改superset\utils\core.py:
def __enter__(self): try: #signal.signal(signal.SIGALRM, self.handle_timeout) #signal.alarm(self.seconds) pass except ValueError as e: logging.warning("timeout can't be used in the current context") logging.exception(e) def __exit__(self, type, value, traceback): try: #signal.alarm(0) pass except ValueError as e: logging.warning("timeout can't be used in the current context") logging.exception(e)
A、 在superset\viz.py增加
class EchartsCountryMapViz(BaseViz): """A country centric""" viz_type = 'echarts_country_map' verbose_name = _('Echarts Country Map') is_timeseries = False credits = 'From bl.ocks.org By john-guerra' def query_obj(self): qry = super(EchartsCountryMapViz, self).query_obj() qry['metrics'] = [ self.form_data['metric']] qry['groupby'] = [self.form_data['entity']] return qry def get_data(self, df): fd = self.form_data cols = [fd.get('entity')] metric = self.metric_labels[0] cols += [metric] ndf = df[cols] df = ndf df.columns = ['country_id', 'metric'] d = df.to_dict(orient='records') return d
B、 在superset/assets/src/explore/controlPanels/index.js引入
import EchartsCountryMap from './EchartsCountryMap';
export const controlPanelConfigs = { echarts_country_map: EchartsCountryMap, }
C、 在superset/assets/src/explore/controlPanels/下新建EchartsCountryMap.js(左侧选项)
import { t } from '@superset-ui/translation'; export default { controlPanelSections: [ { label: t('Query'), expanded: true, controlSetRows: [ ['entity'], ['metric'], ], }, { label: t('Options'), controlSetRows: [ ['select_country'], ['number_format'], ['linear_color_scheme'], ], }, ], controlOverrides: { entity: { label: t('ISO 3166-2 codes of region/province/department'), description: t('It\'s ISO 3166-2 of your region/province/department in your table. (see documentation for list of ISO 3166-2)'), }, metric: { label: t('Metric'), description: 'Metric to display bottom title', }, linear_color_scheme: { renderTrigger: false, }, }, };
D、 修改superset\static\assets\src\visualizations\presets\MapChartPreset.js,
(一般为CommonChartPreset.js)
import { Preset } from '@superset-ui/core'; import CountryMapChartPlugin from '../CountryMap/CountryMapChartPlugin'; import MapBoxChartPlugin from '../MapBox/MapBoxChartPlugin'; import WorldMapChartPlugin from '../WorldMap/WorldMapChartPlugin'; import EchartsCountryMapChartPlugin from '../EchartsCountryMap/EchartsCountryMapChartPlugin'; export default class MapChartPreset extends Preset { constructor() { super({ name: 'Maps', plugins: [ new CountryMapChartPlugin().configure({ key: 'country_map' }), new MapBoxChartPlugin().configure({ key: 'mapbox' }), new WorldMapChartPlugin().configure({ key: 'world_map' }), new EchartsCountryMapChartPlugin().configure({ key: 'echarts_country_map' }), ], }); } }
E、 复制countryMap,并改名为EchartsCountryMap
⑴修改transformProps.js: 在const {}和return {}新增字段:‘sliceId,’
⑵参照countryMap修改EchartsCountryMap.css文件和EchartsCountryMapChartPlugin.js和EchartsReactCountryMap.js文件(改名).
⑶修改EchartsCountryMap.js: 或使用countryMap.js文件,如:
import echarts from 'echarts'; import PropTypes from 'prop-types'; import d3 from 'd3'; import { format as d3Format } from 'd3-format'; import './EchartsCountryMap.css'; import { getSequentialSchemeRegistry } from '@superset-ui/color'; const propTypes = { data: PropTypes.arrayOf(PropTypes.shape({ country_id: PropTypes.string, metric: PropTypes.number, })), width: PropTypes.number, height: PropTypes.number, country: PropTypes.string, linearColorScheme: PropTypes.string, mapBaseUrl: PropTypes.string, numberFormat: PropTypes.string, sliceId: PropTypes.number, }; function EchartsCountryMap(element, props) { const { data, width, height, country, linearColorScheme, mapBaseUrl = '/static/assets/src/visualizations/EchartsCountryMap/countries', numberFormat, sliceId, } = props; const div = d3.select(element); const sliceID = 'echarts_slice_' + sliceId; const html = '<div id=' + sliceID + ' style="width:' + width + 'px;height:' + height + 'px;"></div>'; div.html(html); // reset const myChart = echarts.init(document.getElementById(sliceID)); const json = data; let oldFeatures = {}; const features = []; const resultFeatures = {}; const colorScale = getSequentialSchemeRegistry().get(linearColorScheme); const colors=colorScale.getColors(); const format = d3Format(numberFormat); let formatter; if (format === 'none') { formatter = ''; } else if (format === 'province') { formatter = '{b}'; } else if (format === 'province+number') { formatter = '{b}:{c}'; } else if (format === 'number') { formatter = '{c}'; } let max = null; let min = null; // const dataAll = []; $.each(json, function (i, item) { const d = {}; d.name = item.country_id; d.value = item.metric; if (max == null || d.value > max) { max = d.value; } if (min == null || d.value < min) { min = d.value; } dataAll.push(d); }); const countryKey = country.toLowerCase(); const url = `${mapBaseUrl}/${countryKey}.geojson`; d3.json(url, function (datas) { oldFeatures = datas.features; // domecharts // var name; $.each(oldFeatures, function (i, oldFeature) { const feature = {}; feature.type = oldFeature.type; feature.id = oldFeature.properties.ID_0; feature.properties = {}; feature.properties.name = oldFeature.properties.NL_NAME_1; if (oldFeature.properties.NL_NAME_1 == null) { feature.properties.name = oldFeature.properties.NAME_1; } else { feature.properties.name = oldFeature.properties.NL_NAME_1; } feature.geometry = oldFeature.geometry; features.push(feature); }); resultFeatures.type = datas.type; resultFeatures.features = features; echarts.registerMap('USA', resultFeatures, { Alaska: { // left: -131, top: 25, width: 15, }, Hawaii: { left: -110, // top: 28, width: 5, }, 'Puerto Rico': { // left: -76, top: 26, width: 2, }, }); const option = { // tooltip: { trigger: 'item', showDelay: 0, transitionDuration: 0.2, formatter(params) { let value = (params.value + '').split('.'); value = value[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,'); return params.seriesName + '<br/>' + params.name + ': ' + value; }, }, // visualMap: { left: 'right', min, max, inRange: { color: colors, }, text: ['High', 'Low'], // calculable: true, }, // toolbox: { show: true, // orient: 'Horizontal', left: 'left', top: 'top', feature: { restore: {}, dataView: { readOnly: false }, saveAsImage: {}, }, }, // series: [ { name: '', type: 'map', roam: true, map: 'USA', // map: fd.select_country.toUpperCase(), label: { normal: { show: true, // textStyle: { color: '#238e23' }, // formatter, }, emphasis: {// show: true, textStyle: { color: '#800080' }, }, }, // itemStyle: { // normal: { // show: true,// // textStyle: {color: "#c71585"},// // formatter: '{c}' // }, // emphasis: {label: {show: true},formatter:'{c}'} // }, // textFixed: { Alaska: [20, -20], }, data: dataAll, }, ], }; // myChart.dispatchAction({ // type:'mapunselected', // seriesId:string, // name:'a', // selected:a // }); myChart.setOption(option); }); } EchartsCountryMap.displayName = 'EchartsCountryMap'; EchartsCountryMap.propTypes = propTypes; export default EchartsCountryMap;
文件位置均在site-packages\superset,修改后需重新编译
A、从后台获取数据 修改viz.py, 增加:
class Gauge(BaseViz):
"""Gauge"""
viz_type = 'gauge'
verbose_name = _('Gauge')
is_timeseries = False
def get_data(self, df):
metric = self.metric_labels[0]
df = df.pivot_table(
index = 1,#self.groupby,
values=[metric])
return df.to_dict(orient='records')
B、控制面板引导文件 修改 \static\assets\src\explore\controlPanels\index.js,增加:
import Gauge from './Gauge';
export const controlPanelConfigs = {
...
gauge: Gauge,
};
C、控制面板 在\static\assets\src\explore\controlPanels\下增加文件gauge.js:
import { t } from '@superset-ui/translation'; export default { controlPanelSections: [ { label: t('Query'), expanded: true, controlSetRows: [ ['metric'], ], }, { label: t('Chart Options'), expanded: true, controlSetRows: [ ], }, ], controlOverrides: { row_limit: { default: 25, }, }, };
D可视化文件配置 在static\assets\src\visualizations\下新建gauge文件夹:
1、新建images文件夹,并存放thumbnail.png图片
2、新建css文件:(图表使用)
.partition { position: relative; } .partition .chart { display: block; margin: auto; font-size: 11px; } .partition rect { stroke: #eee; fill: #aaa; fill-opacity: .8; transition: fill-opacity 180ms linear; cursor: pointer; } .partition rect:hover { fill-opacity: 1; } .partition g text { font-weight: bold; fill: rgba(0, 0, 0, 0.8); } .partition g:hover text { fill: rgba(0, 0, 0, 1); } .partition .partition-tooltip { position: absolute; top: 0; left: 0; opacity: 0; padding: 5px; pointer-events: none; background-color: rgba(255,255,255, 0.75); border-radius: 5px; } .partition-tooltip td { padding-left: 5px; font-size: 11px; }
3、新建GaugeChartPlugin.js, 通过index.js调用本组件。
import { t } from '@superset-ui/translation'; import { ChartMetadata, ChartPlugin } from '@superset-ui/chart'; import transformProps from './transformProps'; import thumbnail from './images/thumbnail.png'; const metadata = new ChartMetadata({ name: t('Gauge'), description: '', thumbnail, }); export default class GaugeChartPlugin extends ChartPlugin { constructor() { super({ metadata, transformProps, loadChart: () => import('./ReactGauge.js'), }); } }
4、新建ReactGauge.js, react引用
import reactify from '../../utils/reactify';
import Component from './Gauge';
export default reactify(Component);
5、新建transformProps.js, 整理可提供的变量参数
export default function transformProps(chartProps) {
const { width, height, datasource, formData, payload } = chartProps;
const {
metrics,
dateTimeFormat,
} = formData;
const { verboseMap } = datasource;
return {
width,
height,
data: payload.data,
metrics,
dateTimeFormat,
};
}
6、新建Gauge.js, 生成图表文件
import echarts from 'echarts'; import d3 from 'd3'; import PropTypes from 'prop-types'; import { hierarchy } from 'd3-hierarchy'; import { CategoricalColorNamespace } from '@superset-ui/color'; import { d3TimeFormatPreset } from '../../modules/utils'; import './Gauge.css'; const propTypes = { width: PropTypes.number, height: PropTypes.number, data: PropTypes.arrayOf(PropTypes.shape({ count: PropTypes.number, })) }; function Gauge(element, props){ // 建立chart图表的容器 const div = d3.select(element); const divId = 'echarts_guage' + "_guage_ID"; var html = `<div id="${divId}" style="width: ${props.width}px;height: ${props.height}px;"></div>`; div.html(html); // 重新加载 // 初始化 var myChart = echarts.init(document.getElementById(divId)); // 图表参数配置 var option = { tooltip : { formatter: "{a} <br/>{c} {b}" }, toolbox: { show: true, feature: { restore: {show: true}, saveAsImage: {show: true} } }, series : [ { name: '速度', type: 'gauge', z: 1, min: 0, max: 50000, splitNumber: 10, radius: '100%', axisLine: { // 坐标轴线 lineStyle: { // 属性lineStyle控制线条样式 width: 25 } }, axisTick: { // 坐标轴小标记 length: 35, // 属性length控制线长 lineStyle: { // 属性lineStyle控制线条样式 color: 'auto' } }, splitLine: { // 分隔线 length: 40, // 属性length控制线长 lineStyle: { // 属性lineStyle(详见lineStyle)控制线条样式 color: 'auto' } }, axisLabel: { backgroundColor: 'auto', borderRadius: 2, color: '#eee', padding: 10, textShadowBlur: 2, textShadowOffsetX: 1, textShadowOffsetY: 1, textShadowColor: '#222' }, title : { // 其余属性默认使用全局文本样式,详见TEXTSTYLE fontWeight: 'bolder', fontSize: 40, fontStyle: 'italic', }, detail : { // 其余属性默认使用全局文本样式,详见TEXTSTYLE formatter: function (value) { value = (value + '').split('.'); value.length < 2 && (value.push('00')); return ('00' + value[0]).slice(-2) + '.' + (value[1] + '00').slice(0, 2);}, fontWeight: 'bolder', borderRadius: 3, backgroundColor: '#444', borderColor: '#aaa', shadowBlur: 5, shadowColor: '#333', shadowOffsetX: 0, shadowOffsetY: 3, borderWidth: 2, textBorderColor: '#000', textBorderWidth: 2, textShadowBlur: 2, textShadowColor: '#fff', textShadowOffsetX: 0, textShadowOffsetY: 0, fontFamily: 'Arial', width: 100, color: '#eee', rich: {} }, data:[{value: props.data[0].count, name: 'km/h'}] } ] }; // 参数加载 myChart.setOption(option); }; Gauge.displayName = 'Gauge'; Gauge.propTypes = propTypes; export default Gauge;
1,修改config.py: PUBLIC_ROLE_LIKE_GAMMA = True
2, 网页admin登录superset,安全>用户列表>修改public,增加
all datasource access on all_datasource_access
all database access on all_database_access
3, superset\bin下,执行python superset init,初始化用户角色和权限
4,到看板页面,分享相应看板的链接。
5,修改config.py:BABEL_DEFAULT_LOCALE = 'zh'
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。