Create a field which is immutable after being set
Asked Answered
F

4

9

Is it possible to create a Pydantic field that does not have a default value and this value must be set on object instance creation and is immutable from then on?

e.g.

from pydantic import BaseModel

class User(BaseModel):
    user_id: int
    name: str

user = User(user_id=1, name='John')
user.user_id = 2 # raises immutable error
Fabrienne answered 10/1, 2022 at 6:38 Comment(0)
L
12

Pydantic already has the option you want. You can customize specific field by specifying allow_mutation to false. This raises a TypeError if the field is assigned on an instance.

from pydantic import BaseModel, Field


class User(BaseModel):
    user_id: int = Field(..., allow_mutation=False)
    name: str

    class Config:
        validate_assignment = True


user = User(user_id=1, name='John')
user.user_id = 2  # TypeError: "user_id" has allow_mutation set to False and cannot be assigned
Lm answered 10/1, 2022 at 12:9 Comment(0)
N
5

If you want to make all fields immutable, you can declare the class as being frozen

class User(BaseModel):
    user_id: int
    name: str
    class Config:
        frozen = True

However, this will make all fields immutable and not just a specific field

Neumark answered 10/1, 2022 at 6:47 Comment(1)
I am hoping just to have one field immutable. I am thinking of creating the immutable field as a private variable and then implementing a property.setter() mothod that raises an immatable exceptionFabrienne
A
3

You can try my solution below:

from pydantic import BaseModel, Field
class User(BaseModel):
    user_id: int
    name: str
    def setattr(cls, name, value):
        if name == "user_id": # or add more fiels here
            raise AttributeError("Cannot modify {}".format(name))
        else:
            return type.setattr(cls, name, value)

user = User(user_id=1, name='John')
user.user_id = 2 # raises immutable error
Azelea answered 10/1, 2022 at 7:55 Comment(0)
E
1

You now do this (in Pydantic v2) with the Field(frozen=True) kwarg (docs)

Immutability ¶

The parameter frozen is used to emulate the [frozen dataclass] behaviour. It is used to prevent the field from being assigned a new value after the model is created (immutability).

See the frozen dataclass documentation for more details.

from pydantic import BaseModel, Field, ValidationError


class User(BaseModel):
    name: str = Field(frozen=True)
    age: int


user = User(name='John', age=42)

try:
    user.name = 'Jane'  


except ValidationError as e:
    print(e)
    """
    1 validation error for User
    name
      Field is frozen [type=frozen_field, input_value='Jane', input_type=str]
    """
Erlene answered 22/8, 2023 at 20:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.