1
0
mirror of https://github.com/django/django.git synced 2025-07-06 10:49:17 +00:00

queryset-refactor: Interpret qs.filter(foo=None) to be the same as qs.filter(foo__isnull=True). Refs #2737.

git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6760 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-11-30 02:29:25 +00:00
parent 648a3d87a3
commit a2418176fd
4 changed files with 25 additions and 17 deletions

View File

@ -679,13 +679,13 @@ class Query(object):
else:
lookup_type = parts.pop()
# Interpret '__exact=None' as the sql '= NULL'; otherwise, reject all
# Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
# uses of None as a query value.
# FIXME: Weren't we going to change this so that '__exact=None' was the
# same as '__isnull=True'? Need to check the conclusion of the mailing
# list thread.
if value is None and lookup_type != 'exact':
raise ValueError("Cannot use None as a query value")
if value is None:
if lookup_type != 'exact':
raise ValueError("Cannot use None as a query value")
lookup_type = 'isnull'
value = True
elif callable(value):
value = value()
@ -708,7 +708,8 @@ class Query(object):
alias = join[LHS_ALIAS]
col = join[LHS_JOIN_COL]
if (lookup_type == 'isnull' and value is True):
if lookup_type == 'isnull' and value is True and (len(join_list) > 1 or
len(join_list[0]) > 1):
# If the comparison is against NULL, we need to use a left outer
# join when connecting to the previous model. We make that
# adjustment here. We don't do this unless needed because it's less

View File

@ -1137,7 +1137,12 @@ Examples::
SQL equivalents::
SELECT ... WHERE id = 14;
SELECT ... WHERE id = NULL;
SELECT ... WHERE id IS NULL;
**New in Django development version:** The semantics of ``id__exact=None`` have
changed in the development version. Previously, it was (intentionally)
converted to ``WHERE id = NULL`` at the SQL level, which would never match
anything. It has now been changed to behave the same as ``id__isnull=True``.
iexact
~~~~~~
@ -1367,14 +1372,6 @@ SQL equivalent::
SELECT ... WHERE pub_date IS NULL;
.. admonition:: ``__isnull=True`` vs ``__exact=None``
There is an important difference between ``__isnull=True`` and
``__exact=None``. ``__exact=None`` will *always* return an empty result
set, because SQL requires that no value is equal to ``NULL``.
``__isnull`` determines if the field is currently holding the value
of ``NULL`` without performing a comparison.
search
~~~~~~

View File

@ -80,6 +80,11 @@ None
>>> Article.objects.filter(reporter__isnull=True)
[<Article: Third>]
# We can achieve the same thing by filtering for the case where the reporter is
# None.
>>> Article.objects.filter(reporter=None)
[<Article: Third>]
# Set the reporter for the Third article
>>> r.article_set.add(a3)
>>> r.article_set.all()

View File

@ -24,10 +24,15 @@ __test__ = {'API_TESTS':"""
>>> c2 = Choice(poll=p1, choice='Why Not?')
>>> c2.save()
# Exact query with value None returns nothing (=NULL in sql)
# Exact query with value None returns nothing ("is NULL" in sql, but every 'id'
# field has a value).
>>> Choice.objects.filter(id__exact=None)
[]
Excluding the previous result returns everything.
>>> Choice.objects.exclude(id=None).order_by('id')
[<Choice: Choice: Because. in poll Q: Why? >, <Choice: Choice: Why Not? in poll Q: Why? >]
# Valid query, but fails because foo isn't a keyword
>>> Choice.objects.filter(foo__exact=None)
Traceback (most recent call last):