Django

Code

Changeset 7493

Show
Ignore:
Timestamp:
04/27/08 23:29:06 (2 months ago)
Author:
mtredinnick
Message:

Fixed #7096 -- The simplifications in [7461] weren't complete. They broke
multi-component exclude() calls. Fixed that.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/models/sql/query.py

    r7477 r7493  
    896896        (filter_string, value). E.g. ('name__contains', 'fred') 
    897897 
    898         If 'negate' is True, this is an exclude() filter. If 'trim' is True, we 
    899         automatically trim the final join group (used internally when 
    900         constructing nested queries). 
     898        If 'negate' is True, this is an exclude() filter. It's important to 
     899        note that this method does not negate anything in the where-clause 
     900        object when inserting the filter constraints. This is because negated 
     901        filters often require multiple calls to add_filter() and the negation 
     902        should only happen once. So the caller is responsible for this (the 
     903        caller will normally be add_q(), so that as an example). 
     904 
     905        If 'trim' is True, we automatically trim the final join group (used 
     906        internally when constructing nested queries). 
    901907 
    902908        If 'can_reuse' is a set, we are processing a component of a 
     
    10021008        self.where.add((alias, col, field, lookup_type, value), connector) 
    10031009        if negate: 
    1004             self.where.negate() 
    10051010            for alias in join_list: 
    10061011                self.promote_alias(alias) 
     
    10401045                self.add_q(child, used_aliases) 
    10411046                self.where.end_subtree() 
    1042                 if q_object.negated: 
    1043                     self.where.children[-1].negate() 
    10441047            else: 
    10451048                self.add_filter(child, connector, q_object.negated, 
    10461049                        can_reuse=used_aliases) 
    10471050            connector = q_object.connector 
     1051        if q_object.negated: 
     1052            self.where.negate() 
    10481053        if subtree: 
    10491054            self.where.end_subtree() 
  • django/trunk/tests/regressiontests/queries/models.py

    r7490 r7493  
    659659>>> Item.objects.values('note__note').order_by('queries_note.note', 'id') 
    660660[{'note__note': u'n2'}, {'note__note': u'n3'}, {'note__note': u'n3'}, {'note__note': u'n3'}] 
     661 
     662Bug #7096 -- Make sure exclude() with multiple conditions continues to work. 
     663>>> Tag.objects.filter(parent=t1, name='t3').order_by('name') 
     664[<Tag: t3>] 
     665>>> Tag.objects.exclude(parent=t1, name='t3').order_by('name') 
     666[<Tag: t1>, <Tag: t2>, <Tag: t4>, <Tag: t5>] 
     667>>> Item.objects.exclude(tags__name='t1', name='one').order_by('name').distinct() 
     668[<Item: four>, <Item: three>, <Item: two>] 
     669>>> Item.objects.filter(name__in=['three', 'four']).exclude(tags__name='t1').order_by('name') 
     670[<Item: four>, <Item: three>] 
     671 
     672More twisted cases, involving nested negations. 
     673>>> Item.objects.exclude(~Q(tags__name='t1', name='one')) 
     674[<Item: one>] 
     675>>> Item.objects.filter(~Q(tags__name='t1', name='one'), name='two') 
     676[<Item: two>] 
     677>>> Item.objects.exclude(~Q(tags__name='t1', name='one'), name='two') 
     678[<Item: four>, <Item: one>, <Item: three>] 
     679 
    661680"""} 
    662681