Traceback (most recent call last):
File "/data/Superset/superset-0.25.6/superset/views/core.py", line 1107, in generate_json
payload = viz_obj.get_payload()
File "/data/Superset/superset-0.25.6/superset/viz.py", line 329, in get_payload
payload['data'] = self.get_data(df)
File "/data/Superset/superset-0.25.6/superset/viz.py", line 628, in get_data
margins=self.form_data.get('pivot_margins'),
File "/home/.local/share/virtualenvs/Superset-VKnIdCi7/lib/python2.7/site-packages/pandas/core/frame.py", line 4468, in pivot_table
margins_name=margins_name)
File "/home/.local/share/virtualenvs/Superset-VKnIdCi7/lib/python2.7/site-packages/pandas/core/reshape/pivot.py", line 57, in pivot_table
if i not in data:
File "/home/.local/share/virtualenvs/Superset-VKnIdCi7/lib/python2.7/site-packages/pandas/core/generic.py", line 1075, in __contains__
return key in self._info_axis
File "/home/.local/share/virtualenvs/Superset-VKnIdCi7/lib/python2.7/site-packages/pandas/core/indexes/base.py", line 1694, in __contains__
hash(key)
TypeError: unhashable type: 'dict'
解决方案
在PivotTableViz中对于metrics参数改为区分处理即可。
具体实现
class PivotTableViz(BaseViz):
······
def get_data(self, df):
if (
self.form_data.get('granularity') == 'all' and
DTTM_ALIAS in df):
del df[DTTM_ALIAS]
metrics = self.form_data.get('metrics')
values = []
for metric in metrics:
if isinstance(metric, dict):
values.append(metric['label'])
else:
values.append(metric)
df = df.pivot_table(
index=self.form_data.get('groupby'),
columns=self.form_data.get('columns'),
values=values,
aggfunc=self.form_data.get('pandas_aggfunc'),
margins=self.form_data.get('pivot_margins'),
)
······
unsupported format character ''' (0x27) at index 49
Traceback (most recent call last):
File "/data/Superset/superset-0.25.6/superset/sql_lab.py", line 220, in execute_sql
**db_engine_spec.cursor_execute_kwargs)
File "/home/.local/share/virtualenvs/Superset-VKnIdCi7/lib/python2.7/site-packages/MySQLdb/cursors.py", line 238, in execute
query = query % args
ValueError: unsupported format character ''' (0x27) at index 49
from superset.utils import string_to_num
class XYLineViz(DistributionBarViz):
"""A good old xy-line chart"""
viz_type = 'xy_line'
verbose_name = _('XY - Line Chart')
is_timeseries = False
def query_obj(self):
return super(XYLineViz, self).query_obj()
def get_data(self, df):
fd = self.form_data
pt = self.sort_df_values(df)
if fd.get('contribution'):
pt = pt.fillna(0)
pt = pt.T
pt = (pt / pt.sum()).T
chart_data = []
for name, ys in pt.items():
if pt[name].dtype.kind not in 'biufc' or name in self.groupby:
continue
if isinstance(name, string_types):
series_title = name
elif len(self.metrics) > 1:
series_title = ', '.join(name)
else:
l = [str(s) for s in name[1:]] # noqa: E741
series_title = ', '.join(l)
values = []
x_i = 0
import datetime
for i, v in ys.items():
x = i
if isinstance(x, (tuple, list)):
x = ', '.join([text_type(s) for s in x])
if isinstance(x, datetime.date):
x = str(x)
else:
xn = string_to_num(x)
x = xn if xn else text_type(x)
values.append({
'x': x_i,
'y': v,
'label': x
})
x_i = x_i + 1
d = {
'key': series_title,
'values': values,
}
chart_data.append(d)
return chart_data
新增自定义排序机制:图表编辑页面中的 SQL 模块增加 ORDER BY 配置,后台接收此配置并整合到最终执行的SQL中。
效果展示
具体实现
superset/static/assets/src/explore/controls.jsx
where: {
······
},
order_by: {
type: 'TextAreaControl',
label: t('Custom ORDER BY clause'),
default: '',
language: 'sql',
minLines: 2,
maxLines: 10,
offerEditInModal: false,
description: t('The text in this box gets included in your query\'s ORDER BY ' +
'clause. You can include ' +
'complex expression, parenthesis and anything else ' +
'supported by the backend it is directed towards.' +
'Example:{"column1":"desc","column2":"asc"}'
),
},
having: {
······
},
superset/static/assets/src/explore/visTypes.js
superset/connectors/sqla/models.py
def get_sqla_query( # sqla
······
template_processor = self.get_template_processor(**template_kwargs)
db_engine_spec = self.database.db_engine_spec
if not orderby:
orderby = extras.get('orderby', [])
orderby = orderby or []
······
from urllib import quote_plus as urlquote
······
def set_sqlalchemy_uri(self, uri):
conn = sqla.engine.url.make_url(uri.strip())
if conn.password and conn.password != PASSWORD_MASK and not custom_password_store:
# do not over-write the password with the password mask
self.password = urlquote(conn.password)
conn.password = PASSWORD_MASK if conn.password else None
self.sqlalchemy_uri = str(conn) # hides the password
[改进]修复日志记录时间差8小时的问题
背景
Superset使用MySQL管理元数据时,logs表中dttm字段时间与当前时间差8个小时。
解决方案
具体实现
superset/models/core.py
class Log(Model):
······
dttm = Column(DateTime, default=datetime.utcnow)
[改进]改进每次查询新开数据库连接的问题
背景
SQL Editor中每次查询都会新开一条数据库连接,长时间使用会导致出现大量数据库连接。
解决方案
具体实现
superset/sql_lab.py
[修复]修复查询结果导出乱码问题
背景
Superset查询结果导出CSV出现乱码。
解决方案
改为使用 utf-8-sig 编码。
具体实现
superset/config.py
# CSV Options: key/value pairs that will be passed as argument to DataFrame.to_csv method
# note: index option should not be overridden
CSV_EXPORT = {
'encoding': 'utf-8-sig',
}
import ExportResults from './ExportResults';
······
if (this.props.search || this.props.visualize || this.props.csv) {
let csvButton;
if (this.props.csv) {
csvButton = (
);
}
let visualizeButton;
if (this.props.visualize) {
······
superset/views/core.py
@has_access
@expose('/csv//')
@log_this
def csv(self, client_id, file_name):
"""Download the query results as csv."""
logging.info('Exporting CSV file [{}]'.format(client_id))
query = (
db.session.query(Query)
······
response = Response(csv, mimetype='text/csv')
response.headers['Content-Disposition'] = (
'attachment; filename={}.csv'.format(parse.quote(file_name or query.name)))
logging.info('Ready to return response')
return response