def get_prefetcher(instance, attr):
    """
    For the attribute 'attr' on the given instance, finds
    an object that has a get_prefetch_query_set().
    Returns a 4 tuple containing:
    (the object with get_prefetch_query_set (or None),
     the descriptor object representing this relationship (or None),
     a boolean that is False if the attribute was not found at all,
     a boolean that is True if the attribute has already been fetched)
    """
    prefetcher = None
    attr_found = False
    is_fetched = False

    # For singly related objects, we have to avoid getting the attribute
    # from the object, as this will trigger the query. So we first try
    # on the class, in order to get the descriptor object.
    rel_obj_descriptor = getattr(instance.__class__, attr, None)
    if rel_obj_descriptor is None:
        try:
            rel_obj = getattr(instance, attr)
            attr_found = True
        except __HOLE__:
            pass
    else:
        attr_found = True
        if rel_obj_descriptor:
            # singly related object, descriptor object has the
            # get_prefetch_query_set() method.
            if hasattr(rel_obj_descriptor, 'get_prefetch_query_set'):
                prefetcher = rel_obj_descriptor
                if rel_obj_descriptor.is_cached(instance):
                    is_fetched = True
            else:
                # descriptor doesn't support prefetching, so we go ahead and get
                # the attribute on the instance rather than the class to
                # support many related managers
                rel_obj = getattr(instance, attr)
                if hasattr(rel_obj, 'get_prefetch_query_set'):
                    prefetcher = rel_obj
    return prefetcher, rel_obj_descriptor, attr_found, is_fetched
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/django-1.5/django/db/models/query.py/get_prefetcher