1. from django.core.exceptions import FieldError
    
  2. from django.test import TestCase
    
  3. 
    
  4. from .models import Choice, Inner, OuterA, OuterB, Poll
    
  5. 
    
  6. 
    
  7. class NullQueriesTests(TestCase):
    
  8.     def test_none_as_null(self):
    
  9.         """
    
  10.         Regression test for the use of None as a query value.
    
  11. 
    
  12.         None is interpreted as an SQL NULL, but only in __exact and __iexact
    
  13.         queries.
    
  14.         Set up some initial polls and choices
    
  15.         """
    
  16.         p1 = Poll(question="Why?")
    
  17.         p1.save()
    
  18.         c1 = Choice(poll=p1, choice="Because.")
    
  19.         c1.save()
    
  20.         c2 = Choice(poll=p1, choice="Why Not?")
    
  21.         c2.save()
    
  22. 
    
  23.         # Exact query with value None returns nothing ("is NULL" in sql,
    
  24.         # but every 'id' field has a value).
    
  25.         self.assertSequenceEqual(Choice.objects.filter(choice__exact=None), [])
    
  26. 
    
  27.         # The same behavior for iexact query.
    
  28.         self.assertSequenceEqual(Choice.objects.filter(choice__iexact=None), [])
    
  29. 
    
  30.         # Excluding the previous result returns everything.
    
  31.         self.assertSequenceEqual(
    
  32.             Choice.objects.exclude(choice=None).order_by("id"), [c1, c2]
    
  33.         )
    
  34. 
    
  35.         # Valid query, but fails because foo isn't a keyword
    
  36.         msg = (
    
  37.             "Cannot resolve keyword 'foo' into field. Choices are: choice, id, poll, "
    
  38.             "poll_id"
    
  39.         )
    
  40.         with self.assertRaisesMessage(FieldError, msg):
    
  41.             Choice.objects.filter(foo__exact=None)
    
  42. 
    
  43.         # Can't use None on anything other than __exact and __iexact
    
  44.         with self.assertRaisesMessage(ValueError, "Cannot use None as a query value"):
    
  45.             Choice.objects.filter(id__gt=None)
    
  46. 
    
  47.     def test_unsaved(self):
    
  48.         poll = Poll(question="How?")
    
  49.         msg = (
    
  50.             "'Poll' instance needs to have a primary key value before this "
    
  51.             "relationship can be used."
    
  52.         )
    
  53.         with self.assertRaisesMessage(ValueError, msg):
    
  54.             poll.choice_set.all()
    
  55. 
    
  56.     def test_reverse_relations(self):
    
  57.         """
    
  58.         Querying across reverse relations and then another relation should
    
  59.         insert outer joins correctly so as not to exclude results.
    
  60.         """
    
  61.         obj = OuterA.objects.create()
    
  62.         self.assertSequenceEqual(OuterA.objects.filter(inner__third=None), [obj])
    
  63.         self.assertSequenceEqual(OuterA.objects.filter(inner__third__data=None), [obj])
    
  64. 
    
  65.         inner = Inner.objects.create(first=obj)
    
  66.         self.assertSequenceEqual(
    
  67.             Inner.objects.filter(first__inner__third=None), [inner]
    
  68.         )
    
  69. 
    
  70.         # Ticket #13815: check if <reverse>_isnull=False does not produce
    
  71.         # faulty empty lists
    
  72.         outerb = OuterB.objects.create(data="reverse")
    
  73.         self.assertSequenceEqual(OuterB.objects.filter(inner__isnull=False), [])
    
  74.         Inner.objects.create(first=obj)
    
  75.         self.assertSequenceEqual(OuterB.objects.exclude(inner__isnull=False), [outerb])