Commit d4e578d0 authored by Denis Moskalets's avatar Denis Moskalets Committed by Tim Graham
Browse files

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

Thanks Anubhav Joshi for the documentation.
parent 2fd7fc13
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1031,7 +1031,7 @@ class Query(object):
        # Interpret '__exact=None' as the sql 'is NULL'; otherwise, reject all
        # uses of None as a query value.
        if value is None:
            if lookup_type != 'exact':
            if lookup_type not in ('exact', 'iexact'):
                raise ValueError("Cannot use None as a query value")
            lookup_type = 'isnull'
            value = True
+6 −0
Original line number Diff line number Diff line
@@ -2028,9 +2028,15 @@ iexact

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::

    Blog.objects.get(name__iexact='beatles blog')
    Blog.objects.get(name__iexact=None)

SQL equivalent::

+3 −0
Original line number Diff line number Diff line
@@ -450,6 +450,9 @@ Models
  argument to control whether or not to perform operations in bulk
  (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
^^^^^^^

+7 −3
Original line number Diff line number Diff line
@@ -12,7 +12,8 @@ class NullQueriesTests(TestCase):
        """
        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
        """
        p1 = Poll(question='Why?')
@@ -26,6 +27,9 @@ class NullQueriesTests(TestCase):
        # but every 'id' field has a value).
        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.
        self.assertQuerysetEqual(
            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
        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)

        # 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)

        # Related managers use __exact=None implicitly if the object hasn't been saved.