Fixed #21552 -- Allowed the use of None for the iexact lookup.

Thanks Anubhav Joshi for the documentation.
This commit is contained in:
Denis Moskalets 2013-12-03 13:24:45 +04:00 committed by Tim Graham
parent 2fd7fc134c
commit d4e578d0f6
4 changed files with 17 additions and 4 deletions

View File

@ -1031,7 +1031,7 @@ class Query(object):
# Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
# uses of None as a query value. # uses of None as a query value.
if value is None: if value is None:
if lookup_type != 'exact': if lookup_type not in ('exact', 'iexact'):
raise ValueError("Cannot use None as a query value") raise ValueError("Cannot use None as a query value")
lookup_type = 'isnull' lookup_type = 'isnull'
value = True value = True

View File

@ -2028,9 +2028,15 @@ iexact
Case-insensitive exact match. Case-insensitive exact match.
.. versionchanged:: 1.7
If the value provided for comparision is ``None``, it will be interpreted
as an SQL ``NULL`` (see :lookup:`isnull` for more details).
Example:: Example::
Blog.objects.get(name__iexact='beatles blog') Blog.objects.get(name__iexact='beatles blog')
Blog.objects.get(name__iexact=None)
SQL equivalent:: SQL equivalent::

View File

@ -450,6 +450,9 @@ Models
argument to control whether or not to perform operations in bulk argument to control whether or not to perform operations in bulk
(i.e. using ``QuerySet.update()``). Defaults to ``True``. (i.e. using ``QuerySet.update()``). Defaults to ``True``.
* It is now possible to use ``None`` as a query value for the :lookup:`iexact`
lookup.
Signals Signals
^^^^^^^ ^^^^^^^

View File

@ -12,7 +12,8 @@ class NullQueriesTests(TestCase):
""" """
Regression test for the use of None as a query value. Regression test for the use of None as a query value.
None is interpreted as an SQL NULL, but only in __exact queries. None is interpreted as an SQL NULL, but only in __exact and __iexact
queries.
Set up some initial polls and choices Set up some initial polls and choices
""" """
p1 = Poll(question='Why?') p1 = Poll(question='Why?')
@ -26,6 +27,9 @@ class NullQueriesTests(TestCase):
# but every 'id' field has a value). # but every 'id' field has a value).
self.assertQuerysetEqual(Choice.objects.filter(choice__exact=None), []) self.assertQuerysetEqual(Choice.objects.filter(choice__exact=None), [])
# The same behavior for iexact query.
self.assertQuerysetEqual(Choice.objects.filter(choice__iexact=None), [])
# Excluding the previous result returns everything. # Excluding the previous result returns everything.
self.assertQuerysetEqual( self.assertQuerysetEqual(
Choice.objects.exclude(choice=None).order_by('id'), Choice.objects.exclude(choice=None).order_by('id'),
@ -38,10 +42,10 @@ class NullQueriesTests(TestCase):
# Valid query, but fails because foo isn't a keyword # Valid query, but fails because foo isn't a keyword
self.assertRaises(FieldError, Choice.objects.filter, foo__exact=None) self.assertRaises(FieldError, Choice.objects.filter, foo__exact=None)
# Can't use None on anything other than __exact # Can't use None on anything other than __exact and __iexact
self.assertRaises(ValueError, Choice.objects.filter, id__gt=None) self.assertRaises(ValueError, Choice.objects.filter, id__gt=None)
# Can't use None on anything other than __exact # Can't use None on anything other than __exact and __iexact
self.assertRaises(ValueError, Choice.objects.filter, foo__gt=None) self.assertRaises(ValueError, Choice.objects.filter, foo__gt=None)
# Related managers use __exact=None implicitly if the object hasn't been saved. # Related managers use __exact=None implicitly if the object hasn't been saved.