1

Assuming a simple model like this:

class Item(models.Model): 
    name = models.CharField(max_length=10)

class Relation(models.Model):
    item = models.ForeignKey(Item)
    weight = models.IntegerField() 

And a couple of Q objects like this:

some = Q(relation__x__gt=3)
others = Q(relation__x=7)

What is the semantic difference between:

first = Item.objects.filter(some, ~others)

and

second = Item.objects.filter(some).exclude(others) 

NOTE: Querying through the relation appears to be different than querying a single simple object. The SQL generated for the two above queries is different.

Here's the generated SQL for first:

SELECT "item_item"."id", "item_item"."name" 
FROM "item_item" 
INNER JOIN "item_relation" 
ON ("item_item"."id" = "item_relation"."item_id") 
WHERE ("item_relation"."weight" > 3  
  AND NOT ("item_item"."id" IN 
    (SELECT U1."item_id" 
     FROM "item_relation" U1 
     WHERE (U1."weight" = 7  AND U1."item_id" IS NOT NULL))))

And the SQL for second:

SELECT "item_item"."id", "item_item"."name" 
FROM "item_item" 
INNER JOIN "item_relation" 
ON ("item_item"."id" = "item_relation"."item_id") 
INNER JOIN "item_relation" T3 
ON ("item_item"."id" = T3."item_id") 
WHERE ("item_relation"."weight" > 3  AND NOT (T3."weight" = 7 ))
Tomasz Jakub Rup
  • 10,502
  • 7
  • 48
  • 49
slacy
  • 11,397
  • 8
  • 56
  • 61
  • Related question: http://stackoverflow.com/questions/8164675/chaining-multiple-filter-in-django-is-this-a-bug – Etienne Nov 17 '11 at 19:52
  • Per the link in Etienne's comment, it doesn't seem that this behavior is intentional on Django's part; I wouldn't try to read into it as a genuine semantic difference. In practice, you'd probably want to avoid any ambiguity and just &/| your Q's beforehand, and pass a single one into .filter(). – AdamKG Nov 17 '11 at 20:37

0 Answers0