starting from comment make sure that a selectrelated with a specified set of fields will properly left join multiple levels of nulls and the things that come after the nulls or else data that should exist won t regression test for 7369 regression test for 7530 7716 each of these individually should return the item logically qs1 and qs2 and qs3 and qs4 should be the same regression test for 15823 starting from comment make sure that a select_related with a specified set of fields will properly left join multiple levels of nulls and the things that come after the nulls or else data that should exist won t regression test for 7369 regression test for 7530 7716 value null each of these individually should return the item logically qs1 and qs2 and qs3 and qs4 should be the same regression test for 15823
from django.db.models import Q
from django.test import TestCase

from .models import Comment, Forum, Item, Post, PropertyValue, SystemDetails, SystemInfo


class NullFkTests(TestCase):
    def test_null_fk(self):
        d = SystemDetails.objects.create(details="First details")
        s = SystemInfo.objects.create(system_name="First forum", system_details=d)
        f = Forum.objects.create(system_info=s, forum_name="First forum")
        p = Post.objects.create(forum=f, title="First Post")
        c1 = Comment.objects.create(post=p, comment_text="My first comment")
        c2 = Comment.objects.create(comment_text="My second comment")

        
        
        
        
        c = Comment.objects.select_related().get(id=c1.id)
        self.assertEqual(c.post, p)
        self.assertIsNone(Comment.objects.select_related().get(id=c2.id).post)

        self.assertQuerySetEqual(
            Comment.objects.select_related("post__forum__system_info").all(),
            [
                (c1.id, "My first comment", "<Post: First Post>"),
                (c2.id, "My second comment", "None"),
            ],
            transform=lambda c: (c.id, c.comment_text, repr(c.post)),
        )

        
        self.assertIsNone(
            Comment.objects.select_related("post").filter(post__isnull=True)[0].post
        )

        self.assertQuerySetEqual(
            Comment.objects.select_related("post__forum__system_info__system_details"),
            [
                (c1.id, "My first comment", "<Post: First Post>"),
                (c2.id, "My second comment", "None"),
            ],
            transform=lambda c: (c.id, c.comment_text, repr(c.post)),
        )

    def test_combine_isnull(self):
        item = Item.objects.create(title="Some Item")
        pv = PropertyValue.objects.create(label="Some Value")
        item.props.create(key="a", value=pv)
        item.props.create(key="b")  
        q1 = Q(props__key="a", props__value=pv)
        q2 = Q(props__key="b", props__value__isnull=True)

        
        self.assertEqual(Item.objects.get(q1), item)
        self.assertEqual(Item.objects.get(q2), item)

        
        qs1 = Item.objects.filter(q1) & Item.objects.filter(q2)
        qs2 = Item.objects.filter(q2) & Item.objects.filter(q1)
        qs3 = Item.objects.filter(q1) | Item.objects.filter(q2)
        qs4 = Item.objects.filter(q2) | Item.objects.filter(q1)

        
        self.assertEqual(list(qs1), list(qs2))
        self.assertEqual(list(qs3), list(qs4))