mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	Fixed #21787 -- regression in MTI .exclude() queries
This commit is contained in:
		
							parent
							
								
									16f3a6a4c7
								
							
						
					
					
						commit
						78a2617703
					
				
					 2 changed files with 24 additions and 2 deletions
				
			
		| 
						 | 
					@ -1334,6 +1334,7 @@ class Query(object):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        path, names_with_path = [], []
 | 
					        path, names_with_path = [], []
 | 
				
			||||||
        for pos, name in enumerate(names):
 | 
					        for pos, name in enumerate(names):
 | 
				
			||||||
 | 
					            cur_names_with_path = (name, [])
 | 
				
			||||||
            if name == 'pk':
 | 
					            if name == 'pk':
 | 
				
			||||||
                name = opts.pk.name
 | 
					                name = opts.pk.name
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
| 
						 | 
					@ -1359,19 +1360,22 @@ class Query(object):
 | 
				
			||||||
                        targets = (final_field.rel.get_related_field(),)
 | 
					                        targets = (final_field.rel.get_related_field(),)
 | 
				
			||||||
                        opts = int_model._meta
 | 
					                        opts = int_model._meta
 | 
				
			||||||
                        path.append(PathInfo(final_field.model._meta, opts, targets, final_field, False, True))
 | 
					                        path.append(PathInfo(final_field.model._meta, opts, targets, final_field, False, True))
 | 
				
			||||||
 | 
					                        cur_names_with_path[1].append(PathInfo(final_field.model._meta, opts, targets, final_field, False, True))
 | 
				
			||||||
            if hasattr(field, 'get_path_info'):
 | 
					            if hasattr(field, 'get_path_info'):
 | 
				
			||||||
                pathinfos = field.get_path_info()
 | 
					                pathinfos = field.get_path_info()
 | 
				
			||||||
                if not allow_many:
 | 
					                if not allow_many:
 | 
				
			||||||
                    for inner_pos, p in enumerate(pathinfos):
 | 
					                    for inner_pos, p in enumerate(pathinfos):
 | 
				
			||||||
                        if p.m2m:
 | 
					                        if p.m2m:
 | 
				
			||||||
                            names_with_path.append((name, pathinfos[0:inner_pos + 1]))
 | 
					                            cur_names_with_path[1].extend(pathinfos[0:inner_pos + 1])
 | 
				
			||||||
 | 
					                            names_with_path.append(cur_names_with_path)
 | 
				
			||||||
                            raise MultiJoin(pos + 1, names_with_path)
 | 
					                            raise MultiJoin(pos + 1, names_with_path)
 | 
				
			||||||
                last = pathinfos[-1]
 | 
					                last = pathinfos[-1]
 | 
				
			||||||
                path.extend(pathinfos)
 | 
					                path.extend(pathinfos)
 | 
				
			||||||
                final_field = last.join_field
 | 
					                final_field = last.join_field
 | 
				
			||||||
                opts = last.to_opts
 | 
					                opts = last.to_opts
 | 
				
			||||||
                targets = last.target_fields
 | 
					                targets = last.target_fields
 | 
				
			||||||
                names_with_path.append((name, pathinfos))
 | 
					                cur_names_with_path[1].extend(pathinfos)
 | 
				
			||||||
 | 
					                names_with_path.append(cur_names_with_path)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                # Local non-relational field.
 | 
					                # Local non-relational field.
 | 
				
			||||||
                final_field = field
 | 
					                final_field = field
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3225,3 +3225,21 @@ class ValuesJoinPromotionTests(TestCase):
 | 
				
			||||||
        self.assertEqual(qs.count(), 1)
 | 
					        self.assertEqual(qs.count(), 1)
 | 
				
			||||||
        tblname = connection.ops.quote_name(ObjectB._meta.db_table)
 | 
					        tblname = connection.ops.quote_name(ObjectB._meta.db_table)
 | 
				
			||||||
        self.assertTrue(' LEFT OUTER JOIN %s' % tblname in str(qs.query))
 | 
					        self.assertTrue(' LEFT OUTER JOIN %s' % tblname in str(qs.query))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ForeignKeyToBaseExcludeTests(TestCase):
 | 
				
			||||||
 | 
					    def test_ticket_21787(self):
 | 
				
			||||||
 | 
					        sc1 = SpecialCategory.objects.create(special_name='sc1', name='sc1')
 | 
				
			||||||
 | 
					        sc2 = SpecialCategory.objects.create(special_name='sc2', name='sc2')
 | 
				
			||||||
 | 
					        sc3 = SpecialCategory.objects.create(special_name='sc3', name='sc3')
 | 
				
			||||||
 | 
					        c1 = CategoryItem.objects.create(category=sc1)
 | 
				
			||||||
 | 
					        CategoryItem.objects.create(category=sc2)
 | 
				
			||||||
 | 
					        self.assertQuerysetEqual(
 | 
				
			||||||
 | 
					            SpecialCategory.objects.exclude(
 | 
				
			||||||
 | 
					                categoryitem__id=c1.pk).order_by('name'),
 | 
				
			||||||
 | 
					            [sc2, sc3], lambda x: x
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        self.assertQuerysetEqual(
 | 
				
			||||||
 | 
					            SpecialCategory.objects.filter(categoryitem__id=c1.pk),
 | 
				
			||||||
 | 
					            [sc1], lambda x: x
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue