@@ -273,7 +273,9 @@ def __new__(
273
273
key : pydantic_kwargs .pop (key )
274
274
for key in pydantic_kwargs .keys () & allowed_config_kwargs
275
275
}
276
- config_table = getattr (class_dict .get ("Config" , object ()), "table" , False ) or kwargs .get ("table" , False )
276
+ config_table = getattr (
277
+ class_dict .get ("Config" , object ()), "table" , False
278
+ ) or kwargs .get ("table" , False )
277
279
# If we have a table, we need to have defaults for all fields
278
280
# Pydantic v2 sets a __pydantic_core_schema__ which is very hard to change. Changing the fields does not do anything
279
281
if config_table is True :
@@ -282,7 +284,12 @@ def __new__(
282
284
if value is PydanticUndefined :
283
285
dict_used [key ] = None
284
286
elif isinstance (value , FieldInfo ):
285
- if value .default is PydanticUndefined and value .default_factory is None :
287
+ if (
288
+ value .default in (PydanticUndefined , Ellipsis )
289
+ ) and value .default_factory is None :
290
+ value .original_default = (
291
+ value .default
292
+ ) # So we can check for nullable
286
293
value .default = None
287
294
288
295
new_cls : Type ["SQLModelMetaclass" ] = super ().__new__ (
@@ -496,6 +503,7 @@ def get_column_from_field(field: FieldInfo) -> Column: # type: ignore
496
503
class_registry = weakref .WeakValueDictionary () # type: ignore
497
504
498
505
default_registry = registry ()
506
+ _TSQLModel = TypeVar ("_TSQLModel" , bound = "SQLModel" )
499
507
500
508
501
509
class SQLModel (BaseModel , metaclass = SQLModelMetaclass , registry = default_registry ):
@@ -549,12 +557,28 @@ def __tablename__(cls) -> str:
549
557
return cls .__name__ .lower ()
550
558
551
559
@classmethod
552
- def model_validate (cls , * args , ** kwargs ):
553
- return super ().model_validate (* args , ** kwargs )
560
+ def model_validate (
561
+ cls : type [_TSQLModel ],
562
+ obj : Any ,
563
+ * ,
564
+ strict : bool | None = None ,
565
+ from_attributes : bool | None = None ,
566
+ context : dict [str , Any ] | None = None ,
567
+ ) -> _TSQLModel :
568
+ # Somehow model validate doesn't call __init__ so it would remove our init logic
569
+ validated = super ().model_validate (
570
+ obj , strict = strict , from_attributes = from_attributes , context = context
571
+ )
572
+ return cls (** {key : value for key , value in validated })
554
573
555
574
556
575
def _is_field_noneable (field : FieldInfo ) -> bool :
576
+ if getattr (field , "nullable" , PydanticUndefined ) is not PydanticUndefined :
577
+ return field .nullable
557
578
if not field .is_required ():
579
+ default = getattr (field , "original_default" , field .default )
580
+ if default is PydanticUndefined :
581
+ return False
558
582
if field .annotation is None or field .annotation is NoneType :
559
583
return True
560
584
if get_origin (field .annotation ) is Union :
0 commit comments