@gen.coroutine
def QueryFollowed(client, obj_store, user_id, device_id, request):
  """Queries all viewpoints followed by the current user. Supports a limit and a start key
  for pagination.
  """
  start_key = request.get('start_key', None)
  limit = request.get('limit', None)

  followed = yield gen.Task(Followed.RangeQuery,
                            client,
                            hash_key=user_id,
                            range_desc=None,
                            limit=limit,
                            col_names=['viewpoint_id'],
                            excl_start_key=start_key)

  # Get the viewpoint associated with each follower object.
  last_key = followed[-1].sort_key if len(followed) > 0 else None

  viewpoint_keys = [db_client.DBKey(f.viewpoint_id, None) for f in followed]
  follower_keys = [db_client.DBKey(user_id, f.viewpoint_id) for f in followed]
  viewpoints, followers = yield [gen.Task(Viewpoint.BatchQuery, client, viewpoint_keys, None, must_exist=False),
                                 gen.Task(Follower.BatchQuery, client, follower_keys, None, must_exist=False)]

  # Formulate the viewpoints list into a dict for JSON output.
  # NOTE: If we ever add content to the viewpoint data being returned here, filtering out that content
  #       if the requester doesn't have view access to it should be considered.
  response = {'viewpoints': [_MakeViewpointMetadataDict(v, f, obj_store)
                             for v, f in zip(viewpoints, followers)
                             if v is not None]}
  util.SetIfNotNone(response, 'last_key', last_key)

  logging.info('QUERY FOLLOWED: user: %d, device: %d, %d viewpoints, start key %s, last key %s' %
               (user_id, device_id, len(response['viewpoints']), start_key,
                response.get('last_key', 'None')))

  raise gen.Return(response)
dataset/ETHPy150Open viewfinderco/viewfinder/backend/www/service.py/QueryFollowed/original