Using custom attributes
- Python
- JavaScript
Custom attributes can be written and read from entities using the custom_attributes
property.
The custom_attributes
property provides a similar interface to a dictionary.
Keys can be printed using the keys method:
task['custom_attributes'].keys()
[u'my_text_field']
or access keys and values as items:
print(task['custom_attributes'].items())
[(u'my_text_field', u'some text')]
Read existing custom attribute values:
print(task['custom_attributes']['my_text_field'])
'some text'
Updating a custom attributes can also be done similar to a dictionary:
task['custom_attributes']['my_text_field'] = 'foo'
To query for tasks with a custom attribute, my_text_field
, you can use the key from the configuration:
for task in session.query(
'Task where custom_attributes any '
'(key is "my_text_field" and value is "bar")'
):
print(task['name'])
There are some limitations that are important to be aware of when creating an entity and updating custom attributes in one commit.
The following code does not work:
task = session.create('Task', {
...
'custom_attributes': {
'my_text_field': 'bar',
},
})
session.commit()
Instead, the entity must be created first, then we can set the custom attributes:
task = session.create('Task', {
...
})
task['custom_attributes']['my_text_field'] = 'bar'
session.commit()
After the commit the remote value is not automatically populated. This will cause an extra query to the server when a custom attribute is accessed:
# This will cause a server query.
print(task['custom_attributes']['my_text_field'])
Custom attributes can be written and read from entities using the custom_attributes
property.
Querying custom attributes on a task
const task = (await session.query("select custom_attributes.key, custom_attributes.value from Task limit 1")).data[0];
The resulting data will have the custom attributes as an array of 'ContextCustomAttributeValue' objects, which have key
and value
as keys.
To find the value of a the custom attribute, we can use find on the array:
const key = "customAttributeKey";
const customAttribute = task.custom_attributes.find(x => x.key === key);
const value = customAttribute.value;
If we want to update the value, we need to get the configuration ID of the custom attribute, and update that value:
const configurationId = customAttribute.configuration_id;
await session.update('ContextCustomAttributeValue', [configurationId, task.id],
{
value: "new Value",
key,
entity_id: task.id,
configuration_id: configurationId,
})
To query for tasks with a specific custom attribute value for the key my_text_field
, you can use the any
relationship filter:
const tasksWithTextField = await session.query(
'select name from Task where custom_attributes any (key is "my_text_field" and value is "bar")'
)
Limitations
Expression attributes
Expression attributes are not yet supported and the reported value will always be the non-evaluated expression.
Hierarchical attributes
Hierarchical attributes are not yet fully supported in the API. Hierarchical attributes support both read and write, but when read they are not calculated and instead the [raw] value is returned:
# The hierarchical attribute `my_attribute` is set on Shot but this will not
# be reflected on the children. Instead the raw value is returned.
print(shot['custom_attributes']['my_attribute'])
'foo'
print(task['custom_attributes']['my_attribute'])
None
To work around this limitation it is possible to use the legacy api for hierarchical attributes or to manually query the parents for values and use the first value that is set.
Validation
Custom attributes are validated on the ftrack server before persisted. The validation will check that the type of the data is correct for the custom attribute.
- number -
int
orfloat
- text -
str
orunicode
- enumerator -
list
- boolean -
bool
- date -
datetime.datetime
ordatetime.date
If the value set is not valid a ftrack_api.exception.ServerError
is raised with debug information:
shot['custom_attributes']['fstart'] = 'test'
Traceback (most recent call last):
...
ftrack_api.exception.ServerError: Server reported error: ValidationError(Custom attribute value for "fstart" must be of type number. Got "test" of type <type 'unicode'>)