Hi @Maile_Lucks,
@Phil_Seeman is correct we’ve enabled pagination for our python client libraries by default.
See: “The pagination feature is enabled by default.”
What this means is that in the response we return a python collection (PageIterator) object. With this collection you can simply use the response as part of a for loop to extract the data and the library will auto fetch pages for you. This is why the offset token is obstract. If you would like to get the offset token back and implement your own pagination you can disable the auto-pagination feature in the client configuration (See: 2: Globally - Disable pagination behavior for all requests - Set return_page_iterator to False)
From the code snippet that you shared, it looks like you are using v5.0.X version of our client library.
Here’s some sample code using the python-asana (v5.0.3) to get you started:
SCENARIO SETUP:
- You have a project (
<YOUR_PROJECT_GID>
) with 1000 tasks
SCENARIO 1: Auto Pagination [ENABLED]:
import asana
from asana.rest import ApiException
from pprint import pprint
configuration = asana.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
api_client = asana.ApiClient(configuration)
# create an instance of the API class
tasks_api_instance = asana.TasksApi(api_client)
project_gid = "<YOUR_PROJECT_GID>"
opts = {}
try:
# Get tasks from a project
tasks = tasks_api_instance.get_tasks_for_project(project_gid, opts)
for task in tasks:
pprint(task)
except ApiException as e:
print("Exception when calling TasksApi->get_tasks_for_project: %s\n" % e)
SAMPLE OUTPUT:
{'gid': '123',
'name': 'task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'}
{'gid': '456',
'name': 'task 2',
'resource_subtype': 'default_task',
'resource_type': 'task'}
{'gid': '789',
'name': 'task 3',
'resource_subtype': 'default_task',
'resource_type': 'task'}
{'gid': '101112',
'name': 'task 4',
'resource_subtype': 'default_task',
'resource_type': 'task'}
.
.
.
{'gid': '131415',
'name': 'task 1000',
'resource_subtype': 'default_task',
'resource_type': 'task'}
Each task in the loop is an individual task that you can do something with it in the for loop.
If you want to do something with the entire list of tasks instead of iterating through the collection one by one it might make sense to have the for loop store each value in a list.
SCENARIO 2: Auto Pagination [DISABLED]:
import asana
from asana.rest import ApiException
from pprint import pprint
configuration = asana.Configuration()
configuration.access_token = '<YOUR_ACCESS_TOKEN>'
configuration.return_page_iterator = False # THIS IS HOW YOU DISABLED THE AUTO PAGINATION
api_client = asana.ApiClient(configuration)
# create an instance of the API class
tasks_api_instance = asana.TasksApi(api_client)
project_gid = "<YOUR_PROJECT_GID>"
opts = {
'limit': 1,
}
try:
# Get tasks from a project
response = tasks_api_instance.get_tasks_for_project(project_gid, opts)
pprint(response)
except ApiException as e:
print("Exception when calling TasksApi->get_tasks_for_project: %s\n" % e)
SAMPLE OUTPUT:
{
'data': [
{
'gid': '123',
'name': 'task 1',
'resource_subtype': 'default_task',
'resource_type': 'task'
}
],
'next_page': {
'offset': 'eyJ0eXAiOiJKVxoESLCJhbGciOiJIUzI1NiJ9.eyJib3JkZXJfcmFuayI6IltcIlZcIixcIjlaWVg1STg3NTFFRlwiLDEyMDYzMDE0MzkzNzc3MTJdIiwiaWF0IjoxNzA2MDM0MjEyLCJleHAiOjE3MDYwMzUxMTJ9.DGIPuHAV5AUgvSFa2EhyzVkaCZpWW4s2d42nY-fgIhk',
'path': '/projects/0987/tasks?limit=1&offset=eyJ0eXAiOiJKVxoESLCJhbGciOiJIUzI1NiJ9.eyJib3JkZXJfcmFuayI6IltcIlZcIixcIjlaWVg1STg3NTFFRlwiLDEyMDYzMDE0MzkzNzc3MTJdIiwiaWF0IjoxNzA2MDM0MjEyLCJleHAiOjE3MDYwMzUxMTJ9.DGIPuHAV5AUgvSFa2EhyzVkaCZpWW4s2d42nY-fgIhk',
'uri': 'https://app.asana.com/api/1.0/projects/0987/tasks?limit=1&offset=eyJ0eXAiOiJKVxoESLCJhbGciOiJIUzI1NiJ9.eyJib3JkZXJfcmFuayI6IltcIlZcIixcIjlaWVg1STg3NTFFRlwiLDEyMDYzMDE0MzkzNzc3MTJdIiwiaWF0IjoxNzA2MDM0MjEyLCJleHAiOjE3MDYwMzUxMTJ9.DGIPuHAV5AUgvSFa2EhyzVkaCZpWW4s2d42nY-fgIhk'
}
}
Since this approach disabled auto pagination we return the next_page
param in the response with the offset
so that you can handle pagination on your own.
On another note, I noticed that you specified 'opt_pretty': True
in your opt_fields. This is not necessary with the client library since it returns a dict or object. Additionally, from our docs we state that: “This will take extra time and increase the response size so it is advisable only to use this during debugging.”