'Add a single filter to the query. The \'filter_expr\' is a pair:
(filter_string, value). E.g. (\'name__contains\', \'fred\')
If \'negate\' is True, this is an exclude() filter. It\'s important to
note that this method does not negate anything in the where-clause
object when inserting the filter constraints. This is because negated
filters often require multiple calls to add_filter() and the negation
should only happen once. So the caller is responsible for this (the
caller will normally be add_q(), so that as an example).
If \'trim\' is True, we automatically trim the final join group (used
internally when constructing nested queries).
If \'can_reuse\' is a set, we are processing a component of a
multi-component filter (e.g. filter(Q1, Q2)). In this case, \'can_reuse\'
will be a set of table aliases that can be reused in this filter, even
if we would otherwise force the creation of new aliases for a join
(needed for nested Q-filters). The set is updated by this method.
If \'process_extras\' is set, any extra filters returned from the table
joining process will be processed. This parameter is set to False
during the processing of extra filters to avoid infinite recursion.'

def add_filter(self, filter_expr, connector=AND, negate=False, trim=False, can_reuse=None, process_extras=True, force_having=False):

    (arg, value) = filter_expr
    parts = arg.split(LOOKUP_SEP)
    if (not parts):
        raise FieldError(('Cannot    parse    keyword    query    %r' % arg))
    lookup_type = 'exact'
    num_parts = len(parts)
    if ((len(parts) > 1) and (parts[(-1)] in self.query_terms) and (arg not in self.aggregates)):
        lookup_model = self.model
        for (counter, field_name) in enumerate(parts):
            try:
                lookup_field = lookup_model._meta.get_field(field_name)
            except FieldDoesNotExist:
                lookup_type = parts.pop()
                break
            if ((counter + 1) < num_parts):
                try:
                    lookup_model = lookup_field.rel.to
                except AttributeError:
                    lookup_type = parts.pop()
                    break
    having_clause = False
    if (value is None):
        if (lookup_type != 'exact'):
            raise ValueError('Cannot    use    None    as    a    query    value')
        lookup_type = 'isnull'
        value = True
    elif callable(value):
        value = value()
    elif isinstance(value, ExpressionNode):
        value = SQLEvaluator(value, self, reuse=can_reuse)
        having_clause = value.contains_aggregate
    if (connections[DEFAULT_DB_ALIAS].features.interprets_empty_strings_as_nulls and (lookup_type == 'exact') and (value == '')):
        value = True
        lookup_type = 'isnull'
    for (alias, aggregate) in self.aggregates.items():
        if (alias in (parts[0], LOOKUP_SEP.join(parts))):
            entry = self.where_class()
            entry.add((aggregate, lookup_type, value), AND)
            if negate:
                entry.negate()
            self.having.add(entry, connector)
            return
    opts = self.get_meta()
    alias = self.get_initial_alias()
    allow_many = (trim or (not negate))
    try:
        (field, target, opts, join_list, last, extra_filters) = self.setup_joins(parts, opts, alias, True, allow_many, allow_explicit_fk=True, can_reuse=can_reuse, negate=negate, process_extras=process_extras)
    except MultiJoin as e:
        self.split_exclude(filter_expr, LOOKUP_SEP.join(parts[:e.level]), can_reuse)
        return
    table_promote = False
    join_promote = False
    if ((lookup_type == 'isnull') and (value is True) and (not negate) and (len(join_list) > 1)):
        self.promote_joins(join_list)
        join_promote = True
    nonnull_comparison = ((lookup_type == 'isnull') and (value is False))
    (col, alias, join_list) = self.trim_joins(target, join_list, last, trim, nonnull_comparison)
    if (connector == OR):
        join_it = iter(join_list)
        table_it = iter(self.tables)
        (next(join_it), next(table_it))
        unconditional = False
        for join in join_it:
            table = next(table_it)
            unconditional = (unconditional or (self.alias_map[join].join_type == self.LOUTER))
            if ((join == table) and (self.alias_refcount[join] > 1)):
                continue
            join_promote = (join_promote or self.promote_joins([join], unconditional))
            if (table != join):
                table_promote = self.promote_joins([table])
            break
        self.promote_joins(join_it, join_promote)
        self.promote_joins(table_it, (table_promote or join_promote))
    if (having_clause or force_having):
        if ((alias, col) not in self.group_by):
            self.group_by.append((alias, col))
        self.having.add((Constraint(alias, col, field), lookup_type, value), connector)
    else:
        self.where.add((Constraint(alias, col, field), lookup_type, value), connector)
    if negate:
        self.promote_joins(join_list)
        if (lookup_type != 'isnull'):
            if (len(join_list) > 1):
                for j_alias in join_list:
                    if (self.alias_map[j_alias].join_type == self.LOUTER):
                        j_col = self.alias_map[j_alias].rhs_join_col
                        assert (j_col is not None)
                        entry = self.where_class()
                        entry.add((Constraint(j_alias, j_col, None), 'isnull', True), AND)
                        entry.negate()
                        self.where.add(entry, AND)
                        break
            if self.is_nullable(field):
                self.where.add((Constraint(alias, col, None), 'isnull', False), AND)
    if (can_reuse is not None):
        can_reuse.update(join_list)
    if process_extras:
        for filter in extra_filters:
            self.add_filter(filter, negate=negate, can_reuse=can_reuse, process_extras=False)
