web-dev-qa-db-fra.com

PyDantic: Comment transmettre la valeur par défaut à une variable si aucune n'a été adoptée?

Puis-je faire une valeur par défaut dans PyDantic si aucun n'est transmis dans le champ?

J'ai le code suivant, mais il me semble que le validateur ne fonctionne ici que sur l'initialisation du modèle et non autrement.

Mon code :

class User(BaseModel):
     name: Optional[str] = ''
     password: Optional[str] = ''
     email: EmailStr
    

    @validator('name')
    def set_name(cls, name):
        return name or 'foo'

Problème rencontré :

user = User(name=None, password='some_password', email='[email protected]')
print("Name is ", user.name)
# > 'Name is foo'

user.name = None
print("Name is ", user.name)
# > 'Name is None'

sortie souhaitée :

user = User(name='some_name', password='some_password', email='[email protected]')
user.name = None
print("Name is ", user.name)
# > 'Name is foo'

Des idées sur la manière dont je peux obtenir la sortie souhaitée? Je pense avoir des getters et des pigments aidera à résoudre le problème. Cependant, je ne pouvais pas les amener à travailler dans un modèle pydantique:

Tentative d'implémenter des getters and 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='[email protected]')
# > RecursionError: maximum recursion depth exceeded

J'ai également essayé le décorateur de la propriété :

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='[email protected]')
user.password = 'some_password'
# > ValueError: "User" object has no field "password"

J'ai aussi essayé d'écraser la 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='[email protected]')
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
6
Manas Sambare

De nombreuses façons d'attribuer une valeur par défaut

Méthode n ° 1: un champ requis id avec la valeur par défaut

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

méthode n ° 2 un champ optionnel id avec valeur par défaut

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

Méthode n ° 3: un champ requis id avec valeur par défaut

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

Méthode n ° 4: Un champ requis id avec la valeur par défaut de l'appelable. Ceci est utile pour générer des valeurs à la demande telles que unique UUIDs ou Timestamps. Voir @ Yagiz-degirmenci Réponse.

class User(BaseModel):
    id: str = Field(default_factory=uuid.uuid4)  # uuid.uuid4 is not executed immediately
2
Dev Sareno

Regarder dans l'ajout d'un __init__ Méthode à votre classe. Quelque chose comme

def __init__(self, name, pass, email):
    if pass is None:
        self.password = "foo"
    else:
        self.password = pass
    self.name = name
    self.email = email
0
Eric Canton