首页 > 解决方案 > 用pydantic指定嵌套字典的最佳方法?

问题描述

语境

我正在尝试使用pydantic.

我想指定 dict 可以有一个 key daytime,或者没有。如果是这样,我希望 的值daytime同时包含sunrisesunset

例如,这些应该被允许:

{
   'type': 'solar',
   'daytime': {
      'sunrise': 4, # 4am
      'sunset': 18 # 6pm
   }
}

{
   'type': 'wind'
   # daytime key is omitted
}

{
   'type': 'wind',
   'daytime': None
}

但我想验证失败

{
   'type': 'solar',
   'daytime': {
      'sunrise': 4
   }
}

因为这有daytime值,但没有日落值。

MWE

我有一些代码可以做到这一点。如果我运行此脚本,它将成功执行。

from pydantic import BaseModel, ValidationError
from typing import List, Optional, Dict

class DayTime(BaseModel):
    sunrise: int
    sunset: int
    
class Plant(BaseModel):
    daytime: Optional[DayTime] = None
    type: str

p = Plant.parse_obj({'type': 'wind'})
p = Plant.parse_obj({'type': 'wind', 'daytime': None})
p = Plant.parse_obj({
    'type': 'solar', 
    'daytime': {
        'sunrise': 5, 
        'sunset': 18
    }})
    
try:
    p = Plant.parse_obj({
        'type': 'solar', 
        'daytime': {
            'sunrise': 5
        }})
except ValidationError:
    pass
else:
    raise AssertionError("Should have failed")

问题

我想知道的是, 这就是你应该如何使用 pydantic 来处理嵌套数据吗?

我有很多嵌套层,这似乎有点冗长。

有没有办法做一些更简洁的事情,比如:

class Plant(BaseModel):
    daytime: Optional[Dict[('sunrise', 'sunset'), int]] = None
    type: str

标签: pythonvalidationnestedfastapipydantic

解决方案


Pydanticcreate_model函数正是您所需要的:

from pydantic import BaseModel, create_model

class Plant(BaseModel):
    daytime: Optional[create_model('DayTime', sunrise=(int, ...), sunset=(int, ...))] = None
    type: str

推荐阅读