1. from django.db.models import Q
    
  2. from django.test import TestCase
    
  3. 
    
  4. from .models import Comment, Forum, Item, Post, PropertyValue, SystemDetails, SystemInfo
    
  5. 
    
  6. 
    
  7. class NullFkTests(TestCase):
    
  8.     def test_null_fk(self):
    
  9.         d = SystemDetails.objects.create(details="First details")
    
  10.         s = SystemInfo.objects.create(system_name="First forum", system_details=d)
    
  11.         f = Forum.objects.create(system_info=s, forum_name="First forum")
    
  12.         p = Post.objects.create(forum=f, title="First Post")
    
  13.         c1 = Comment.objects.create(post=p, comment_text="My first comment")
    
  14.         c2 = Comment.objects.create(comment_text="My second comment")
    
  15. 
    
  16.         # Starting from comment, make sure that a .select_related(...) with a specified
    
  17.         # set of fields will properly LEFT JOIN multiple levels of NULLs (and the things
    
  18.         # that come after the NULLs, or else data that should exist won't). Regression
    
  19.         # test for #7369.
    
  20.         c = Comment.objects.select_related().get(id=c1.id)
    
  21.         self.assertEqual(c.post, p)
    
  22.         self.assertIsNone(Comment.objects.select_related().get(id=c2.id).post)
    
  23. 
    
  24.         self.assertQuerysetEqual(
    
  25.             Comment.objects.select_related("post__forum__system_info").all(),
    
  26.             [
    
  27.                 (c1.id, "My first comment", "<Post: First Post>"),
    
  28.                 (c2.id, "My second comment", "None"),
    
  29.             ],
    
  30.             transform=lambda c: (c.id, c.comment_text, repr(c.post)),
    
  31.         )
    
  32. 
    
  33.         # Regression test for #7530, #7716.
    
  34.         self.assertIsNone(
    
  35.             Comment.objects.select_related("post").filter(post__isnull=True)[0].post
    
  36.         )
    
  37. 
    
  38.         self.assertQuerysetEqual(
    
  39.             Comment.objects.select_related("post__forum__system_info__system_details"),
    
  40.             [
    
  41.                 (c1.id, "My first comment", "<Post: First Post>"),
    
  42.                 (c2.id, "My second comment", "None"),
    
  43.             ],
    
  44.             transform=lambda c: (c.id, c.comment_text, repr(c.post)),
    
  45.         )
    
  46. 
    
  47.     def test_combine_isnull(self):
    
  48.         item = Item.objects.create(title="Some Item")
    
  49.         pv = PropertyValue.objects.create(label="Some Value")
    
  50.         item.props.create(key="a", value=pv)
    
  51.         item.props.create(key="b")  # value=NULL
    
  52.         q1 = Q(props__key="a", props__value=pv)
    
  53.         q2 = Q(props__key="b", props__value__isnull=True)
    
  54. 
    
  55.         # Each of these individually should return the item.
    
  56.         self.assertEqual(Item.objects.get(q1), item)
    
  57.         self.assertEqual(Item.objects.get(q2), item)
    
  58. 
    
  59.         # Logically, qs1 and qs2, and qs3 and qs4 should be the same.
    
  60.         qs1 = Item.objects.filter(q1) & Item.objects.filter(q2)
    
  61.         qs2 = Item.objects.filter(q2) & Item.objects.filter(q1)
    
  62.         qs3 = Item.objects.filter(q1) | Item.objects.filter(q2)
    
  63.         qs4 = Item.objects.filter(q2) | Item.objects.filter(q1)
    
  64. 
    
  65.         # Regression test for #15823.
    
  66.         self.assertEqual(list(qs1), list(qs2))
    
  67.         self.assertEqual(list(qs3), list(qs4))