Create a field which is immutable after being set
Question:
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
Answers:
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
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
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
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
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
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
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