Custom fields on tasks are bulky and hard to use
BBI-YggyKing opened this issue · 2 comments
I hope I am missing something here, and apologies if this isn't appropriate to raise as a GitHub issue, feel free to send me elsewhere if there's a better forum for this.
I have just started to use the Asana API. I am retrieving tasks as follows, so far so good:
task_fields = ['name', 'completed', 'assignee', 'completed_at']
tasks = client.tasks.find_by_project(project_id, opt_fields=task_fields)
Now I want to retrieve a specific custom field, which leads to two questions:
- Is there a way to request which custom fields I want to retrieve?
- Is there a simple way to retrieve the value of a specific field from the returned object?
At present I have added 'custom_fields'
to the list of task_fields
, which retrieves ALL the custom fields. And not just the fields, but all their metadata as well. We have a number of enum fields, and so the specification of all the metadata ends up as 500 lines of pretty-printed json, most of which is duplicated for every task. This seems inefficient, though perhaps under the hood things are cached?
Now that I have the custom fields, I want the value of a specific field for a particular task. Now, task['custom_fields']
is an array, so I need to search the array by name until I find what I'm looking for, then retrieve the corresponding value. It feels like there should be a better way than this:
time_spent = 0
for field in task['custom_fields']:
if field['name'] == "Time Spent (days)":
time_spent = field['number_value']
Information and advice welcomed with thanks! 😅
When I wrote that I wasn't aware of using paths in opt_fields
, but I don't think it helps, since Time Spent (days)
isn't a key, and number_value
isn't unique.
Hi @BBI-YggyKing, apologies for the late reply. To answer your questions:
1: Is there a way to request which custom fields I want to retrieve?
Unfortunately we do not have a way to request which custom fields you want to retrieve. The custom fields property on a task is an array of object so it will return an array of custom field objects (See task schema). You can however use paths (“Selecting fields”) to select what fields on the custom field objects you want to return. Note when using our path feature it will always return a gid of the selected resource.
So for example, if you specify assignee.name
in the path it will return the gid
of the assignee and their name
and ignore the other properties like resource_type
that would have been returned if the path feature was not used.
import os
import asana
from pprint import pprint
client = asana.Client.access_token(os.environ['ASANA_PERSONAL_ACCESS_TOKEN'])
tasks = client.tasks.get_tasks_for_project(
'<YOUR_PROJECT_GID>',
opt_fields=[
'assignee.name'
]
)
This will return something like:
[{'assignee': {'gid': '1201938574638920', 'name': 'example@user.com'},'gid': '1203019405968385'}]
Notice that in the task schema if you expand the assignee
property you see gid
, resource_type
, and name
since we specified assignee.name
we will get the name
property back + the gid
since gid
will be returned by default.
2: Is there a simple way to retrieve the value of a specific field from the returned object?
As far as I know there is no efficient way to retrieve the value of a specific field from the returned object. Because custom fields on a task is a list of custom field objects you will have to loop through each custom field on the task response to find the particular custom field that you are looking for. I would recommend that you change your if
condition check to look at the GID of the custom field rather than the name. This is because if someone changes the name of the custom field within Asana (UI) then this condition will fail.
Here’s some sample code that wraps this together:
import os
import asana
from pprint import pprint
client = asana.Client.access_token(os.environ['ASANA_PERSONAL_ACCESS_TOKEN'])
tasks = client.tasks.get_tasks_for_project(
‘<YOUR_PROJECT_GID>’,
opt_fields=[
'name',
'custom_fields.name',
'custom_fields.number_value',
'custom_fields.type'
]
)
for task in tasks:
time_spent = 0
for field in task['custom_fields']:
if field['gid'] == '<YOUR_CUSTOM_FIELD_GID>':
time_spent = field['number_value']
print(time_spent)
The returned tasks
response will look like the following:
[{'custom_fields': [{
'gid': '1233333333333332',
'name': 'Priority',
'type': 'enum'
},
{'gid': '1233333333333333',
'name': 'Time Spent (days)',
'number_value': 1,
'type': 'number'
}],
'gid': '1203000000000000',
'name': 'task 1'},
{'custom_fields': [{
'gid': '1233333333333332',
'name': 'Priority',
'type': 'enum'
},
{'gid': '1233333333333333',
'name': 'Time Spent (days)',
'number_value': None,
'type': 'number'
}],
'gid': '1203000000000001',
'name': 'task 2'}
]
Notice that custom fields that are not of type number
does not return a number_value
value
Also please switch from using client.tasks.find_by_project
to client.tasks.get_tasks_for_project