def aggregateKey(ob, view_name='', request=None, request_names=(),
                 local_keys=None):
    """ Return a key to be used when retrieving or inserting a cache entry.

    o 'ob' is the object for whom the key is desired.

    o 'view_name' must be a string.

    o 'request' must be a mapping.

    o 'request_names' must be a sorted list of keys to be included in the key
      from 'request'

    o 'local_keys' is a mapping or None.
    """
    path = '/'.join(ob.getPhysicalPath())
    request_index = []
    local_index = []
    if request is None:
        request = {}
    if local_keys is None:
        local_keys = {}

    for key in request_names:
        val = request.get(key, '')
        request_index.append('%s:%s' % (str(key), str(val)))

    for key, val in local_keys.items():
        local_index.append('%s:%s' % (str(key), str(val)))

    full_key = '|'.join((path, str(view_name),
                         ','.join(request_index),
                         ','.join(sorted(local_index))))

    # Memcache does not like  blank spaces in keys
    return full_key.replace(' ', '_')