Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

1.3K
Views
Pydantic: ¿Cómo pasar el valor predeterminado a una variable si no se pasó Ninguno?

¿Puedo hacer un valor predeterminado en Pydantic si se pasa Ninguno en el campo?

Tengo el siguiente código, pero me parece que el validador aquí solo funciona en la inicialización del modelo y no de otra manera.

Mi código:

 class User(BaseModel): name: Optional[str] = '' password: Optional[str] = '' email: EmailStr @validator('name') def set_name(cls, name): return name or 'foo'

Problema encontrado:

 user = User(name=None, password='some_password', email='user@example.com') print("Name is ", user.name) # > 'Name is foo' user.name = None print("Name is ", user.name) # > 'Name is None'

Salida deseada:

 user = User(name='some_name', password='some_password', email='user@example.com') user.name = None print("Name is ", user.name) # > 'Name is foo'

¿Alguna idea sobre cómo puedo obtener el resultado deseado? Creo que tener getters y setters ayudará a abordar el problema. Sin embargo, no pude hacer que funcionaran en un modelo Pydantic:

Intentando implementar getters y setters:

 class User(BaseModel): name: Optional[str] = '' password: Optional[str] = '' email: EmailStr def get_password(self): return self.password def set_password(self, password): self.password = hash_password(password) password = property(get_password, set_password) user = User(name='some_name', password='some_password', email='user@example.com') # > RecursionError: maximum recursion depth exceeded

También probé el decorador de propiedades:

 class User(BaseModel): name: Optional[str] = '' password: Optional[str] = '' email: EmailStr @property def password(self): return self._password @password.setter def password(self, password): pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") self._password = pwd_context.hash(password) user = User(name='some_name', email='user@example.com') user.password = 'some_password' # > ValueError: "User" object has no field "password"

También intenté sobrescribir el init :

 class User(BaseModel): name: Optional[str] = "" password: Optional[str] = "" email: EmailStr def __init__(self, name, password, email): pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") password = pwd_context.hash(password) super().__init__(name=name, password=password, email=email) user = User(name="some_name", password="some_password", email='user@example.com') print(user.password) # > AYylwSnbQgCHrl4uue6kO7yiuT20lazSzK7x # Works as expected user.password = "some_other_password" print(user.password) # > "some_other_password" # Does not work user.password = None print(user.password) # > None # Does not work either
over 4 years ago · Santiago Trujillo
4 answers
Answer question

0

Considere agregar un método __init__ a su clase. Algo como

 def __init__(self, name, pass, email): if pass is None: self.password = "foo" else: self.password = pass self.name = name self.email = email
over 4 years ago · Santiago Trujillo Report

0

Debe habilitar la opción de validate_assignment en la configuración del modelo:

 from typing import Optional from pydantic import BaseModel, validator class User(BaseModel): name: Optional[str] = '' password: Optional[str] = '' class Config: validate_assignment = True @validator('name') def set_name(cls, name): return name or 'foo' user = User(name=None, password='some_password', ) print("Name is ", user.name) user.name = None print("Name is ", user.name)
 Name is foo Name is foo
over 4 years ago · Santiago Trujillo Report

0

Esta pregunta se hizo perfectamente, así que quería dar un ejemplo más amplio, porque hay muchas formas de asignar un valor dinámicamente.

La respuesta de Alex es correcta, pero solo funciona cuando el campo hereda directamente una clase de datos, más específicamente, algo como esto no funcionará.

 class User(BaseModel): name: Optional[str] = "" password: Optional[str] = "" class Config: validate_assignment = True @validator("name") def set_name(cls, name): return name or "bar" user_dict = {"password": "so_secret"} user_one = User(**user_dict) Out: name='' password='so_secret'

Validar siempre

Por razones de rendimiento, de forma predeterminada, no se llama a los validadores para los campos cuando no se proporciona un valor. Pero en situaciones como esta, cuando necesita establecer un valor predeterminado dinámico , podemos establecerlo en True

 class User(BaseModel): name: Optional[str] = "" @validator("name", pre=True, always=True) def set_name(cls, name): return name or "bar" In: user_one = User(name=None) In: user_two = User() Out: name='bar' Out: name='bar'

Pero hay un problema importante con always, ya que estamos usando always=True pydantic intentaría validar el valor predeterminado None, lo que provocaría un error.

Al configurar Pre en True , llamará a ese campo antes de que ocurra un error de validación, el valor predeterminado de un validador pre se establece en False , en cuyo caso se llaman después de la validación del campo.

Uso de configuración

Pero esto tiene algunas desventajas.

 class User(BaseModel): name: Optional[str] = "" class Config: validate_assignment = True @validator("name") def set_name(cls, name): return name or "foo" In: user = User(name=None) Out: name='foo'

Cuando lo establece en Ninguno, devuelve el valor dinámico correctamente, pero en algunas situaciones, como si fuera completamente None , falla.

 In: user = User() Out: name=''

Una vez más, debe configurar para que funcione.

 pre=True always=True

Usando default_factory

Esto es principalmente útil en los casos en que desea establecer un valor predeterminado, como UUID o fecha y hora, etc. En esos casos, es posible que desee usar default_factory , pero hay un problema importante: no puede asignar un argumento Callable a default_factory.

 class User(BaseModel): created_at: datetime = Field(default_factory=datetime.now) In: user = User() Out: created_at=datetime.datetime(2020, 8, 29, 2, 40, 12, 780986)
over 4 years ago · Santiago Trujillo Report

0

Muchas formas de asignar un valor predeterminado

Método #1: Un campo de id requerido con valor predeterminado

 class User(BaseModel): id: str = uuid.uuid4()

Método #2 Un campo de id opcional con valor predeterminado

 class User(BaseModel): id: Optional[str] = uuid.uuid4()

Método #3: Un campo de id requerido con valor predeterminado

 class User(BaseModel): id: str = Field(default=uuid.uuid4())

Método n.º 4: un campo de id obligatorio con un valor predeterminado de invocable. Esto es útil para generar valores a pedido, como unique UUIDs o marcas de Timestamps . Vea la respuesta de @yagiz-degirmenci.

 class User(BaseModel): id: str = Field(default_factory=uuid.uuid4) # uuid.uuid4 is not executed immediately
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!