如何从Pydantic模型实例创建新模型并保留原有赋值?
能否从Pydantic实例创建新模型并保留原有赋值
可以实现,你原有示例代码未正确传递字段定义和实例的已有值,所以生成的动态模型是空的。修正后的可运行代码如下:
from pydantic import create_model, BaseModel from typing import Optional class ExampleModel(BaseModel): some_text: str optional_number: Optional[float] instance = ExampleModel(some_text="foo") # 构造动态模型的字段定义:格式为(字段类型, 默认值) fields = { field_name: (field.type_, getattr(instance, field_name)) for field_name, field in instance.__fields__.items() } # 创建动态模型时传入字段定义和配置 dynamic_Model = create_model("Parameters", **fields, __config__=instance.Config) dyn_instance = dynamic_Model() print(instance) # 输出:some_text='foo' optional_number=None print(dyn_instance) # 输出:some_text='foo' optional_number=None print("Is it equal ? "+ str(dyn_instance == instance)) # 输出:Is it equal ? True
核心逻辑说明:
create_model创建新模型时,除了配置参数外,需要传入所有字段的定义,格式为字段名=(字段类型, 默认值)- 从已有实例中可以通过
.__fields__属性拿到原模型的所有字段定义,再通过getattr获取实例已经赋值的内容作为新模型的字段默认值 - 这样生成的动态模型实例会完全继承原有实例的所有字段和赋值,两个实例判等结果为True
- 如果使用Pydantic V2版本,只需将上述代码中读取字段的
instance.__fields__替换为instance.model_fields即可,逻辑完全一致
Streamlit多页应用表单状态保留方案
你遇到的多页切换后表单内容丢失,本质是Streamlit多页切换时会话状态不会自动关联到streamlit-pydantic的表单默认值,用上述动态模型方案即可解决,实现步骤如下:
- 首次渲染表单时,将用户提交后的模型实例存入
st.session_state - 每次页面加载时,先判断会话状态中是否存在该表单对应的实例:
- 不存在:直接用原Pydantic模型渲染空表单
- 存在:用该实例生成带默认值的动态模型,传入
sp.pydantic_form的model参数
- 表单提交后更新会话状态中存储的实例
场景适配示例代码:
import streamlit as st import streamlit_pydantic as sp from pydantic import create_model, BaseModel from typing import Optional class InputModel(BaseModel): some_text: str optional_number: Optional[float] # 初始化会话状态存储 if "form_instance" not in st.session_state: st.session_state.form_instance = None if st.session_state.form_instance is None: # 首次加载用原模型渲染空表单 model_to_render = InputModel else: # 已有提交记录,用存储的实例生成带默认值的动态模型 fields = { k: (v.type_, getattr(st.session_state.form_instance, k)) for k, v in st.session_state.form_instance.__fields__.items() } model_to_render = create_model("CachedInputModel", **fields, __config__=InputModel.Config) # 渲染表单 current_instance = sp.pydantic_form(model=model_to_render, key="my_form") if current_instance: # 提交后更新会话状态 st.session_state.form_instance = current_instance st.write(current_instance)
内容的提问来源于stack exchange,提问作者Erysol
相关产品推荐
相关产品推荐

