11from __future__ import annotations
22import contextlib
3- from typing import Any , Dict , get_args
3+ from typing import Any , Dict , Optional , get_args
44from enum import Enum , EnumMeta
55# Dataclass
66import inspect
@@ -210,10 +210,13 @@ def to_dict(
210210 self ,
211211 remove_nulls : bool = False ,
212212 convert_enums : bool = False ,
213- as_values : bool = False
213+ as_values : bool = False ,
214+ exclude : Optional [set ] = None
214215 ) -> dict [str , Any ]:
216+ exclude = exclude or set ()
217+ exclude .add ('_pgoutput' ) # Always exclude _pgoutput
215218 if as_values :
216- return self .__collapse_as_values__ (remove_nulls , convert_enums , as_values )
219+ return self .__collapse_as_values__ (remove_nulls , convert_enums , as_values , exclude )
217220 d = as_dict (self , dict_factory = dict )
218221 if convert_enums :
219222 d = self .__convert_enums__ (d )
@@ -226,12 +229,21 @@ def __collapse_as_values__(
226229 self ,
227230 remove_nulls : bool = False ,
228231 convert_enums : bool = False ,
229- as_values : bool = False
232+ as_values : bool = False ,
233+ exclude : Optional [set ] = None
230234 ) -> dict [str , Any ]:
231235 """Recursively converts any BaseModel instances to their primary key value."""
232236 out = {}
233237 _fields = self .columns ()
234238 for name , field in _fields .items ():
239+ if name in exclude :
240+ continue
241+ # Skip internal or error fields
242+ if name .startswith ('__' ) or name == '__errors__' :
243+ continue
244+ # Skip fields marked for exclusion
245+ if field .metadata .get ('exclude' , False ):
246+ continue
235247 # datatype = field.type
236248 value = getattr (self , name )
237249 if value is None and remove_nulls :
0 commit comments