1+ import copy
12from typing import (
23 TYPE_CHECKING ,
34 Any ,
5+ Callable ,
46 Dict ,
57 Generic ,
68 Optional ,
911)
1012
1113from pydantic import BaseModel
14+ from pydantic .fields import FieldInfo
1215from pydantic_core import core_schema
1316
1417from ninja import Body
1518from ninja .orm import ModelSchema
1619from ninja .schema import Schema
1720from ninja .utils import is_optional_type
1821
22+ try :
23+ copy_field_info : Callable [[FieldInfo ], FieldInfo ] = FieldInfo ._copy
24+ except AttributeError :
25+ # Fallback for Pydantic<2.11.0
26+ copy_field_info = copy .copy
27+
1928
2029class ModelToDict (dict ):
2130 _wrapped_model : Any = None
@@ -45,15 +54,20 @@ def get_schema_annotations(schema_cls: Type[Any]) -> Dict[str, Any]:
4554 return annotations
4655
4756
48- def create_patch_schema (schema_cls : Type [Any ]) -> Type [ModelToDict ]:
57+ def create_patch_schema (schema_cls : Type [BaseModel ]) -> Type [ModelToDict ]:
4958 schema_annotations = get_schema_annotations (schema_cls )
50- values , annotations = {}, {}
51- # assert False, f"{schema_cls} - {schema_cls.model_fields}"
52- for f in schema_cls .model_fields .keys ():
53- t = schema_annotations [f ]
54- if not is_optional_type (t ):
55- values [f ] = getattr (schema_cls , f , None )
56- annotations [f ] = Optional [t ]
59+ values : Dict [str , Any ] = {}
60+ annotations = {}
61+
62+ for name , field in schema_cls .model_fields .items ():
63+ annotation = schema_annotations [name ]
64+ if is_optional_type (annotation ):
65+ continue
66+ patch_field = copy_field_info (field )
67+ patch_field .default = None
68+ patch_field .default_factory = None
69+ values [name ] = patch_field
70+ annotations [name ] = Optional [annotation ]
5771 values ["__annotations__" ] = annotations
5872 OptionalSchema = type (f"{ schema_cls .__name__ } Patch" , (schema_cls ,), values )
5973
@@ -65,7 +79,7 @@ class OptionalDictSchema(ModelToDict):
6579
6680
6781class PatchDictUtil :
68- def __getitem__ (self , schema_cls : Any ) -> Any :
82+ def __getitem__ (self , schema_cls : Type [ BaseModel ] ) -> Any :
6983 new_cls = create_patch_schema (schema_cls )
7084 return Body [new_cls ] # type: ignore
7185
0 commit comments