如何使用GraphQL查询查询Tableau元数据API ?



我能够使用REST API很好地登录(没有证书验证)。然而,当我查询元数据API时,我得到的只是来自graphQL GUI的html/javascript。有没有人知道我如何正确地设置我的查询来检索与/metadata/graphQL上的GUI中显示的相同的信息?

下面是我的登录代码:

import requests
import json
url = "https://<tableau-server-name>/api/3.8/auth/signin"
payload = json.dumps({
  "credentials": {
    "personalAccessTokenName": "<my login token>",
    "personalAccessTokenSecret": "<my token value>",
    "site": {
      "contentUrl": ""
    }
  }
})
headers = {
  'Accept': 'application/json',
  'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload, verify=False)
response = json.loads(response.text)
    
print(response)
site_id = response['credentials']['site']['id']
user_id = response['credentials']['user']['id']
token = response['credentials']['token']
headers['X-tableau-auth']=token

我得到一个很好的json响应与授权令牌,我可以传递给后续调用:

{'credentials': {'site': {'id': '<site-id>', 'contentUrl': ''}, 'user': {'id': '<my-user-id>'}, 'token': '<my-user-token>'}}

我对元数据api的下一个调用,这里是问题开始的地方:

import requests
import json
url = "https://<tableau-server-name>/metadata/graphql/"
payload="{"query":"query getAllTables {\r\n  workbooks (filter: {id: \"<workbook id>"\"}) {\r\n\t\tname\r\n    dashboards {\r\n      id\r\n      name\r\n      sheets {\r\n        id\r\n        name\r\n      \tdatasourceFields {\r\n          id \r\n          name\r\n          __typename\r\n          ...on CalculatedField {\r\n            formula\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n}","variables":{}}"
headers = {
  ''X-tableau-auth'': token,
  'Accept': 'application/json',
  'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)

响应是:

<!DOCTYPE html>
<html xmlns:ng="" xmlns:tb="">
<head ng-csp>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport"
        content="initial-scale=1, maximum-scale=2, width=device-width, height=device-height, viewport-fit=cover">
    <meta name="format-detection" content="telephone=no">
    <meta name="vizportal-config" data-buildId="2020_2_164_widw5sl5zoo" data-staticAssetsUrlPrefix="">
    <link href="vendors-vizportal.css?c5da2e24bb179cf9a5dd" rel="stylesheet">
    <link href="vizportal.css?c5da2e24bb179cf9a5dd" rel="stylesheet">
    <script type="text/javascript" src="/javascripts/api/tableau-2.min.js?c5da2e24bb179cf9a5dd"></script>
    <script type="text/javascript" src="jquery.min.js?c5dasdfasdfcf9a5dd"></script>
    <script type="text/javascript" src="angular.min.js?cadfasdff9a5dd"></script>
    <script type="text/javascript" src="angular-cookies.min.js?cadfasdfsacf9a5dd"></script>
    <script type="text/javascript" src="angular-sanitize.min.js?casdfasdfasdfb179cf9a5dd"></script>
    <script type="text/javascript" src="rsa.js?c5da2easdfasdfasfasdfdd"></script>
    <script type="text/javascript" src="underscore-min.js?adfasghdfhfdgdfacf9a5dd"></script>
    <script type="text/javascript" src="q.min.js?casdfdsfa9a5dd"></script>
    <script type="text/javascript" src="canvas-to-blob.min.js?c5sdfasdfasdfafa5dd"></script>
    <script type="text/javascript" src="js.cookie.js?c5adsfasdf9a5dd"></script>
    <script type="text/javascript" src="mousetrap.js?c5djdfghjrhfcff9a5dd"></script>
    <script type="text/javascript" src="core.min.js?c5dahkfghjfghj9a5dd"></script>
    <script type="text/javascript" src="vendors-vizportal.js?c5da2e24bwtertcf9a5dd"></script>
    <script type="text/javascript" src="vizportal.js?c5da2e2dfghdfgha5dd"></script>
</head>
<body class="tb-body">
    <div class="tb-app" ng-app="VizPortalRun" id="ng-app" tb-window-resize>
        <tb:app></tb:app>
        <tb:react-toaster></tb:react-toaster>
        <script type="text/ng-template" id="inline_stackedElement.html">
            <div class="tb-absolute" tb-window-resize tb-left="left" tb-top="top" tb-right="right" tb-bottom="bottom" tb-visible="visible" tb-overflow-y="overflowY"></div>
      </script>
        <tb:stacked-elements></tb:stacked-elements>
    </div>
</body>

通过比较,我希望查询返回json与适当的响应我的graphql查询,我在graphql GUI中测试。

我正在运行的graphQL查询在这里:

query getAllFields {
  workbooks (filter: {id: "<workbook-id>"}){
      embeddedDatasources {
    fields {
      id
      name
      ...on CalculatedField{
        formula
      }
    }
    name
    id
  }
    
  }
}

我遇到了同样的问题,但通过对GraphQL UI的调用进行逆向工程解决了这个问题。而不是

https:///元数据/graphql/

你需要使用

https:///relationship-service-war graphql

用于GraphQL查询。

我的认证看起来像这样:

import requests, json
server_name = "<tableau-server-name>"
api_version = "<tableau-api-version>"
site_url_id = "<tableau-site-url>"
personal_access_token_name = "<your-personal-token-name>"
personal_access_token_secret = "<your-personal-token-secret>"
signin_url = f"https://{server_name}/api/{api_version}/auth/signin"
payload = { "credentials": { "personalAccessTokenName": personal_access_token_name, "personalAccessTokenSecret": personal_access_token_secret, "site": {"contentUrl": site_url_id }}}
headers = {
    'accept': 'application/json',
    'content-type': 'application/json'
}
req = requests.post(signin_url, json=payload, headers=headers, verify=False)
response = json.loads(req.content)
token = response["credentials"]["token"]
site_id = response["credentials"]["site"]["id"]
headers['X-tableau-auth'] = token

GraphQL查询可以使用以下代码:

query = """
query tableauUsers {
  tableauUsers {
    id
  }
}
"""
url = f'https://{server_name}/relationship-service-war/graphql'
request_body = {'query': query}
response = requests.post(url, headers=headers, json=request_body, verify=False)
dma_views_response = json.loads(response.content)

我也遇到过这个问题,直到我意识到url需要包含"api">

url = "https://<tableau-server-name>/api/metadata/graphql/"

最新更新