上下文
SQLModel在很大程度上基于Pydantic。后者具有create_model函数,允许您在运行时创建/定义模型类,方法是将字段定义作为任意关键字参数传递。
在create_model中似乎没有内置到SQLModel中的特殊版本,文档中也没有提到动态模型的创建。
问题
可以利用Pydantic create_model函数来定义一个功能齐全的SQLModel类吗?
要求
在某种意义上,它将正确地充当ORM类,使用数据库引擎发挥作用,它的实例可以添加到数据库会话中并由数据库会话刷新,就像任何静态定义的SQLModel子类一样。
作为概念的证明,应该可以动态地构造以下静态定义模型的等效工作,并使用它执行上述操作:
from typing import Optional
from sqlmodel import Field, SQLModel
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None发布于 2022-10-24 20:25:54
答案是肯定的!
create_model函数具有可选的__base__参数(如文档中提到的),它接受Pydantic BaseModel的任何子类(或子类序列)。SQLModel基类恰好是直接从BaseModel继承的,因此可以在这里传递。
但是,这不足以使模型映射到表。SQLModelMetaclass要求table=True作为关键字参数在SQLModel子类中传递。幸运的是,在Pydantic中也有一个解决方案。
虽然Pydantic的文档网站上没有提到这一点,但是create_model函数(来源在这里)有一个__cls_kwargs__参数,可以在类创建期间将任意关键字参数传递给元类。
这两个组件以及实际的字段定义实际上都是我们动态创建ORM类所需要的。下面是一个完整的工作示例:
from typing import Optional
from pydantic import create_model
from sqlmodel import Field, Session, SQLModel, create_engine
field_definitions = {
"id": (Optional[int], Field(default=None, primary_key=True)),
"name": (str, ...),
"secret_name": (str, ...),
"age": (Optional[int], None),
}
Hero = create_model(
"Hero",
__base__=SQLModel,
__cls_kwargs__={"table": True},
**field_definitions,
)
if __name__ == '__main__':
sqlite_url = "sqlite:///test.db"
engine = create_engine(sqlite_url, echo=True)
SQLModel.metadata.create_all(engine)
session = Session(engine)
hero = Hero(name="Spider-Boy", secret_name="Pedro Parqueador")
session.add(hero)
session.commit()
session.refresh(hero)
print(hero)该print语句提供以下输出:
secret_name='Pedro Parqueador' id=1 age=None name='Spider-Boy'这说明id是在插入时由数据库创建的。
引擎打印到stdout的SQL语句显示,一切按计划进行:
CREATE TABLE hero (
id INTEGER NOT NULL,
name VARCHAR NOT NULL,
secret_name VARCHAR NOT NULL,
age INTEGER,
PRIMARY KEY (id)
)
...
INSERT INTO hero (name, secret_name, age) VALUES (?, ?, ?)
('Spider-Boy', 'Pedro Parqueador', None)
...
SELECT hero.id, hero.name, hero.secret_name, hero.age
FROM hero
WHERE hero.id = ?
(1,)到目前为止,除了适用于Pydantic中的动态模型创建之外,我还没有遇到对这种方法的任何警告,例如,如果模型是动态定义的,那么显然缺乏静态类型检查支持或自动建议。
https://stackoverflow.com/questions/74186458
复制相似问题