mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #33937 -- Optimized serialization of related m2m fields without natural keys.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							604fadde11
						
					
				
				
					commit
					19e0587ee5
				
			
							
								
								
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -616,6 +616,7 @@ answer newbie questions, and generally made Django that much better: | ||||
|     Mario Gonzalez <gonzalemario@gmail.com> | ||||
|     Mariusz Felisiak <felisiak.mariusz@gmail.com> | ||||
|     Mark Biggers <biggers@utsl.com> | ||||
|     Mark Evans <mark@meltdownlabs.com> | ||||
|     Mark Gensler <mark.gensler@protonmail.com> | ||||
|     mark@junklight.com | ||||
|     Mark Lavin <markdlavin@gmail.com> | ||||
|   | ||||
| @@ -70,14 +70,20 @@ class Serializer(base.Serializer): | ||||
|                 def m2m_value(value): | ||||
|                     return value.natural_key() | ||||
|  | ||||
|                 def queryset_iterator(obj, field): | ||||
|                     return getattr(obj, field.name).iterator() | ||||
|  | ||||
|             else: | ||||
|  | ||||
|                 def m2m_value(value): | ||||
|                     return self._value_from_field(value, value._meta.pk) | ||||
|  | ||||
|                 def queryset_iterator(obj, field): | ||||
|                     return getattr(obj, field.name).only("pk").iterator() | ||||
|  | ||||
|             m2m_iter = getattr(obj, "_prefetched_objects_cache", {}).get( | ||||
|                 field.name, | ||||
|                 getattr(obj, field.name).iterator(), | ||||
|                 queryset_iterator(obj, field), | ||||
|             ) | ||||
|             self._current[field.name] = [m2m_value(related) for related in m2m_iter] | ||||
|  | ||||
|   | ||||
| @@ -146,14 +146,20 @@ class Serializer(base.Serializer): | ||||
|                         self.xml.endElement("natural") | ||||
|                     self.xml.endElement("object") | ||||
|  | ||||
|                 def queryset_iterator(obj, field): | ||||
|                     return getattr(obj, field.name).iterator() | ||||
|  | ||||
|             else: | ||||
|  | ||||
|                 def handle_m2m(value): | ||||
|                     self.xml.addQuickElement("object", attrs={"pk": str(value.pk)}) | ||||
|  | ||||
|                 def queryset_iterator(obj, field): | ||||
|                     return getattr(obj, field.name).only("pk").iterator() | ||||
|  | ||||
|             m2m_iter = getattr(obj, "_prefetched_objects_cache", {}).get( | ||||
|                 field.name, | ||||
|                 getattr(obj, field.name).iterator(), | ||||
|                 queryset_iterator(obj, field), | ||||
|             ) | ||||
|             for relobj in m2m_iter: | ||||
|                 handle_m2m(relobj) | ||||
|   | ||||
| @@ -410,6 +410,33 @@ class SerializersTestBase: | ||||
|         self.assertEqual(self._get_field_values(child_data, "parent_m2m"), []) | ||||
|         self.assertEqual(self._get_field_values(child_data, "parent_data"), []) | ||||
|  | ||||
|     def test_serialize_only_pk(self): | ||||
|         with self.assertNumQueries(5) as ctx: | ||||
|             serializers.serialize( | ||||
|                 self.serializer_name, | ||||
|                 Article.objects.all(), | ||||
|                 use_natural_foreign_keys=False, | ||||
|             ) | ||||
|  | ||||
|         categories_sql = ctx[1]["sql"] | ||||
|         self.assertNotIn(connection.ops.quote_name("meta_data_id"), categories_sql) | ||||
|         meta_data_sql = ctx[2]["sql"] | ||||
|         self.assertNotIn(connection.ops.quote_name("kind"), meta_data_sql) | ||||
|  | ||||
|     def test_serialize_no_only_pk_with_natural_keys(self): | ||||
|         with self.assertNumQueries(5) as ctx: | ||||
|             serializers.serialize( | ||||
|                 self.serializer_name, | ||||
|                 Article.objects.all(), | ||||
|                 use_natural_foreign_keys=True, | ||||
|             ) | ||||
|  | ||||
|         categories_sql = ctx[1]["sql"] | ||||
|         self.assertNotIn(connection.ops.quote_name("meta_data_id"), categories_sql) | ||||
|         # CategoryMetaData has natural_key(). | ||||
|         meta_data_sql = ctx[2]["sql"] | ||||
|         self.assertIn(connection.ops.quote_name("kind"), meta_data_sql) | ||||
|  | ||||
|  | ||||
| class SerializerAPITests(SimpleTestCase): | ||||
|     def test_stream_class(self): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user