字典键和值的 Pydantic 可重用验证
Pydantic reusable Validation for Dictionary's keys and values
如何验证输入以获得以下 Dict
通过!
d = dict()
d['en'] = 'English content'
d['it'] = 'Italian content'
d['es'] = 'Spanish content'
print(d)
# {'en': 'English content', 'it': 'Italian content', 'es': 'Spanish content'}
在此示例中,密钥是 ISO 639-1 codes
使用 pycountry
python 包。
code = 'en'
pycountry.languages.get(alpha_2=code.upper()).alpha_2 # = 'en'
重点是如何使用 pydantic 可重用验证器或任何其他方法来验证 keys?
并验证 values 是 str
还是 int
?
Pydantic 模型 schema
应该与此示例 相似 :
# products/model.py
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from custom_field import Translatable
Base = declarative_base()
class Model(Base):
__tablename__ = "products"
id = Column(Integer, unique=True, index=True)
name = Column(Translatable())
price = Column(Integer)
# products/pydantic.py
from pydantic import BaseModel
import custom_pydantic_field
class BaseSchema(BaseModel):
id: int
class CreateSchema(BaseSchema):
name: custom_pydantic_field.translatable
price: int
记住在其他 models/schemas.
中的可重用性
创建华丽的定制class
# validators/translated_field.py
from typing import Dict
from pydantic import ValidationError
from pydantic.error_wrappers import ErrorWrapper
import pycountry
class Translatable(Dict):
"""
Validate Translation Dict Field (Json) where Language is Key and Translation as Value
Languages : ISO 639-1 code
Translation : Int, str, None
ref:
- https://pydantic-docs.helpmanual.io/usage/types/#classes-with-__get_validators__
By: Khalid Murad
"""
@property
def __translation_interface__(self):
return self.dict()
@classmethod
def __get_validators__(cls):
yield cls.validate
@classmethod
def validate(cls, base_dictionary):
result = dict()
dictionary = dict()
errors = []
dictionary = base_dictionary
for key in dictionary:
try:
parsed_language = pycountry.languages.get(alpha_2=key.upper())
except ValueError as exc:
errors.append(ErrorWrapper(Exception(f"Invalid language: {key}."), loc="language"))
if not parsed_language:
errors.append(ErrorWrapper(Exception(f"Invalid language: {key}."), loc="language"))
if isinstance(dictionary[key], int | str | None):
result[key] = dictionary[key]
else:
errors.append(ErrorWrapper(Exception(f"Invalid content for language: {key}."), loc=("language","content")))
if errors:
raise ValidationError(
errors,
cls,
)
return cls(result)
然后在您的 schema/pydantic 模型中使用它,例如:
# products/pydantic.py
from pydantic import BaseModel
from validators.translated_field import Translatable
class BaseSchema(BaseModel):
id: int
class CreateSchema(BaseSchema):
name: Translatable
...your code
并在 SQLALchemy 模型中使用正常的 JSON
字段!
# products/model.py
...
from sqlalchemy import Column, JSON
...
class Model(Base):
name = Column(JSON, nullable=True)
...
如何验证输入以获得以下 Dict
通过!
d = dict()
d['en'] = 'English content'
d['it'] = 'Italian content'
d['es'] = 'Spanish content'
print(d)
# {'en': 'English content', 'it': 'Italian content', 'es': 'Spanish content'}
在此示例中,密钥是 ISO 639-1 codes
使用 pycountry
python 包。
code = 'en'
pycountry.languages.get(alpha_2=code.upper()).alpha_2 # = 'en'
重点是如何使用 pydantic 可重用验证器或任何其他方法来验证 keys?
并验证 values 是 str
还是 int
?
Pydantic 模型 schema
应该与此示例 相似 :
# products/model.py
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from custom_field import Translatable
Base = declarative_base()
class Model(Base):
__tablename__ = "products"
id = Column(Integer, unique=True, index=True)
name = Column(Translatable())
price = Column(Integer)
# products/pydantic.py
from pydantic import BaseModel
import custom_pydantic_field
class BaseSchema(BaseModel):
id: int
class CreateSchema(BaseSchema):
name: custom_pydantic_field.translatable
price: int
记住在其他 models/schemas.
中的可重用性创建华丽的定制class
# validators/translated_field.py
from typing import Dict
from pydantic import ValidationError
from pydantic.error_wrappers import ErrorWrapper
import pycountry
class Translatable(Dict):
"""
Validate Translation Dict Field (Json) where Language is Key and Translation as Value
Languages : ISO 639-1 code
Translation : Int, str, None
ref:
- https://pydantic-docs.helpmanual.io/usage/types/#classes-with-__get_validators__
By: Khalid Murad
"""
@property
def __translation_interface__(self):
return self.dict()
@classmethod
def __get_validators__(cls):
yield cls.validate
@classmethod
def validate(cls, base_dictionary):
result = dict()
dictionary = dict()
errors = []
dictionary = base_dictionary
for key in dictionary:
try:
parsed_language = pycountry.languages.get(alpha_2=key.upper())
except ValueError as exc:
errors.append(ErrorWrapper(Exception(f"Invalid language: {key}."), loc="language"))
if not parsed_language:
errors.append(ErrorWrapper(Exception(f"Invalid language: {key}."), loc="language"))
if isinstance(dictionary[key], int | str | None):
result[key] = dictionary[key]
else:
errors.append(ErrorWrapper(Exception(f"Invalid content for language: {key}."), loc=("language","content")))
if errors:
raise ValidationError(
errors,
cls,
)
return cls(result)
然后在您的 schema/pydantic 模型中使用它,例如:
# products/pydantic.py
from pydantic import BaseModel
from validators.translated_field import Translatable
class BaseSchema(BaseModel):
id: int
class CreateSchema(BaseSchema):
name: Translatable
...your code
并在 SQLALchemy 模型中使用正常的 JSON
字段!
# products/model.py
...
from sqlalchemy import Column, JSON
...
class Model(Base):
name = Column(JSON, nullable=True)
...