def get_cached_row(row, index_start, using,  klass_info, offset=0):
    """
    Helper function that recursively returns an object with the specified
    related attributes already populated.

    This method may be called recursively to populate deep select_related()
    clauses.

    Arguments:
         * row - the row of data returned by the database cursor
         * index_start - the index of the row at which data for this
           object is known to start
         * offset - the number of additional fields that are known to
           exist in row for `klass`. This usually means the number of
           annotated results on `klass`.
        * using - the database alias on which the query is being executed.
         * klass_info - result of the get_klass_info function
    """
    if klass_info is None:
        return None
    klass, field_names, field_count, related_fields, reverse_related_fields, pk_idx = klass_info

    fields = row[index_start : index_start + field_count]
    # If the pk column is None (or the Oracle equivalent ''), then the related
    # object must be non-existent - set the relation to None.
    if fields[pk_idx] == None or fields[pk_idx] == '':
        obj = None
    elif field_names:
        obj = klass(**dict(zip(field_names, fields)))
    else:
        obj = klass(*fields)

    # If an object was retrieved, set the database state.
    if obj:
        obj._state.db = using
        obj._state.adding = False

    # Instantiate related fields
    index_end = index_start + field_count + offset
    # Iterate over each related object, populating any
    # select_related() fields
    for f, klass_info in related_fields:
        # Recursively retrieve the data for the related object
        cached_row = get_cached_row(row, index_end, using, klass_info)
        # If the recursive descent found an object, populate the
        # descriptor caches relevant to the object
        if cached_row:
            rel_obj, index_end = cached_row
            if obj is not None:
                # If the base object exists, populate the
                # descriptor cache
                setattr(obj, f.get_cache_name(), rel_obj)
            if f.unique and rel_obj is not None:
                # If the field is unique, populate the
                # reverse descriptor cache on the related object
                setattr(rel_obj, f.related.get_cache_name(), obj)

    # Now do the same, but for reverse related objects.
    # Only handle the restricted case - i.e., don't do a depth
    # descent into reverse relations unless explicitly requested
    for f, klass_info in reverse_related_fields:
        # Recursively retrieve the data for the related object
        cached_row = get_cached_row(row, index_end, using, klass_info)
        # If the recursive descent found an object, populate the
        # descriptor caches relevant to the object
        if cached_row:
            rel_obj, index_end = cached_row
            if obj is not None:
                # If the field is unique, populate the
                # reverse descriptor cache
                setattr(obj, f.related.get_cache_name(), rel_obj)
            if rel_obj is not None:
                # If the related object exists, populate
                # the descriptor cache.
                setattr(rel_obj, f.get_cache_name(), obj)
                # Now populate all the non-local field values on the related
                # object. If this object has deferred fields, we need to use
                # the opts from the original model to get non-local fields
                # correctly.
                opts = rel_obj._meta
                if getattr(rel_obj, '_deferred'):
                    opts = opts.proxy_for_model._meta
                for rel_field, rel_model in opts.get_fields_with_model():
                    if rel_model is not None:
                        setattr(rel_obj, rel_field.attname, getattr(obj, rel_field.attname))
                        # populate the field cache for any related object
                        # that has already been retrieved
                        if rel_field.rel:
                            try:
                                cached_obj = getattr(obj, rel_field.get_cache_name())
                                setattr(rel_obj, rel_field.get_cache_name(), cached_obj)
                            except __HOLE__:
                                # Related object hasn't been cached yet
                                pass
    return obj, index_end
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/django-1.5/django/db/models/query.py/get_cached_row