首页 > 编程问答 >用于将日期时间表示为日期和时间的 Pydantic 模型

用于将日期时间表示为日期和时间的 Pydantic 模型

时间:2024-09-25 04:10:22浏览次数:7  
标签:python pydantic

我为日期时间创建了一个 Pydantic 模型,它将处理解析一个类似于 { "date": "2021-07-01", "time": "12:36:23" } 的 JSON 对象 datetime(2021, 7, 1, 12, 36, 23) 它还为模型生成正确的 JSON 架构。

class TimestampWithSplit(RootModel):
    root: datetime

    @classmethod
    def __get_pydantic_core_schema__(
        cls, source: Type[Any], handler: GetCoreSchemaHandler
    ) -> core_schema.CoreSchema:
        return core_schema.chain_schema(
            [
                core_schema.typed_dict_schema(
                    {
                        "date": core_schema.typed_dict_field(core_schema.date_schema()),
                        "time": core_schema.typed_dict_field(core_schema.time_schema()),
                    }
                ),
                core_schema.no_info_plain_validator_function(cls.validate_to_datetime),
            ]
        )

    @staticmethod
    def validate_to_datetime(value: dict) -> datetime:
        return datetime.combine(value["date"], value["time"])

我现在尝试做两件事:

  1. 我现在想向生成的 json 架构添加描述。目前 TimestampWithSplit.model_json_schema() 返回
{'properties': {'date': {'format': 'date', 'title': 'Date', 'type': 'string'},
                'time': {'format': 'time', 'title': 'Time', 'type': 'string'}},
 'required': ['date', 'time'],
 'type': 'object'}

并且我想添加

{'properties': {'date': {'format': 'date', 'title': 'Date', 'type': 'string', 'description': 'ISO format date, blah blah'},
                'time': {'format': 'time', 'title': 'Time', 'type': 'string', 'description': 'ISO format time, blah blah'}},
 'required': ['date', 'time'],
 'type': 'object'}
  1. 为日期字段添加自定义验证器,以便它可以解析个位数的日期和月份数字。我通常会这样做:
    def validator(value: str):
        try:
            return datetime.strptime(value, "%Y-%m-%d").date()
        except ValueError:
            return None

并将该验证器添加为字段上的普通验证器。但我不确定如何将其融入到我所拥有的内容中。

我是否走错了路?如何拥有一个模型,该模型将日期和时间作为单独的字段,但返回 datetime from model_validate_json ,同时还自定义 JSON 架构和日期验证?


对 Pydantic 模型的使用方式和想要实现的目标方面做得很好。但是,可以通过利用 Pydantic 提供的更多内置功能来简化的代码并实现想要的结果。

这是一个改进代码的更新版本,包括描述和自定义验证:

from datetime import datetime, date
from pydantic import BaseModel, validator, Field
from pydantic.types import Annotated

class TimestampWithSplit(BaseModel):
    date: Annotated[
        date,
        Field(
            description="ISO format date (YYYY-MM-DD). Single-digit days and months are allowed.", 
            example="2021-7-1"
        )
    ]
    time: Annotated[
        time, 
        Field(
            description="ISO format time (HH:MM:SS).", 
            example="12:36:23"
        )
    ]

    @validator("date", pre=True)
    def parse_date(cls, value: str) -> date:
        try:
            return datetime.strptime(value, "%Y-%m-%d").date()
        except ValueError:
            raise ValueError("Invalid date format. Please use YYYY-MM-DD.")

    @root_validator(pre=True)
    def combine_datetime(cls, values: dict) -> datetime:
        if "date" in values and "time" in values:
            values["root"] = datetime.combine(values["date"], values["time"])
        return values

    class Config:
        schema_extra = {
            "properties": {
                "date": {"description": "ISO format date (YYYY-MM-DD). Single-digit days and months are allowed."},
                "time": {"description": "ISO format time (HH:MM:SS)."},
            }
        }

让我们分解一下这段代码:

  1. description Field 中: 我们直接在 date time 字段中使用 Pydantic 的 Field 类来提供描述。这使的代码更简洁易读。

  2. example Field 中: description 类似,我们还可以在 Field 中提供 example ,以便在生成的架构中包含它。

  3. @validator 用于自定义验证: @validator("date", pre=True) 装饰器用于在解析输入字符串之前添加自定义验证逻辑。 pre=True 确保此验证器在任何其他验证之前运行。

  4. @root_validator 用于组合值: @root_validator(pre=True) 装饰器允许在所有字段验证后处理所有输入数据。我们使用它来组合 date time 字段以创建 datetime 对象,并将其存储在名为 root 的字段中。

  5. schema_extra 用于其他架构修改: Config 类中的 schema_extra 属性允许自定义生成的 JSON 模式。在这里,我们添加了日期和时间字段的描述。

现在,当使用 TimestampWithSplit.model_json_schema() 时,生成的架构将包含添加的描述以及 date time 字段的示例。

此设置还将使用的自定义验证逻辑正确解析日期,并且 model_validate_json 将返回一个带有 root 作为组合 datetime 对象的字典。

例如:

data = {"date": "2021-7-1", "time": "12:36:23"}
timestamp_obj = TimestampWithSplit.model_validate_json(data)
print(timestamp_obj)  # 输出:TimestampWithSplit(date=datetime.date(2021, 7, 1), time=datetime.time(12, 36, 23))
print(timestamp_obj.root)  # 输出:2021-07-01 12:36:23

此解决方案使的代码更简洁、更易读,同时利用 Pydantic 的内置功能来实现想要的结果。

标签:python,pydantic
From: 79020189

相关文章

  • Python升级后找不到uwsgi模块
    我的家庭服务器上运行着Flask/UWSGI应用程序。最近的Ubuntu升级删除了Python3.10并安装了Python3.12。我已经创建了一个新的venv并安装了该应用程序,但它不再运行。在UWSGI日志中,它显示:ModuleNotFoundError:Nomodulenamed'wsgi'我的应用程序称为sieve,工作......
  • Chameleon 模板不替换 python 变量
    我是使用FastAPI和Python的Chameleon新用户。我在模板中有以下代码片段:${ag.name}在python代码中,我有一个类定义为:classAgeGroupInfo:definit(self,名称:str,检查:str):self.name=姓名self.checked=check视图字典包含AgeGroupInfo对象的列表......
  • 基于父模型归档的 Pydantic 联合判别器
    我有这样的模型:classFoo(BaseModel):protocol:strprotocol_params:Union[ProtocolOneParam,ProtocolTwoParam]ProtocolOneParam和ProtocolTwoParam没有具有可区分值的相同字段,因此我可以将它们用作Discriminator,而我可以理解哪个模......
  • 如何在 Python 中获得类似 Cron 的调度程序?
    我正在寻找一个Python库,它将提供at和cron类似的功能。我很想有一个纯Python解决方案,而不是依赖于安装在盒子上的工具;这样我就可以在没有cron的机器上运行。对于那些不熟悉cron的人:您可以根据如下表达式来安排任务:02**7/usr/bin/run......
  • 我找不到一种方法让我的 python print 语句在几秒钟后自行删除
    我正在尝试制作一款基于文本的冒险游戏,我希望能够让文本自行删除。举个例子,游戏将使用print()语句打印文本,5秒后文本将被删除或对玩家隐藏。我试图找到其他人与此问题相关的问题,并且我找不到任何信息。我不知道该使用什么命令或与之相关的任何内容,请帮忙。Ivetriedtof......
  • 在 python 中可视化四元数
    我在无人机上安装了一个IMU,每0.1秒收集一次四元数数据(w,x,y,z)。现在我想将四元数数据与实际的无人机方向(视频数据)进行比较。所以我想创建某种盒子对象来显示基于四元数数据的方向。我实现了以下教程,将四元数转换为欧拉以进行可视化:https://www.youtube.com/watch?......
  • 有没有办法在 python 中获取特定的键盘输入
    我正在为学校开发一个项目,它目前有行输入(“按Enter继续”),它可以工作,但只要用户按Enter键程序继续,输入是什么并不重要,而且我我希望它仅在按下特定键时才起作用。我查了一下,曾经有一个键盘模块,但由于某种莫名其妙的原因它被删除了,那么还有其他方式获取输入吗?你绝对可以......
  • python+flask计算机毕业设计基于微信小程序的法律问题咨询系统设计与实现(程序+开题+论
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网的飞速发展和智能手机的普及,人们获取信息和解决问题的途径日益多样化。在法律服务领域,传统的线下咨询方式已难以满足公众日益增......
  • python+flask计算机毕业设计基于人脸识别的医疗保险系统的设计与实现(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着科技的飞速发展和人口老龄化的加剧,医疗保险系统面临着前所未有的挑战与机遇。传统医疗保险管理方式依赖于人工审核与纸质记录,不仅效率......
  • python+flask计算机毕业设计基于微信小程序的河南省美食分享平台(程序+开题+论文)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在移动互联网时代,智能手机和社交媒体已成为人们日常生活不可或缺的一部分。微信小程序作为腾讯推出的一种轻量级应用形态,凭借其无需安装、......