16

Is there any obvious to validate a pydantic model after some changing some attribute?

Say I create a simple Model and object:

from pydantic import BaseModel

class A(BaseModel):
    b: int = 0

a=A()

Then edit it, so that it is actually invalid:

a.b = "foobar"

Can I force a re-validation and expect a ValidationError to be raised?

I tried

A.validate(a)                      # no error
a.copy(update=dict(b='foobar'))    # no error

What did work was

A(**dict(a._iter()))

ValidationError: 1 validation error for A
b
  value is not a valid integer (type=type_error.integer)

But that is not really straightforward and I need to use the supposedly private method _iter.

Is there a clean alternative?

lordvlad
  • 5,200
  • 1
  • 24
  • 44
  • 1
    Do you need only the pydantic library? I made the data class for validation easier. There's that: https://github.com/EvgeniyBurdin/validated_dc – Evgeniy_Burdin May 26 '20 at 15:44

1 Answers1

22

pydantic can do this for you, you just need validate_assignment:

from pydantic import BaseModel

class A(BaseModel):
    b: int = 0

    class Config:
        validate_assignment = True
SColvin
  • 11,584
  • 6
  • 57
  • 71
  • 4
    Do you have any insights into the design decision regarding this? That is, why is `validate_assignment` (and `validate_all` for that matter) `False` by default? I'm a huge Pydantic fan but was a bit surprised to learn about this because I thought that Pydantic would be more, well, pedantic (at least by default)... – Paul P May 10 '22 at 12:05
  • 2
    The problem I have with this is with root validators that validate multiple fields together. For example, I have a model with start/stop fields. In a root validator, I'm enforcing start<=stop. Say I initialize a model with start=1 and stop=2. I then want to change it to start=3 and stop=4. That's not possible (or it's cumbersome and hacky to resolve) because if I set start first, it will fail validation (start=3 stop=2). – Taylor Vance Feb 01 '23 at 14:02
  • 2
    @TaylorVance, I was stuck on that same question for a while as well. Finally came up with a couple approaches to address it that worked well for me. Check out this answer: https://stackoverflow.com/a/75451357/16448566 – Zachary Duvall Apr 02 '23 at 14:27