@@ -644,3 +644,46 @@ def _calculate_keys(
644
644
@declared_attr # type: ignore
645
645
def __tablename__ (cls ) -> str :
646
646
return cls .__name__ .lower ()
647
+
648
+
649
+ def create_model (
650
+ model_name : str ,
651
+ field_definitions : Dict [str , Tuple [Any , Any ]],
652
+ * ,
653
+ __module__ : str = __name__ ,
654
+ ** kwargs ,
655
+ ) -> Type [SQLModelMetaclass ]:
656
+ """
657
+ Dynamically create a model, similar to the Pydantic `create_model()` method
658
+
659
+ :param model_name: name of the created model
660
+ :param field_definitions: data fields of the create model
661
+ :param __module__: module of the created model
662
+ :param **kwargs: Other keyword arguments to pass to the metaclass constructor, e.g. table=True
663
+ """
664
+ fields = {}
665
+ annotations = {}
666
+
667
+ for f_name , f_def in field_definitions .items ():
668
+ if f_name .startswith ("_" ):
669
+ raise ValueError ("Field names may not start with an underscore" )
670
+ try :
671
+ if isinstance (f_def , tuple ) and len (f_def ) > 1 :
672
+ f_annotation , f_value = f_def
673
+ elif isinstance (f_def , tuple ):
674
+ f_annotation , f_value = f_def [0 ], Field (nullable = False )
675
+ else :
676
+ f_annotation , f_value = f_def , Field (nullable = False )
677
+ except ValueError as e :
678
+ raise ConfigError (
679
+ "field_definitions values must be either a tuple of (<type_annotation>, <default_value>)"
680
+ "or just a type annotation [or a 1-tuple of (<type_annotation>,)]"
681
+ ) from e
682
+
683
+ if f_annotation :
684
+ annotations [f_name ] = f_annotation
685
+ fields [f_name ] = f_value
686
+
687
+ namespace = {"__annotations__" : annotations , "__module__" : __module__ , ** fields }
688
+
689
+ return type (model_name , (SQLModel ,), namespace , ** kwargs )
0 commit comments