qs.exclude(something=123) should not exclude objects with something=None
from django.db import models
class A(models.Model):
str = models.CharField(null=True, blank=True, max_length=20)
def __unicode__(self):
return self.str or 'None'
In [1]: from test import models
In [2]: a = models.A.objects.create(str='a')
In [3]: b = models.A.objects.create(str=None)
In [4]: models.A.objects.exclude(str='a')
Out[4]: []
In [5]: models.A.objects.filter(str__isnull=True).exclude(str='a')
Out[5]: []
In [6]: models.A.objects.all()
Out[6]: [<A: a>, <A: None>]
Expected output:
Out[4]: [<A: None>]
Out[5]: [<A: None>]
Tested with trunk & queryset-refactor.
Change History
(9)
| Keywords: |
qsrf-cleanup added
|
| Has patch: |
set
|
| Needs documentation: |
set
|
| Needs tests: |
set
|
| Owner: |
changed from nobody to anonymous
|
| Patch needs improvement: |
set
|
| Status: |
new → assigned
|
| Owner: |
anonymous removed
|
| Status: |
assigned → new
|
| Triage Stage: |
Unreviewed → Accepted
|
| Resolution: |
→ fixed
|
| Status: |
new → closed
|
I can reproduce this (r7573 + postgres).
It could be solved easyly by making
__exactNULL-safe:%s IS NOT DISTINCT FROMhttp://postgresql.com.cn/docs/8.3/static/functions-comparison.html%s <=>http://dev.mysql.com/doc/refman/4.1/en/comparison-operators.htmlBut I couldn't find something comparable for sqlite and oracle (except for
(a=b OR (a IS NULL AND b IS NULL))) - and I don't know if anything depends onNULL==1=NULL==NOT (1=NULL)and would break withFALSE==1<=>NULL!=NOT(1<=>NULL)==TRUE.While trying to come up with a patch I found some dead code that should handle the issue for related tables (see patch, missing
[JOIN_TYPE]inif final > 1 ...) and just threw in a similar weakening for the unjoined case.This will be a backwards incompatible change.