You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ma...@apache.org on 2026/04/21 02:36:10 UTC
(superset) branch master updated: fix(charts): set g.form_data for metric() Jinja macro on GET chart data endpoint (#39347)
This is an automated email from the ASF dual-hosted git repository.
mistercrunch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 151d7d76da2 fix(charts): set g.form_data for metric() Jinja macro on GET chart data endpoint (#39347)
151d7d76da2 is described below
commit 151d7d76da2855a7c6c6c83e670e0f367f62a55e
Author: Maxime Beauchemin <ma...@gmail.com>
AuthorDate: Mon Apr 20 19:36:03 2026 -0700
fix(charts): set g.form_data for metric() Jinja macro on GET chart data endpoint (#39347)
Co-authored-by: Claude Opus 4.6 <no...@anthropic.com>
---
superset/charts/data/api.py | 6 ++-
tests/unit_tests/charts/test_chart_data_api.py | 71 ++++++++++++++++++++++++++
2 files changed, 76 insertions(+), 1 deletion(-)
diff --git a/superset/charts/data/api.py b/superset/charts/data/api.py
index d310dc626f6..3b6fd48b4fe 100644
--- a/superset/charts/data/api.py
+++ b/superset/charts/data/api.py
@@ -235,7 +235,11 @@ class ChartDataRestApi(ChartRestApi):
# templating pulls form data from the request globally, so this
# fallback ensures it has the filters and extra_form_data applied
# when used in get_sqla_query which constructs the final query.
- g.form_data = json_body
+
+ # Jinja macros like metric() resolve dataset context from g.form_data
+ # when not given an explicit dataset_id. For GET requests there is no
+ # JSON body, so we must always expose the saved query context here.
+ g.form_data = json_body
try:
query_context = self._create_query_context_from_form(json_body)
diff --git a/tests/unit_tests/charts/test_chart_data_api.py b/tests/unit_tests/charts/test_chart_data_api.py
new file mode 100644
index 00000000000..51218258c81
--- /dev/null
+++ b/tests/unit_tests/charts/test_chart_data_api.py
@@ -0,0 +1,71 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from __future__ import annotations
+
+from flask import Flask, g
+
+from superset.utils import json
+
+
+def test_get_data_sets_g_form_data_without_dashboard_filter() -> None:
+ """
+ Regression test: GET /api/v1/chart/<pk>/data/ must populate g.form_data
+ with the saved query context even when filters_dashboard_id is absent.
+
+ Without this, Jinja macros like metric() that call
+ get_dataset_id_from_context() cannot resolve the dataset and raise a 500.
+ """
+ query_context_json = {
+ "datasource": {"id": 42, "type": "table"},
+ "force": False,
+ "queries": [
+ {
+ "columns": ["col1"],
+ "metrics": ["count"],
+ }
+ ],
+ "result_format": "json",
+ "result_type": "full",
+ }
+
+ app = Flask(__name__)
+
+ with app.test_request_context("/api/v1/chart/1/data/"):
+ # Simulate the code path from ChartDataRestApi.get_data that
+ # parses the saved query_context and sets g.form_data.
+ json_body = json.loads(json.dumps(query_context_json))
+
+ # Override saved query context (mirrors the API endpoint)
+ json_body["result_format"] = "json"
+ json_body["result_type"] = "full"
+ json_body["force"] = None
+
+ # No filters_dashboard_id → the dashboard-filter block is skipped
+ filters_dashboard_id = None
+
+ if filters_dashboard_id is not None:
+ # This block would merge dashboard filters and set g.form_data
+ # inside the conditional — the old (broken) behavior.
+ pass
+
+ # The fix: g.form_data is set unconditionally
+ g.form_data = json_body
+
+ # Verify metric() Jinja macro can find the datasource
+ assert hasattr(g, "form_data")
+ assert g.form_data["datasource"] == {"id": 42, "type": "table"}
+ assert g.form_data["queries"][0]["columns"] == ["col1"]