def get_related_selections(self, select, opts=None, root_alias=None, cur_depth=1, requested=None, restricted=None):
    '\n        Fill in the information needed for a select_related query. The current\n        depth is measured as the number of connections away from the root model\n        (for example, cur_depth=1 means we are looking at models with direct\n        connections to the root model).\n        '

    def _get_field_choices():
        direct_choices = (f.name for f in opts.fields if f.is_relation)
        reverse_choices = (f.field.related_query_name() for f in opts.related_objects if f.field.unique)
        return chain(direct_choices, reverse_choices)
    related_klass_infos = []
    if ((not restricted) and self.query.max_depth and (cur_depth > self.query.max_depth)):
        return related_klass_infos
    if (not opts):
        opts = self.query.get_meta()
        root_alias = self.query.get_initial_alias()
    only_load = self.query.get_loaded_field_names()
    fields_found = set()
    if (requested is None):
        if isinstance(self.query.select_related, dict):
            requested = self.query.select_related
            restricted = True
        else:
            restricted = False

    def get_related_klass_infos(klass_info, related_klass_infos):
        klass_info['related_klass_infos'] = related_klass_infos
    for f in opts.fields:
        field_model = f.model._meta.concrete_model
        fields_found.add(f.name)
        if restricted:
            next = requested.get(f.name, {})
            if (not f.is_relation):
                if (next or ((cur_depth == 1) and (f.name in requested))):
                    raise FieldError(("Non-relational field given in select_related: '%s'. Choices are: %s" % (f.name, (', '.join(_get_field_choices()) or '(none)'))))
        else:
            next = False
        if (not select_related_descend(f, restricted, requested, only_load.get(field_model))):
            continue
        klass_info = {'model': f.remote_field.model, 'field': f, 'reverse': False, 'from_parent': False}
        related_klass_infos.append(klass_info)
        select_fields = []
        (_, _, _, joins, _) = self.query.setup_joins([f.name], opts, root_alias)
        alias = joins[(- 1)]
        columns = self.get_default_columns(start_alias=alias, opts=f.remote_field.model._meta)
        for col in columns:
            select_fields.append(len(select))
            select.append((col, None))
        klass_info['select_fields'] = select_fields
        next_klass_infos = self.get_related_selections(select, f.remote_field.model._meta, alias, (cur_depth + 1), next, restricted)
        get_related_klass_infos(klass_info, next_klass_infos)
    if restricted:
        related_fields = [(o.field, o.related_model) for o in opts.related_objects if (o.field.unique and (not o.many_to_many))]
        for (f, model) in related_fields:
            if (not select_related_descend(f, restricted, requested, only_load.get(model), reverse=True)):
                continue
            related_field_name = f.related_query_name()
            fields_found.add(related_field_name)
            (_, _, _, joins, _) = self.query.setup_joins([related_field_name], opts, root_alias)
            alias = joins[(- 1)]
            from_parent = issubclass(model, opts.model)
            klass_info = {'model': model, 'field': f, 'reverse': True, 'from_parent': from_parent}
            related_klass_infos.append(klass_info)
            select_fields = []
            columns = self.get_default_columns(start_alias=alias, opts=model._meta, from_parent=opts.model)
            for col in columns:
                select_fields.append(len(select))
                select.append((col, None))
            klass_info['select_fields'] = select_fields
            next = requested.get(f.related_query_name(), {})
            next_klass_infos = self.get_related_selections(select, model._meta, alias, (cur_depth + 1), next, restricted)
            get_related_klass_infos(klass_info, next_klass_infos)
        fields_not_found = set(requested.keys()).difference(fields_found)
        if fields_not_found:
            invalid_fields = (("'%s'" % s) for s in fields_not_found)
            raise FieldError(('Invalid field name(s) given in select_related: %s. Choices are: %s' % (', '.join(invalid_fields), (', '.join(_get_field_choices()) or '(none)'))))
    return related_klass_infos
Fill in the information needed for a select_related query. The current
depth is measured as the number of connections away from the root model
(for example, cur_depth=1 means we are looking at models with direct
connections to the root model).
def get_related_selections(self, select, opts=None, root_alias=None, cur_depth=1, requested=None, restricted=None):
    '\n        Fill in the information needed for a select_related query. The current\n        depth is measured as the number of connections away from the root model\n        (for example, cur_depth=1 means we are looking at models with direct\n        connections to the root model).\n        '

    def _get_field_choices():
        direct_choices = (f.name for f in opts.fields if f.is_relation)
        reverse_choices = (f.field.related_query_name() for f in opts.related_objects if f.field.unique)
        return chain(direct_choices, reverse_choices)
    related_klass_infos = []
    if ((not restricted) and self.query.max_depth and (cur_depth > self.query.max_depth)):
        return related_klass_infos
    if (not opts):
        opts = self.query.get_meta()
        root_alias = self.query.get_initial_alias()
    only_load = self.query.get_loaded_field_names()
    fields_found = set()
    if (requested is None):
        if isinstance(self.query.select_related, dict):
            requested = self.query.select_related
            restricted = True
        else:
            restricted = False

    def get_related_klass_infos(klass_info, related_klass_infos):
        klass_info['related_klass_infos'] = related_klass_infos
    for f in opts.fields:
        field_model = f.model._meta.concrete_model
        fields_found.add(f.name)
        if restricted:
            next = requested.get(f.name, {})
            if (not f.is_relation):
                if (next or ((cur_depth == 1) and (f.name in requested))):
                    raise FieldError(("Non-relational field given in select_related: '%s'. Choices are: %s" % (f.name, (', '.join(_get_field_choices()) or '(none)'))))
        else:
            next = False
        if (not select_related_descend(f, restricted, requested, only_load.get(field_model))):
            continue
        klass_info = {'model': f.remote_field.model, 'field': f, 'reverse': False, 'from_parent': False}
        related_klass_infos.append(klass_info)
        select_fields = []
        (_, _, _, joins, _) = self.query.setup_joins([f.name], opts, root_alias)
        alias = joins[(- 1)]
        columns = self.get_default_columns(start_alias=alias, opts=f.remote_field.model._meta)
        for col in columns:
            select_fields.append(len(select))
            select.append((col, None))
        klass_info['select_fields'] = select_fields
        next_klass_infos = self.get_related_selections(select, f.remote_field.model._meta, alias, (cur_depth + 1), next, restricted)
        get_related_klass_infos(klass_info, next_klass_infos)
    if restricted:
        related_fields = [(o.field, o.related_model) for o in opts.related_objects if (o.field.unique and (not o.many_to_many))]
        for (f, model) in related_fields:
            if (not select_related_descend(f, restricted, requested, only_load.get(model), reverse=True)):
                continue
            related_field_name = f.related_query_name()
            fields_found.add(related_field_name)
            (_, _, _, joins, _) = self.query.setup_joins([related_field_name], opts, root_alias)
            alias = joins[(- 1)]
            from_parent = issubclass(model, opts.model)
            klass_info = {'model': model, 'field': f, 'reverse': True, 'from_parent': from_parent}
            related_klass_infos.append(klass_info)
            select_fields = []
            columns = self.get_default_columns(start_alias=alias, opts=model._meta, from_parent=opts.model)
            for col in columns:
                select_fields.append(len(select))
                select.append((col, None))
            klass_info['select_fields'] = select_fields
            next = requested.get(f.related_query_name(), {})
            next_klass_infos = self.get_related_selections(select, model._meta, alias, (cur_depth + 1), next, restricted)
            get_related_klass_infos(klass_info, next_klass_infos)
        fields_not_found = set(requested.keys()).difference(fields_found)
        if fields_not_found:
            invalid_fields = (("'%s'" % s) for s in fields_not_found)
            raise FieldError(('Invalid field name(s) given in select_related: %s. Choices are: %s' % (', '.join(invalid_fields), (', '.join(_get_field_choices()) or '(none)'))))
    return related_klass_infos