@@ -73,6 +73,28 @@ def get_tzinfo(self):
7373 """
7474 return
7575
76+ def _get_serializer_options (self , ** kwargs ) -> dict :
77+ """Extract serializer options from kwargs, using model instance defaults as fallback.
78+
79+ :param kwargs: Options to override model defaults
80+ :return: Dictionary of options for Serializer initialization
81+ """
82+ return {
83+ "date_format" : kwargs .get ("date_format" ) or self .date_format ,
84+ "datetime_format" : kwargs .get ("datetime_format" ) or self .datetime_format ,
85+ "time_format" : kwargs .get ("time_format" ) or self .time_format ,
86+ "decimal_format" : kwargs .get ("decimal_format" ) or self .decimal_format ,
87+ "tzinfo" : kwargs .get ("tzinfo" ) or self .get_tzinfo (),
88+ "serialize_types" : kwargs .get ("serialize_types" ) or self .serialize_types ,
89+ "exclude_values" : kwargs .get ("exclude_values" ) or self .exclude_values ,
90+ "max_serialization_depth" : (
91+ kwargs .get ("max_serialization_depth" )
92+ if kwargs .get ("max_serialization_depth" ) is not None
93+ else self .max_serialization_depth
94+ ),
95+ "serialize_columns" : kwargs .get ("serialize_columns" ) or self .serialize_columns ,
96+ }
97+
7698 def to_dict (
7799 self ,
78100 only = (),
@@ -108,21 +130,18 @@ def to_dict(
108130 Custom serializers replace normal serialization for matching columns.
109131 :return: data: dict
110132 """
111- s = Serializer (
112- date_format = date_format or self .date_format ,
113- datetime_format = datetime_format or self .datetime_format ,
114- time_format = time_format or self .time_format ,
115- decimal_format = decimal_format or self .decimal_format ,
116- tzinfo = tzinfo or self .get_tzinfo (),
117- serialize_types = serialize_types or self .serialize_types ,
118- exclude_values = exclude_values or self .exclude_values ,
119- max_serialization_depth = (
120- max_serialization_depth
121- if max_serialization_depth is not None
122- else self .max_serialization_depth
123- ),
124- serialize_columns = serialize_columns or self .serialize_columns ,
133+ options = self ._get_serializer_options (
134+ date_format = date_format ,
135+ datetime_format = datetime_format ,
136+ time_format = time_format ,
137+ decimal_format = decimal_format ,
138+ tzinfo = tzinfo ,
139+ serialize_types = serialize_types ,
140+ exclude_values = exclude_values ,
141+ max_serialization_depth = max_serialization_depth ,
142+ serialize_columns = serialize_columns ,
125143 )
144+ s = Serializer (** options )
126145 return s (self , only = only , extend = rules ) # type: ignore
127146
128147
@@ -378,4 +397,43 @@ def get_type(value) -> str:
378397
379398
380399def serialize_collection (iterable : t .Iterable , * args , ** kwargs ) -> list :
381- return [item .to_dict (* args , ** kwargs ) for item in iterable ]
400+ """Serialize a collection of model instances efficiently by reusing a single Serializer.
401+
402+ This optimized version creates a single Serializer instance and reuses it for all items,
403+ eliminating redundant object creation overhead for large collections.
404+ """
405+ iterable = list (iterable ) # Convert to list to allow multiple passes
406+ if not iterable :
407+ return []
408+
409+ # Get options from first item to create a shared Serializer
410+ first_item = iterable [0 ]
411+ options = first_item ._get_serializer_options (** kwargs )
412+
413+ # Extract only and rules from kwargs or positional args
414+ # to_dict accepts only and rules as positional args, so handle both cases
415+ only = kwargs .get ("only" , args [0 ] if len (args ) > 0 else ())
416+ rules = kwargs .get ("rules" , args [1 ] if len (args ) > 1 else ())
417+
418+ # Create a single Serializer instance to reuse for all items
419+ serializer = Serializer (** options )
420+
421+ # Serialize each item using the shared Serializer
422+ result = []
423+ for item in iterable :
424+ # Create a fresh schema for this item
425+ serializer .schema = Schema ()
426+
427+ # Update schema with provided only/rules first (simulating __call__ behavior)
428+ # This matches the behavior in Serializer.__call__ where schema is updated
429+ # before serialize is called
430+ serializer .schema .update (only = only , extend = rules )
431+
432+ # Serialize the item - serialize_model will update the schema again
433+ # with item.serialize_only and item.serialize_rules, which matches
434+ # the original behavior where __call__ updates schema, then serialize_model
435+ # updates it again
436+ serialized = serializer .serialize (item )
437+ result .append (serialized )
438+
439+ return result
0 commit comments