SDK API
The VIKTOR SDK API can be accessed using the api_v1 module and is built on top of the REST API. It provides access to many of the relevant requests through an even developer-friendlier Python interface and takes care of more complicated parts such as 'pagination', 'filtering by reference', and 'object serialization'. We therefore strongly recommend using the SDK API wherever possible.
The following resources are available in the SDK API:
Workspaces
Entity types
Entities
Revisions
Current user
It is possible to use the SDK API in 3 scenarios:
- Within a workspace (nothing needed)
- Cross-workspace (token needed)
- From an external script (token and environment needed).
Within a workspace
If you want to use the SDK API module from within the context of a workspace, it is as simple as instantiating the
API
class using VIKTOR's api_v1 module:
import viktor as vkt
api = vkt.api_v1.API()
...
entity = api.get_entity(1) # the current workspace is automatically selected
Current workspace and entity
The workspace_id
of the current workspace, and entity_id
and entity_name
of the current entity are sent
along within all view-methods and callback-functions. The workspace_id
/ entity_id
can be used to construct the
current workspace/entity object, from which you can, for example, navigate to relatives within a view-method:
import viktor as vkt
class Controller(vkt.Controller):
@vkt.DataView("Data")
def calculate_view(self, params, entity_id, entity_name, workspace_id, **kwargs):
current_entity = vkt.api_v1.API().get_entity(entity_id)
parent = current_entity.parent()
parent_params = parent.last_saved_params
# do something with parent_params
return vkt.DataResult(...)
Or a callback-function in the parametrization:
import viktor as vkt
def get_options(params, entity_id, entity_name, workspace_id, **kwargs):
current_entity = vkt.api_v1.API().get_entity(entity_id)
parent = current_entity.parent()
parent_params = parent.last_saved_params
# do something with parent_params
return [...]
class Parametrization(vkt.Parametrization):
field = vkt.OptionField(..., options=get_options)
Performance
Within a single job (see app code execution flow for the possible triggers of a job) the results of API calls are temporarily stored (memoized). This means that multiple calls to the same entity only require a single request in the background. This is particularly handy for option functions:
import viktor as vkt
def get_options1_from_parent(params, entity_id, workspace_id, **kwargs):
parent = vkt.api_v1.API().get_entity(entity_id).parent()
parent_params = parent.last_saved_params
# get options1 from parent_params
...
def get_options2_from_parent(params, entity_id, workspace_id, **kwargs):
parent = vkt.api_v1.API().get_entity(entity_id).parent()
parent_params = parent.last_saved_params
# get options2 from parent_params
...
class Parametrization(vkt.Parametrization):
option1 = vkt.OptionField('Option 1', options=get_options1_from_parent)
option2 = vkt.OptionField('Option 2', options=get_options2_from_parent)
Bypassing user access restrictions
If not used properly, (confidential) information which SHOULD NOT be accessible to a user may leak (e.g. by including confidential data in a view, the data is visible to users with access to that view). Please consider the following when using this flag:
- Make sure the app's admin is aware that the code circumvents certain permissions at specific places.
- Make sure to test the implementation thoroughly, to ensure no confidential data is leaked.
Some applications have user restrictions that limit access to certain entities or entity types. For example, if a user does not have permission to read some entity data, the code will also NOT be able to reach this data through an API call when run by the same user.
In some cases it is desirable to restrict user access to a certain entity but have access within the code nonetheless.
An example is the case of a global settings entity that consists of confidential pricing data, which should be
inaccessible for users but accessible for the code to calculate costs. For these cases a privileged
flag can be used:
-
Configure
viktor.config.toml
to make use of the privileged api. This serves as an additional layer of security/awareness.enable_privileged_api = true
-
Use the
privileged
flag on the relevant API call.settings_entity = api.get_root_entities(entity_type_names=['Settings'], privileged=True)[0]
Cross-workspace
If you want to use the SDK API module from one workspace to access data from a different workspace, you can instantiate
the API
class using VIKTOR's api_v1 module and include your
Personal Access Token:
import viktor as vkt
import os
api = vkt.api_v1.API(token=os.environ["TOKEN"])
...
workspace = api.get_workspace(4)
entity = workspace.get_entity(1)
From an external script
If you want to use the SDK API from an external python script (e.g. Jupyter Notebook), make sure to first install the VIKTOR SDK using pip:
pip install viktor
In your python script, you can now instantiate the API
class using VIKTOR's api_v1 module. You
will need to provide some additional authentication-related information:
- Your VIKTOR environment url (the location where your data is stored, e.g.
cloud.viktor.ai
orcompany.us1.viktor.ai
) - Your Personal Access Token
import viktor as vkt
import os
api = vkt.api_v1.API(token=os.environ["TOKEN"], environment="cloud.us1.viktor.ai")
...
workspace = api.get_workspace(3)
entity = workspace.get_entity(1)