Final touches on getting decent database support

This commit is contained in:
Maxime 2015-08-08 15:03:36 +00:00
parent 9e227494ca
commit 3321a56782
3 changed files with 49 additions and 11 deletions

View File

@ -41,6 +41,8 @@ class Database(Model, AuditMixin):
database_name = Column(String(256), unique=True)
sqlalchemy_uri = Column(String(1024))
baselink = "datasourcemodelview"
def __repr__(self):
return self.database_name
@ -59,11 +61,16 @@ class Table(Model, Queryable, AuditMixin):
__tablename__ = 'tables'
id = Column(Integer, primary_key=True)
table_name = Column(String(256), unique=True)
main_datetime_column_id = Column(Integer, ForeignKey('table_columns.id'))
main_datetime_column = relationship(
'TableColumn', foreign_keys=[main_datetime_column_id])
default_endpoint = Column(Text)
database_id = Column(Integer, ForeignKey('dbs.id'))
database = relationship(
'Database', backref='tables', foreign_keys=[database_id])
baselink = "tableview"
@property
def name(self):
return self.table_name
@ -151,7 +158,7 @@ class Table(Model, Queryable, AuditMixin):
"SELECT\n"
" {select_exprs}\n"
"FROM {self.table_name}\n"
"{limiting_join}\n"
"{limiting_join}"
"WHERE\n"
" {where_clause}\n"
"GROUP BY\n"
@ -221,6 +228,8 @@ class TableColumn(Model, AuditMixin):
filterable = Column(Boolean, default=False)
description = Column(Text, default='')
def __repr__(self):
return self.column_name
class Cluster(Model, AuditMixin):
__tablename__ = 'clusters'
@ -350,6 +359,7 @@ class Datasource(Model, AuditMixin, Queryable):
timeseries_limit=15, row_limit=None):
qry_start_dttm = datetime.now()
query_str = ""
aggregations = {
m.metric_name: m.json_obj
for m in self.metrics if m.metric_name in metrics
@ -409,6 +419,7 @@ class Datasource(Model, AuditMixin, Queryable):
}],
}
client.groupby(**pre_qry)
query_str += json.dumps(client.query_dict, indent=2) + "\n"
df = client.export_pandas()
if not df is None and not df.empty:
dims = qry['dimensions']
@ -435,9 +446,12 @@ class Datasource(Model, AuditMixin, Queryable):
qry['limit_spec'] = None
client.groupby(**qry)
query_str += json.dumps(client.query_dict, indent=2)
df = client.export_pandas()
return QueryResult(
df=df, query="", duration=datetime.now() - qry_start_dttm)
df=df,
query=query_str,
duration=datetime.now() - qry_start_dttm)
#class Metric(Model, AuditMixin):

View File

@ -20,6 +20,7 @@ form input.form-control {
max-width: 350px;
//width: 350px;
}
</style>
{% endblock %}
{% block content_fluid %}
@ -30,7 +31,7 @@ form input.form-control {
{% if datasource.description %}
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="bottom" title="{{ datasource.description }}"></i>
{% endif %}
<a href="/datasourcemodelview/edit/{{ datasource.id }}">
<a href="/{{ datasource.baselink }}/edit/{{ datasource.id }}">
<i class="fa fa-edit"></i>
</a>
</h3>
@ -39,11 +40,20 @@ form input.form-control {
<form id="query" method="GET" style="display: none;">
<div>{{ form.viz_type.label }}: {{ form.viz_type(class_="form-control select2") }}</div>
<div>{{ form.metrics.label }}: {{ form.metrics(class_="form-control select2") }}</div>
<div>{{ form.granularity.label }}: {{ form.granularity(class_="form-control select2_free_granularity") }}</div>
<div>{{ form.granularity.label }}
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right"
title="Supports natural language time as in '10 seconds', '1 day' or '1 week'"
id="blah"></i>
{{ form.granularity(class_="form-control select2_free_granularity") }}</div>
<div class="row">
<div class="form-group">
<div class="col-xs-6">{{ form.since.label }}: {{ form.since(class_="form-control select2_free_since") }}</div>
<div class="col-xs-6">{{ form.until.label }}: {{ form.until(class_="form-control select2_free_until") }}</div>
<div class="col-xs-6">{{ form.since.label }}
<i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right"
title="Supports natural language time as in '1 day ago', '28 days' or '3 years'"
id="blah"></i>
{{ form.since(class_="form-control select2_free_since") }}</div>
<div class="col-xs-6">{{ form.until.label }}
{{ form.until(class_="form-control select2_free_until") }}</div>
</div>
</div>
<div>{{ form.groupby.label }}: {{ form.groupby(class_="form-control select2") }}</div>
@ -70,16 +80,14 @@ form input.form-control {
<button type="button" class="btn btn-primary" id="druidify">Druidify!</button>
<button type="button" class="btn btn-default" id="bookmark">Bookmark</button>
<hr style="margin-bottom: 0px;">
<img src="{{ url_for("static", filename="panoramix.png") }}" width=250>
<img src="{{ url_for("static", filename="tux_panoramix.png") }}" width=250>
</form><br>
</div>
<div class="col-md-9">
<h3>{{ viz.verbose_name }}
<span class="label label-success">{{ "{0:0.2f}".format(results.duration.total_seconds()) }} s</span>
<span class="label label-info" data-html="true"
title="<code><pre>{{ results.query }}</pre></code>"
data-toggle="tooltip" data-placement="bottom" >query</span>
<span class="label label-info btn" data-toggle="modal" data-target="#query_modal">query</span>
</h3>
<hr/>
{% block viz %}
@ -98,6 +106,22 @@ form input.form-control {
{% endif %}
</div>
</div>
<div class="modal fade" id="query_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Query</h4>
</div>
<div class="modal-body">
<pre>{{ results.query }}</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block tail_js %}

View File

@ -124,7 +124,7 @@ class TableView(ModelView, DeleteMixin):
datamodel = SQLAInterface(models.Table)
list_columns = ['table_link', 'database']
add_columns = ['table_name', 'database', 'default_endpoint']
edit_columns = add_columns
edit_columns = ['table_name', 'database', 'main_datetime_column', 'default_endpoint']
related_views = [TableColumnInlineView, SqlMetricInlineView]
def post_insert(self, table):