mirror of
				https://github.com/django/django.git
				synced 2025-10-29 00:26:07 +00:00 
			
		
		
		
	[1.6.x] Fixed #23370 -- defer() + select_related() crashed with inherited models.
Backport of 6613ea6e3f from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Tim Graham
						Tim Graham
					
				
			
			
				
	
			
			
			
						parent
						
							ce4057591a
						
					
				
				
					commit
					b877697472
				
			
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -60,6 +60,7 @@ answer newbie questions, and generally made Django that much better: | |||||||
|     Mathieu Agopian <mathieu.agopian@gmail.com> |     Mathieu Agopian <mathieu.agopian@gmail.com> | ||||||
|     Roberto Aguilar <roberto@baremetal.io> |     Roberto Aguilar <roberto@baremetal.io> | ||||||
|     ajs <adi@sieker.info> |     ajs <adi@sieker.info> | ||||||
|  |     Akis Kesoglou <akiskesoglou@gmail.com> | ||||||
|     alang@bright-green.com |     alang@bright-green.com | ||||||
|     A S Alam <aalam@users.sf.net> |     A S Alam <aalam@users.sf.net> | ||||||
|     Andi Albrecht <albrecht.andi@gmail.com> |     Andi Albrecht <albrecht.andi@gmail.com> | ||||||
|   | |||||||
| @@ -1198,12 +1198,12 @@ def get_klass_info(klass, max_depth=0, cur_depth=0, requested=None, | |||||||
|         init_list = [] |         init_list = [] | ||||||
|         # Build the list of fields that *haven't* been requested |         # Build the list of fields that *haven't* been requested | ||||||
|         for field, model in klass._meta.get_concrete_fields_with_model(): |         for field, model in klass._meta.get_concrete_fields_with_model(): | ||||||
|             if field.name not in load_fields: |             if from_parent and model and issubclass(from_parent, model): | ||||||
|                 skip.add(field.attname) |  | ||||||
|             elif from_parent and issubclass(from_parent, model.__class__): |  | ||||||
|                 # Avoid loading fields already loaded for parent model for |                 # Avoid loading fields already loaded for parent model for | ||||||
|                 # child models. |                 # child models. | ||||||
|                 continue |                 continue | ||||||
|  |             elif field.name not in load_fields: | ||||||
|  |                 skip.add(field.attname) | ||||||
|             else: |             else: | ||||||
|                 init_list.append(field.attname) |                 init_list.append(field.attname) | ||||||
|         # Retrieve all the requested fields |         # Retrieve all the requested fields | ||||||
|   | |||||||
| @@ -4,10 +4,13 @@ Django 1.6.7 release notes | |||||||
|  |  | ||||||
| *Under development* | *Under development* | ||||||
|  |  | ||||||
| Django 1.6.7 fixes a regression in the 1.6.6 security release. | Django 1.6.7 fixes several bugs in 1.6.6, including a regression related to | ||||||
|  | a security fix in that release. | ||||||
|  |  | ||||||
| Bugfixes | Bugfixes | ||||||
| ======== | ======== | ||||||
|  |  | ||||||
| * Allowed inherited and m2m fields to be referenced in the admin | * Allowed inherited and m2m fields to be referenced in the admin | ||||||
|   :ticket:`23329` |   (:ticket:`23329`). | ||||||
|  | * Fixed a crash when using ``QuerySet.defer()`` with ``select_related()`` | ||||||
|  |   (:ticket:`23370`). | ||||||
|   | |||||||
| @@ -275,6 +275,43 @@ class ModelInheritanceTests(TestCase): | |||||||
|             lambda: ItalianRestaurant.objects.select_related("chef")[0].chef |             lambda: ItalianRestaurant.objects.select_related("chef")[0].chef | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |     def test_select_related_defer(self): | ||||||
|  |         """ | ||||||
|  |         #23370 - Should be able to defer child fields when using | ||||||
|  |         select_related() from parent to child. | ||||||
|  |         """ | ||||||
|  |         Restaurant.objects.create( | ||||||
|  |             name="Demon Dogs", | ||||||
|  |             address="944 W. Fullerton", | ||||||
|  |             serves_hot_dogs=True, | ||||||
|  |             serves_pizza=False, | ||||||
|  |             rating=2, | ||||||
|  |         ) | ||||||
|  |         ItalianRestaurant.objects.create( | ||||||
|  |             name="Ristorante Miron", | ||||||
|  |             address="1234 W. Ash", | ||||||
|  |             serves_hot_dogs=False, | ||||||
|  |             serves_pizza=False, | ||||||
|  |             serves_gnocchi=True, | ||||||
|  |             rating=4, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         qs = (Restaurant.objects | ||||||
|  |             .select_related("italianrestaurant") | ||||||
|  |             .defer("italianrestaurant__serves_gnocchi") | ||||||
|  |             .order_by("rating")) | ||||||
|  |  | ||||||
|  |         # Test that the field was actually defered | ||||||
|  |         with self.assertNumQueries(2): | ||||||
|  |             objs = list(qs.all()) | ||||||
|  |             self.assertTrue(objs[1].italianrestaurant.serves_gnocchi) | ||||||
|  |  | ||||||
|  |         # Test that model fields where assigned correct values | ||||||
|  |         self.assertEqual(qs[0].name, 'Demon Dogs') | ||||||
|  |         self.assertEqual(qs[0].rating, 2) | ||||||
|  |         self.assertEqual(qs[1].italianrestaurant.name, 'Ristorante Miron') | ||||||
|  |         self.assertEqual(qs[1].italianrestaurant.rating, 4) | ||||||
|  |  | ||||||
|     def test_mixin_init(self): |     def test_mixin_init(self): | ||||||
|         m = MixinModel() |         m = MixinModel() | ||||||
|         self.assertEqual(m.other_attr, 1) |         self.assertEqual(m.other_attr, 1) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user