apache / superset

Apache Superset is a Data Visualization and Data Exploration Platform
https://superset.apache.org/
Apache License 2.0
62.86k stars 13.89k forks source link

/api/v1/dashboard/{id_or_slug}/copy with "duplicate_slices" = true not working because The "json_metadata" take from /api/v1/dashboard/{id_or_slug} doesn't have "positions" #29871

Open Qambitions opened 3 months ago

Qambitions commented 3 months ago

Bug description

Description

When i call the "/api/v1/dashboard/{dashboard_id}/copy/" API, with the duplicate_slices is true, I receive this error. Here is my code and the error. And when i come to the code and check. When i come to the code and check the code need the "positions" fields as input. However, the api dont allow to put this fields.

Code and bug notification

Screenshot 2024-08-06 143605

        dashboard_id  = 1
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.access_token}",
            "X-CSRFToken": self.csrf_token
        }

        dashboard_response = requests.get(f"{superset_url}/api/v1/dashboard/{dashboard_id}", 
                                headers=headers, cookies=self.cookies)
        dashboard_data = dashboard_response.json()["result"]
        json_meta = dashboard_data.get("json_metadata", "")
        json_meta = json.loads(json_meta)
        # json_meta["position_json"] = dashboard_data.get("position_json", "")
        reuqest_payload = {
            "dashboard_title": "intergrate_test",
            "duplicate_slices": True,
            "json_metadata":json.dumps(json_meta)
        }
        payload_json = json.dumps(reuqest_payload)
        # r = session.post(f'{superset_url}/api/v1/dashboard/{dashboard_id}/copy/', data=payload_json)
        r = requests.post(f'{superset_url}/api/v1/dashboard/{dashboard_id}/copy/', json=reuqest_payload,
                                headers=headers, cookies=self.cookies)
        print(r.json())

These part of code you should check and change

image

How to reproduce the bug

  1. using "{superset_url}/api/v1/dashboard/{dashboard_id}" API to get the json_metadata
  2. take it the parameter of '{superset_url}/api/v1/dashboard/{dashboard_id}/copy/' API code.txt
  3. you can use this for easy to check,

Screenshots/recordings

No response

Superset version

master / latest-dev

Python version

3.9

Node version

16

Browser

Chrome

Additional context

No response

Checklist

dosubot[bot] commented 3 months ago

Hello, @Qambitions! I'm here to help you with any bugs, questions, or contributions you have for the repository. Let's tackle this issue together!

To resolve the KeyError for the key 'positions' when calling the "/api/v1/dashboard/{dashboard_id}/copy/" API with duplicate_slices set to true, you need to ensure that the positions key is included in the json_metadata of the request payload before making the API call.

Here's how you can modify your code to include the positions key:

  1. Fetch the position_json from the dashboard data.
  2. Add the position_json to the json_metadata.

Here's the updated code:

import json
import requests

dashboard_id = 1
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {self.access_token}",
    "X-CSRFToken": self.csrf_token
}

# Fetch the dashboard data
dashboard_response = requests.get(f"{superset_url}/api/v1/dashboard/{dashboard_id}", 
                                  headers=headers, cookies=self.cookies)
dashboard_data = dashboard_response.json()["result"]

# Extract and update json_metadata
json_meta = dashboard_data.get("json_metadata", "")
json_meta = json.loads(json_meta)
json_meta["positions"] = dashboard_data.get("position_json", "")

# Prepare the request payload
request_payload = {
    "dashboard_title": "intergrate_test",
    "duplicate_slices": True,
    "json_metadata": json.dumps(json_meta)
}

# Make the copy API call
r = requests.post(f'{superset_url}/api/v1/dashboard/{dashboard_id}/copy/', 
                  json=request_payload, headers=headers, cookies=self.cookies)
print(r.json())

This code ensures that the positions key is included in the json_metadata when making the API call to /api/v1/dashboard/{dashboard_id}/copy/, preventing the KeyError [1].

To continue talking to Dosu, mention @dosu.

Qambitions commented 3 months ago

I have check the solutions @dosu. bot and the code return the {'message': {'json_metadata': [{'positions': ['Not a valid mapping type.']}]}} error.

dosubot[bot] commented 3 months ago

To resolve the error {'message': {'json_metadata': [{'positions': ['Not a valid mapping type.']}]}}, you need to ensure that the positions key in the json_metadata is correctly formatted as a valid mapping type (i.e., a dictionary).

Here's how you can modify your code to ensure the positions key is correctly formatted:

  1. Fetch the position_json from the dashboard data.
  2. Parse the position_json to ensure it is a valid dictionary.
  3. Add the parsed position_json to the json_metadata.

Here's the updated code:

import json
import requests

dashboard_id = 1
headers = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {self.access_token}",
    "X-CSRFToken": self.csrf_token
}

# Fetch the dashboard data
dashboard_response = requests.get(f"{superset_url}/api/v1/dashboard/{dashboard_id}", 
                                  headers=headers, cookies=self.cookies)
dashboard_data = dashboard_response.json()["result"]

# Extract and update json_metadata
json_meta = dashboard_data.get("json_metadata", "")
json_meta = json.loads(json_meta)

# Ensure positions is a valid mapping type
positions = dashboard_data.get("position_json", "{}")
positions = json.loads(positions) if isinstance(positions, str) else positions
json_meta["positions"] = positions

# Prepare the request payload
request_payload = {
    "dashboard_title": "intergrate_test",
    "duplicate_slices": True,
    "json_metadata": json.dumps(json_meta)
}

# Make the copy API call
r = requests.post(f'{superset_url}/api/v1/dashboard/{dashboard_id}/copy/', 
                  json=request_payload, headers=headers, cookies=self.cookies)
print(r.json())

This code ensures that the positions key is included in the json_metadata as a valid dictionary, which should resolve the error [1][2][3].

To continue talking to Dosu, mention @dosu.

Qambitions commented 3 months ago

I'm ensure that Superset current version dont allow to add the "positions" into json_metadata. that why its return {'message': {'json_metadata': [{'positions': ['Not a valid mapping type.']}]}} error.