def get_klass_info(klass, max_depth=0, cur_depth=0, requested=None,
                   only_load=None, local_only=False):
    if max_depth and requested is None and cur_depth > max_depth:
        # We've recursed deeply enough; stop now.
        return None

    if only_load:
        load_fields = only_load.get(klass) or set()
        # When we create the object, we will also be creating populating
        # all the parent classes, so traverse the parent classes looking
        # for fields that must be included on load.
        for parent in klass._meta.get_parent_list():
            fields = only_load.get(parent)
            if fields:
                load_fields.update(fields)
    else:
        load_fields = None

    if load_fields:
        # Handle deferred fields.
        skip = set()
        init_list = []
        # Build the list of fields that *haven't* been requested
        for field, model in klass._meta.get_fields_with_model():
            if field.name not in load_fields:
                skip.add(field.attname)
            elif local_only and model is not None:
                continue
            else:
                init_list.append(field.attname)
        # Retrieve all the requested fields
        field_count = len(init_list)
        if skip:
            klass = deferred_class_factory(klass, skip)
            field_names = init_list
        else:
            field_names = ()
    else:
        # Load all fields on klass

        # We trying to not populate field_names variable for perfomance reason.
        # If field_names variable is set, it is used to instantiate desired fields,
        # by passing **dict(zip(field_names, fields)) as kwargs to Model.__init__ method.
        # But kwargs version of Model.__init__ is slower, so we should avoid using
        # it when it is not really neccesary.
        if local_only and len(klass._meta.local_fields) != len(klass._meta.fields):
            field_count = len(klass._meta.local_fields)
            field_names = [f.attname for f in klass._meta.local_fields]
        else:
            field_count = len(klass._meta.fields)
            field_names = ()

    restricted = requested is not None

    related_fields = []
    for f in klass._meta.fields:
        if select_related_descend(f, restricted, requested, load_fields):
            if restricted:
                next = requested[f.name]
            else:
                next = None
            klass_info = get_klass_info(f.rel.to, max_depth=max_depth, cur_depth=cur_depth+1,
                                        requested=next, only_load=only_load)
            related_fields.append((f, klass_info))

    reverse_related_fields = []
    if restricted:
        for o in klass._meta.get_all_related_objects():
            if o.field.unique and select_related_descend(o.field, restricted, requested,
                                                         only_load.get(o.model), reverse=True):
                next = requested[o.field.related_query_name()]
                klass_info = get_klass_info(o.model, max_depth=max_depth, cur_depth=cur_depth+1,
                                            requested=next, only_load=only_load, local_only=True)
                reverse_related_fields.append((o.field, klass_info))
    if field_names:
        pk_idx = field_names.index(klass._meta.pk.attname)
    else:
        pk_idx = klass._meta.pk_index()

    return klass, field_names, field_count, related_fields, reverse_related_fields, pk_idx
Helper function that recursively returns an information for a klass, to be
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/django-1.5/django/db/models/query.py/get_klass_info