'Add a join to query_set.
Join looks like this:
(INNER|LEFT) JOIN <join_table> AS <alias>
ON (<this table>.<join_from_key> = <join_table>.<join_key>
and <join_condition>)
:param join_table table to join to
:param join_key field referencing back to this model to use for the join
:param join_condition extra condition for the ON clause of the join
:param join_condition_values values to substitute into join_condition
:param join_from_key column on this model to join from.
:param alias alias to use for for join
:param suffix suffix to add to join_table for the join alias, if no
alias is provided
:param exclude if true, exclude rows that match this join (will use a
LEFT OUTER JOIN and an appropriate WHERE condition)
:param force_left_join - if true, a LEFT OUTER JOIN will be used
instead of an INNER JOIN regardless of other options'

def add_join(self, query_set, join_table, join_key, join_condition='', join_condition_values=(), join_from_key=None, alias=None, suffix='', exclude=False, force_left_join=False):

    join_from_table = query_set.model._meta.db_table
    if (join_from_key is None):
        join_from_key = self.model._meta.pk.name
    if (alias is None):
        alias = (join_table + suffix)
    full_join_key = ((_quote_name(alias) + '.') + _quote_name(join_key))
    full_join_condition = ('%s    =    %s.%s' % (full_join_key, _quote_name(join_from_table), _quote_name(join_from_key)))
    if join_condition:
        full_join_condition += (('    AND    (' + join_condition) + ')')
    if (exclude or force_left_join):
        join_type = query_set.query.LOUTER
    else:
        join_type = query_set.query.INNER
    query_set = self.CustomQuery.convert_query(query_set)
    query_set.query.add_custom_join(join_table, full_join_condition, join_type, condition_values=join_condition_values, alias=alias)
    if exclude:
        query_set = query_set.extra(where=[(full_join_key + '    IS    NULL')])
    return query_set
