samedi 29 novembre 2014

Django génère des requêtes différentes pour exclure avec Q et recherche de filtre simple - Stack Overflow


There is a simplified scheme of my models:


class A(Model):
name = CharField()

class B(Model):
a = models.ForeignKey(A, related_name='b', editable=False, null=False)
valid = models.NullBooleanField(default=None)

So django generates two different queries for following statements:


1) Exclude with Q object


A.objects.filter().exclude(Q(b__valid=True))
SELECT a.name FROM a INNER JOIN b ON (a.id = b.a_id) WHERE NOT (b.valid = True)

2) Exclude with field lookup


A.objects.filter().exclude(b__valid=True)
SELECT a.name FROM a WHERE NOT
(a.id IN
(SELECT U1.a_id FROM b U1 WHERE
(U1.valid = True and U1.a_id IS NOT NULL)))

Is this normal behavior? It produces different queries and in result we can get different items from database. For example we have following database tables:


A
id name
1 Seagull
2 Weasel
3 Deer

B
id a_id valid
1 1 1
1 1 0

First statement will return 1-Seagull object and second statement will return empty queryset. It doesn't look like correct behavior.



There is a simplified scheme of my models:


class A(Model):
name = CharField()

class B(Model):
a = models.ForeignKey(A, related_name='b', editable=False, null=False)
valid = models.NullBooleanField(default=None)

So django generates two different queries for following statements:


1) Exclude with Q object


A.objects.filter().exclude(Q(b__valid=True))
SELECT a.name FROM a INNER JOIN b ON (a.id = b.a_id) WHERE NOT (b.valid = True)

2) Exclude with field lookup


A.objects.filter().exclude(b__valid=True)
SELECT a.name FROM a WHERE NOT
(a.id IN
(SELECT U1.a_id FROM b U1 WHERE
(U1.valid = True and U1.a_id IS NOT NULL)))

Is this normal behavior? It produces different queries and in result we can get different items from database. For example we have following database tables:


A
id name
1 Seagull
2 Weasel
3 Deer

B
id a_id valid
1 1 1
1 1 0

First statement will return 1-Seagull object and second statement will return empty queryset. It doesn't look like correct behavior.


0 commentaires:

Enregistrer un commentaire