Benutzerdefinierte Pydantic v2-Typvalidatoren mit Informationen
Posted: 27 Dec 2024, 10:45
Ich versuche, meinen Code auf Pydantic v2 zu aktualisieren und habe Probleme, eine gute Möglichkeit zu finden, die benutzerdefinierten Typen zu replizieren, die ich in Version 1 hatte. Ich verwende meinen benutzerdefinierten Datumstyp als Beispiel. Die ursprüngliche Implementierung und Verwendung sah etwa so aus:
Ich habe versucht, den offiziellen Dokumenten und den hier unten aufgeführten Beispielen zu folgen, und es hat größtenteils funktioniert, aber der Parameter info verfügt nicht über die Felder, die ich benötige ( und field_name). Beim Versuch, darauf zuzugreifen, erhalte ich einen AttributeError.
Sowohl der Annotated- als auch der __get_pydantic_core_schema__-Ansatz weisen dieses Problem auf
Wenn ich nur die Funktion „validate_date als regulären field_validator einbinde, erhalte ich Informationen mit allen Feldern, die ich benötige, aber nur, wenn ich sie mit verwende benutzerdefinierte Typen, bei denen ich dieses Problem sehe. Wie schreibe ich einen benutzerdefinierten Typ, der Zugriff auf zuvor validierte Felder und den Namen des zu validierenden Felds hat?
Code: Select all
from datetime import date
from pydantic import BaseModel
class CustomDate(date):
# Override POTENTIAL_FORMATS and fill it with date format strings to match your data
POTENTIAL_FORMATS = []
@classmethod
def __get_validators__(cls):
yield cls.validate_date
@classmethod
def validate_date(cls, field_value, values, field, config) -> date:
if type(field_value) is date:
return field_value
return to_date(field.name, field_value, cls.POTENTIAL_FORMATS, return_str=False)
class ExampleModel(BaseModel):
class MyDate(CustomDate):
POTENTIAL_FORMATS = ['%Y-%m-%d', '%Y/%m/%d']
dt: MyDate
Code: Select all
data
Code: Select all
info.field_name
*** AttributeError: No attribute named 'field_name'
Code: Select all
from datetime import date
from typing import Annotated
from pydantic import BaseModel, BeforeValidator
from pydantic_core import core_schema
class CustomDate:
POTENTIAL_FORMATS = []
@classmethod
def validate(cls, field_value, info):
if type(field_value) is date:
return field_value
return to_date(info.field_name, field_value, potential_formats, return_str=False)
@classmethod
def __get_pydantic_core_schema__(cls, source, handler) -> core_schema.CoreSchema:
return core_schema.general_plain_validator_function(cls.validate)
def custom_date(potential_formats):
"""
:param potential_formats: A list of datetime format strings
"""
def validate_date(field_value, info) -> date:
if type(field_value) is date:
return field_value
return to_date(info.field_name, field_value, potential_formats, return_str=False)
CustomDate = Annotated[date, BeforeValidator(validate_date)]
return CustomDate
class ExampleModel(BaseModel):
class MyDate(CustomDate):
POTENTIAL_FORMATS = ['%Y-%m-%d', '%Y/%m/%d']
dt: MyDate
dt2: custom_date(['%Y-%m-%d', '%Y/%m/%d'])