superset/app/views.py

163 lines
4.9 KiB
Python
Raw Normal View History

2015-07-16 20:55:36 -04:00
from datetime import timedelta
import logging
2015-07-20 19:29:16 -04:00
import json
2015-07-16 20:55:36 -04:00
2015-07-20 19:29:16 -04:00
from flask import request, redirect, flash, Response
2015-07-15 13:12:32 -04:00
from flask.ext.appbuilder.models.sqla.interface import SQLAInterface
from flask.ext.appbuilder import ModelView, CompactCRUDMixin, BaseView, expose
2015-07-27 17:16:18 -04:00
from app import appbuilder, db, models, viz, utils, app
2015-07-23 02:17:51 -04:00
from flask.ext.appbuilder.security.decorators import has_access, permission_name
2015-07-15 13:12:32 -04:00
import config
2015-07-27 01:25:32 -04:00
from pydruid.client import doublesum
from wtforms.validators import ValidationError
def validate_json(form, field):
try:
json.loads(field.data)
except Exception as e:
raise ValidationError("Json isn't valid")
2015-07-15 13:12:32 -04:00
2015-07-15 13:12:32 -04:00
class ColumnInlineView(CompactCRUDMixin, ModelView):
datamodel = SQLAInterface(models.Column)
2015-07-15 20:38:03 -04:00
edit_columns = [
2015-07-21 14:56:05 -04:00
'column_name', 'description', 'datasource', 'groupby',
'count_distinct', 'sum', 'min', 'max']
2015-07-15 20:38:03 -04:00
list_columns = [
'column_name', 'type', 'groupby', 'count_distinct',
'sum', 'min', 'max']
2015-07-15 13:12:32 -04:00
can_delete = False
2015-07-22 19:21:46 -04:00
page_size = 100
def post_update(self, col):
col.generate_metrics()
def post_update(self, col):
col.generate_metrics()
2015-07-15 13:12:32 -04:00
appbuilder.add_view_no_menu(ColumnInlineView)
2015-07-15 20:38:03 -04:00
class MetricInlineView(CompactCRUDMixin, ModelView):
datamodel = SQLAInterface(models.Metric)
list_columns = ['metric_name', 'verbose_name', 'metric_type' ]
edit_columns = [
2015-07-21 14:56:05 -04:00
'metric_name', 'description', 'verbose_name', 'metric_type',
'datasource', 'json']
2015-07-15 20:38:03 -04:00
add_columns = [
'metric_name', 'verbose_name', 'metric_type', 'datasource', 'json']
2015-07-22 19:21:46 -04:00
page_size = 100
validators_columns = {
'json': [validate_json],
}
2015-07-15 20:38:03 -04:00
appbuilder.add_view_no_menu(MetricInlineView)
2015-07-15 13:12:32 -04:00
class DatasourceModelView(ModelView):
datamodel = SQLAInterface(models.Datasource)
2015-07-21 14:56:05 -04:00
list_columns = ['datasource_link', 'owner', 'is_featured', 'is_hidden']
2015-07-15 20:38:03 -04:00
related_views = [ColumnInlineView, MetricInlineView]
edit_columns = [
2015-07-21 14:56:05 -04:00
'datasource_name', 'description', 'owner', 'is_featured', 'is_hidden',
2015-07-15 20:38:03 -04:00
'default_endpoint']
2015-07-15 13:12:32 -04:00
page_size = 100
2015-07-27 01:25:32 -04:00
base_order = ('datasource_name', 'asc')
2015-07-15 13:12:32 -04:00
def post_insert(self, datasource):
datasource.generate_metrics()
def post_update(self, datasource):
datasource.generate_metrics()
2015-07-15 13:12:32 -04:00
appbuilder.add_view(
DatasourceModelView,
"Datasources",
icon="fa-cube",
category_icon='fa-envelope')
2015-07-27 17:16:18 -04:00
@app.route('/health')
def health():
return "OK"
@app.route('/ping')
def ping():
return "OK"
2015-07-15 13:12:32 -04:00
class Panoramix(BaseView):
2015-07-23 02:17:51 -04:00
@has_access
@permission_name('datasources')
2015-07-15 13:12:32 -04:00
@expose("/datasource/<datasource_name>/")
def datasource(self, datasource_name):
2015-07-15 20:38:03 -04:00
viz_type = request.args.get("viz_type")
2015-07-15 13:12:32 -04:00
datasource = (
db.session
.query(models.Datasource)
.filter_by(datasource_name=datasource_name)
.first()
)
2015-07-15 20:38:03 -04:00
if not viz_type and datasource.default_endpoint:
return redirect(datasource.default_endpoint)
if not viz_type:
viz_type = "table"
2015-07-15 13:12:32 -04:00
obj = viz.viz_types[viz_type](
datasource,
form_data=request.args, view=self)
2015-07-20 19:29:16 -04:00
if request.args.get("json"):
return Response(
json.dumps(obj.get_query(), indent=4),
status=200,
mimetype="application/json")
2015-07-15 13:12:32 -04:00
if obj.df is None or obj.df.empty:
return obj.render_no_data()
return obj.render()
2015-07-23 02:17:51 -04:00
@has_access
@permission_name('refresh_datasources')
2015-07-15 13:12:32 -04:00
@expose("/refresh_datasources/")
2015-07-15 20:38:03 -04:00
def refresh_datasources(self):
2015-07-15 13:12:32 -04:00
import requests
endpoint = (
"http://{COORDINATOR_HOST}:{COORDINATOR_PORT}/"
"{COORDINATOR_BASE_ENDPOINT}/datasources"
).format(**config.__dict__)
datasources = json.loads(requests.get(endpoint).text)
for datasource in datasources:
2015-07-16 20:55:36 -04:00
try:
models.Datasource.sync_to_db(datasource)
except Exception as e:
logging.exception(e)
logging.error("Failed at syncing " + datasource)
2015-07-15 13:12:32 -04:00
flash("Refreshed metadata from Druid!", 'info')
return redirect("/datasourcemodelview/list/")
2015-07-27 01:25:32 -04:00
@expose("/autocomplete/<datasource>/<column>/")
def autocomplete(self, datasource, column):
client = utils.get_pydruid_client()
top = client.topn(
datasource=datasource,
granularity='all',
intervals='2013-10-04/2020-10-10',
aggregations={"count": doublesum("count")},
dimension=column,
metric='count',
threshold=1000,
)
values = sorted([d[column] for d in top[0]['result']])
return json.dumps(values)
2015-07-15 13:12:32 -04:00
appbuilder.add_view_no_menu(Panoramix)
appbuilder.add_link(
"Refresh Metadata",
href='/panoramix/refresh_datasources/',
category='Admin',
icon="fa-cogs")
2015-07-15 20:38:03 -04:00
#models.Metric.__table__.drop(db.engine)
2015-07-15 13:12:32 -04:00
db.create_all()