fix: Better error message for dashboard import (#7621)

Common mistake is trying to import dashboard without creating
datasources first. Currently it causes error 500 with a message

> sqlalchemy.orm.exc.NoResultFound: No row was found for one()

which is difficult to understand.

This commit catches NoResultFound error and returns human readable error
using flash('danger').

Ref: #2992
This commit is contained in:
Maxim Sukharev 2019-07-04 06:52:00 +02:00 committed by Maxime Beauchemin
parent 9b8996038e
commit 2fa071a3ac
3 changed files with 44 additions and 7 deletions

View File

@ -42,6 +42,7 @@ from sqlalchemy import (
)
from sqlalchemy.exc import CompileError
from sqlalchemy.orm import backref, relationship
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.schema import UniqueConstraint
from sqlalchemy.sql import column, literal_column, table, text
from sqlalchemy.sql.expression import Label, TextAsFrom
@ -50,6 +51,7 @@ import sqlparse
from superset import app, db, security_manager
from superset.connectors.base.models import BaseColumn, BaseDatasource, BaseMetric
from superset.db_engine_specs.base import TimestampExpression
from superset.exceptions import DatabaseNotFound
from superset.jinja_context import get_template_processor
from superset.models.annotations import Annotation
from superset.models.core import Database
@ -1005,11 +1007,19 @@ class SqlaTable(Model, BaseDatasource):
)
def lookup_database(table):
return (
db.session.query(Database)
.filter_by(database_name=table.params_dict["database_name"])
.one()
)
try:
return (
db.session.query(Database)
.filter_by(database_name=table.params_dict["database_name"])
.one()
)
except NoResultFound:
raise DatabaseNotFound(
_(
"Database '%(name)s' is not found",
name=table.params_dict["database_name"],
)
)
return import_datasource.import_datasource(
db.session, i_datasource, lookup_database, lookup_sqlatable, import_time

View File

@ -54,3 +54,7 @@ class SupersetTemplateException(SupersetException):
class SpatialException(SupersetException):
pass
class DatabaseNotFound(SupersetException):
status = 400

View File

@ -64,7 +64,11 @@ from superset import (
)
from superset.connectors.connector_registry import ConnectorRegistry
from superset.connectors.sqla.models import AnnotationDatasource, SqlaTable
from superset.exceptions import SupersetException, SupersetSecurityException
from superset.exceptions import (
DatabaseNotFound,
SupersetException,
SupersetSecurityException,
)
from superset.forms import CsvToDatabaseForm
from superset.jinja_context import get_template_processor
from superset.legacy import update_time_range
@ -1441,7 +1445,26 @@ class Superset(BaseSupersetView):
"""Overrides the dashboards using json instances from the file."""
f = request.files.get("file")
if request.method == "POST" and f:
dashboard_import_export.import_dashboards(db.session, f.stream)
try:
dashboard_import_export.import_dashboards(db.session, f.stream)
except DatabaseNotFound as e:
flash(
_(
"Cannot import dashboard: %(db_error)s.\n"
"Make sure to create the database before "
"importing the dashboard.",
db_error=e,
),
"danger",
)
except Exception:
flash(
_(
"An unknown error occurred. "
"Please contact your Superset administrator"
),
"danger",
)
return redirect("/dashboard/list/")
return self.render_template("superset/import_dashboards.html")