server-client-python icon indicating copy to clipboard operation
server-client-python copied to clipboard

View Filters on parameters

Open dawilson23 opened this issue 6 months ago • 6 comments

Describe the bug Filtering on workbook parameters doesn't work. Current workaround is to use the .vf() method and prepend the filter name with "Parameters."

To Reproduce with server.auth.sign_in(tableau_auth): logger.info(f"Signed in to Tableau Server: {SERVER_URL}") view_item = server.views.get_by_id(VIEW_ID) logger.info(f"Fetched view: {view_item.name} (ID: {view_item.id})")

    # Set up image request options
    image_req = TSC.ImageRequestOptions()
    image_req.vf('Parameters.field_name', 'value')

    # Download the image
    server.views.populate_image(view_item, image_req)
    image_data = view_item.image

Results No error is received

Source code -> def append_view_filters(self, params) -> None: for name, value in self.view_filters: params["vf" + name] = value for name, value in self.view_parameters: params[name] = value

Might need to be -> def append_view_filters(self, params) -> None: for name, value in self.view_filters: params["vf" + name] = value for name, value in self.view_parameters: params["vf_Parameters." + name] = value

dawilson23 avatar Jul 09 '25 16:07 dawilson23

Have you tried using .parameters to apply the parameters instead of .vf? .vf is intended for things like quick filters.

jorwoods avatar Jul 09 '25 16:07 jorwoods

Yes and I was unable to successfully get it to work. I had to resort to using .vf and prepending "Parameters." to the name of the parameter. Sorry I shared the work around rather than the code to reproduce.

https://github.com/tableau/server-client-python/blob/master/tableauserverclient/server/request_options.py

this is the current implementation of the class

class _DataExportOptions(RequestOptionsBase):
    def __init__(self, maxage: int = -1):
        super().__init__()
        self.view_filters: list[tuple[str, str]] = []
        self.view_parameters: list[tuple[str, str]] = []
        self.max_age: Optional[int] = maxage
        """
        This setting will affect the contents of the workbook as they are exported.
        Valid language values are tableau-supported languages like de, es, en
        If no locale is specified, the default locale for that language will be used
        """
        self.language: Optional[str] = None

    @property
    def max_age(self) -> int:
        return self._max_age

    @max_age.setter
    @property_is_int(range=(0, 240), allowed=[-1])
    def max_age(self, value):
        self._max_age = value

    def get_query_params(self):
        params = {}
        if self.max_age != -1:
            params["maxAge"] = self.max_age
        if self.language:
            params["language"] = self.language

        self._append_view_filters(params)
        return params

    def vf(self, name: str, value: str) -> Self:
        """Apply a filter based on a column within the view.
        Note that when filtering on a boolean type field, the only valid values are 'true' and 'false'

        For more detail see: https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_concepts_filtering_and_sorting.htm#Filter-query-views

        Parameters
        ----------
        name: str
            The name of the column to filter on

        value: str
            The value to filter on

        Returns
        -------
        Self
            The current object
        """
        self.view_filters.append((name, value))
        return self

    def parameter(self, name: str, value: str) -> Self:
        """Apply a filter based on a parameter within the workbook.
        Note that when filtering on a boolean type field, the only valid values are 'true' and 'false'

        Parameters
        ----------
        name: str
            The name of the parameter to filter on

        value: str
            The value to filter on

        Returns
        -------
        Self
            The current object
        """
        self.view_parameters.append((name, value))
        return self

    def _append_view_filters(self, params) -> None:
        for name, value in self.view_filters:
            params["vf_" + name] = value
        for name, value in self.view_parameters:
            params[name] = value

i believe changing the final line would fix it

params["vf_Parameters." + name] = value

dawilson23 avatar Jul 09 '25 17:07 dawilson23

Thanks @dawilson23. I see the issue now and confirmed the behavior. I will work on a resolution soon.

jorwoods avatar Jul 09 '25 19:07 jorwoods

This shouldn't have changed. What server versions are you seeing it on?

jacalata avatar Aug 01 '25 21:08 jacalata

I saw this on 2023.3.8.

jorwoods avatar Aug 01 '25 21:08 jorwoods

Also tested against the 10ax pod of Cloud. Here is the script I used. Verified that it doesn't behave as expected on the development branch, but does with the fixes in #1633

import os

from dotenv import load_dotenv
import tableauserverclient as TSC

load_dotenv()

server = TSC.Server(os.environ["TABLEAU_SERVER"], use_server_version=True)
auth = TSC.PersonalAccessTokenAuth(os.environ["TOKEN_NAME"], os.environ["TOKEN_SECRET"], site_id=os.environ["TABLEAU_SITE"])
with server.auth.sign_in(auth):
    view = server.views.filter(name="test", workbook_name="Superstore", project_name="Samples")[0]
    opts = TSC.CSVRequestOptions()
    opts.parameter("Check", "sent")
    server.views.populate_csv(view, opts)
    for line in view.csv:
        print(line.decode("utf-8").strip())

jorwoods avatar Aug 01 '25 23:08 jorwoods