'Compute the necessary table joins for the passage through the fields
given in \'names\'. \'opts\' is the Options class for the current model
(which gives the table we are starting from), \'alias\' is the alias for
the table to start the joining from.
The \'can_reuse\' defines the reverse foreign key joins we can reuse. It
can be None in which case all joins are reusable or a set of aliases
that can be reused. Note that non-reverse foreign keys are always
reusable when using setup_joins().
If \'allow_many\' is False, then any reverse foreign key seen will
generate a MultiJoin exception.
Return the final field involved in the joins, the target field (used
for any \'where\' constraint), the final \'opts\' value, the joins and the
field path travelled to generate the joins.
The target field is the field containing the concrete value. Final
field can be something different, for example foreign key pointing to
that value. Final field is needed for example in some value
conversions (convert \'obj\' in fk__id=obj to pk val using the foreign
key field for example).'

def setup_joins(self, names, opts, alias, can_reuse=None, allow_many=True):

    joins = [alias]
    (path, final_field, targets, rest) = self.names_to_path(names, opts, allow_many, fail_on_missing=True)
    for join in path:
        opts = join.to_opts
        if join.direct:
            nullable = self.is_nullable(join.join_field)
        else:
            nullable = True
        connection = Join(opts.db_table, alias, None, INNER, join.join_field, nullable)
        reuse = (can_reuse if join.m2m else None)
        alias = self.join(connection, reuse=reuse)
        joins.append(alias)
    return JoinInfo(final_field, targets, opts, joins, path)
