mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
feat: export databases as a ZIP bundle (#11229)
* Export databases as Zip file * Fix tests * Address comments * Implement mulexport for database * Fix lint * Fix lint
This commit is contained in:
@@ -15,9 +15,12 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from typing import Any, Optional
|
||||
from zipfile import ZipFile
|
||||
|
||||
from flask import g, request, Response
|
||||
from flask import g, request, Response, send_file
|
||||
from flask_appbuilder.api import expose, protect, rison, safe
|
||||
from flask_appbuilder.models.sqla.interface import SQLAInterface
|
||||
from flask_babel import gettext as _
|
||||
@@ -43,6 +46,7 @@ from superset.databases.commands.exceptions import (
|
||||
DatabaseSecurityUnsafeError,
|
||||
DatabaseUpdateFailedError,
|
||||
)
|
||||
from superset.databases.commands.export import ExportDatabasesCommand
|
||||
from superset.databases.commands.test_connection import TestConnectionDatabaseCommand
|
||||
from superset.databases.commands.update import UpdateDatabaseCommand
|
||||
from superset.databases.dao import DatabaseDAO
|
||||
@@ -54,6 +58,7 @@ from superset.databases.schemas import (
|
||||
DatabasePutSchema,
|
||||
DatabaseRelatedObjectsResponse,
|
||||
DatabaseTestConnectionSchema,
|
||||
get_export_ids_schema,
|
||||
SchemasResponseSchema,
|
||||
SelectStarResponseSchema,
|
||||
TableMetadataResponseSchema,
|
||||
@@ -72,6 +77,7 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
|
||||
datamodel = SQLAInterface(Database)
|
||||
|
||||
include_route_methods = RouteMethod.REST_MODEL_VIEW_CRUD_SET | {
|
||||
RouteMethod.EXPORT,
|
||||
"table_metadata",
|
||||
"select_star",
|
||||
"schemas",
|
||||
@@ -653,3 +659,61 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
|
||||
charts={"count": len(charts), "result": charts},
|
||||
dashboards={"count": len(dashboards), "result": dashboards},
|
||||
)
|
||||
|
||||
@expose("/export/", methods=["GET"])
|
||||
@protect()
|
||||
@safe
|
||||
@statsd_metrics
|
||||
@rison(get_export_ids_schema)
|
||||
def export(self, **kwargs: Any) -> Response:
|
||||
"""Export database(s) with associated datasets
|
||||
---
|
||||
get:
|
||||
description: Download database(s) and associated dataset(s) as a zip file
|
||||
parameters:
|
||||
- in: query
|
||||
name: q
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
responses:
|
||||
200:
|
||||
description: A zip file with database(s) and dataset(s) as YAML
|
||||
content:
|
||||
application/zip:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
401:
|
||||
$ref: '#/components/responses/401'
|
||||
404:
|
||||
$ref: '#/components/responses/404'
|
||||
500:
|
||||
$ref: '#/components/responses/500'
|
||||
"""
|
||||
requested_ids = kwargs["rison"]
|
||||
timestamp = datetime.now().strftime("%Y%m%dT%H%M%S")
|
||||
root = f"database_export_{timestamp}"
|
||||
filename = f"{root}.zip"
|
||||
|
||||
buf = BytesIO()
|
||||
with ZipFile(buf, "w") as bundle:
|
||||
try:
|
||||
for file_name, file_content in ExportDatabasesCommand(
|
||||
requested_ids
|
||||
).run():
|
||||
with bundle.open(f"{root}/{file_name}", "w") as fp:
|
||||
fp.write(file_content.encode())
|
||||
except DatabaseNotFoundError:
|
||||
return self.response_404()
|
||||
buf.seek(0)
|
||||
|
||||
return send_file(
|
||||
buf,
|
||||
mimetype="application/zip",
|
||||
as_attachment=True,
|
||||
attachment_filename=filename,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user