Commit e07a457c authored by Malcolm Tredinnick's avatar Malcolm Tredinnick
Browse files

Fixed #7096 -- The simplifications in [7461] weren't complete. They broke

multi-component exclude() calls. Fixed that.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@7493 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent a1e4b15f
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -895,9 +895,15 @@ class Query(object):
        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. If 'trim' is True, we
        automatically trim the final join group (used internally when
        constructing nested queries).
        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'
@@ -1001,7 +1007,6 @@ class Query(object):

        self.where.add((alias, col, field, lookup_type, value), connector)
        if negate:
            self.where.negate()
            for alias in join_list:
                self.promote_alias(alias)
            if final > 1 and lookup_type != 'isnull':
@@ -1039,12 +1044,12 @@ class Query(object):
                self.where.start_subtree(connector)
                self.add_q(child, used_aliases)
                self.where.end_subtree()
                if q_object.negated:
                    self.where.children[-1].negate()
            else:
                self.add_filter(child, connector, q_object.negated,
                        can_reuse=used_aliases)
            connector = q_object.connector
        if q_object.negated:
            self.where.negate()
        if subtree:
            self.where.end_subtree()

+19 −0
Original line number Diff line number Diff line
@@ -658,5 +658,24 @@ Bug #7098 -- Make sure semi-deprecated ordering by related models syntax still
works.
>>> Item.objects.values('note__note').order_by('queries_note.note', 'id')
[{'note__note': u'n2'}, {'note__note': u'n3'}, {'note__note': u'n3'}, {'note__note': u'n3'}]

Bug #7096 -- Make sure exclude() with multiple conditions continues to work.
>>> Tag.objects.filter(parent=t1, name='t3').order_by('name')
[<Tag: t3>]
>>> Tag.objects.exclude(parent=t1, name='t3').order_by('name')
[<Tag: t1>, <Tag: t2>, <Tag: t4>, <Tag: t5>]
>>> Item.objects.exclude(tags__name='t1', name='one').order_by('name').distinct()
[<Item: four>, <Item: three>, <Item: two>]
>>> Item.objects.filter(name__in=['three', 'four']).exclude(tags__name='t1').order_by('name')
[<Item: four>, <Item: three>]

More twisted cases, involving nested negations.
>>> Item.objects.exclude(~Q(tags__name='t1', name='one'))
[<Item: one>]
>>> Item.objects.filter(~Q(tags__name='t1', name='one'), name='two')
[<Item: two>]
>>> Item.objects.exclude(~Q(tags__name='t1', name='one'), name='two')
[<Item: four>, <Item: one>, <Item: three>]

"""}