Required Fields¶
Set required=True when a value must be present.
Required fields raise Field.RequiredError when:
- You read
field.valuebefore assigning a valid value. - You create a
Modelwithout providing the required field. - You delete a required field from a model.
Default Values¶
Defaults can be static values or factories.
from datetime import UTC, datetime
import uuid
Field(default=0)
Field(default=uuid.uuid4)
Field(default=lambda: datetime.now(UTC))
Defaults are applied when:
- A standalone
Fieldis created. Field.reset()is called.- A
Modelis created without a value for that field. - A model field with a default is deleted.
Use has_default when you need to know whether a default was configured. Field(default=None).has_default is True.
Granted Values¶
Granted values always pass validation, even if later validators would reject them.
field = Field(grant=[None]).instance(str)
field.value = None
Model Field Typing¶
Model field types come from annotations.
from typing import Annotated
from dictify import Field, Model
class User(Model):
email: Annotated[
str,
"primary email",
Field(required=True).match(r".+@.+"),
]
age: Annotated[int | None, Field(default=None)]
When Field(...) is provided inside Annotated[...], it defines the model field without assigning a class value. Other metadata is ignored for runtime typing.
Direct assignment style remains supported for compatibility:
class User(Model):
email: str = Field(required=True).match(r".+@.+")
This style is fully supported at runtime. For strict static type checking, prefer Annotated[str, Field(...)]. Do not combine both forms for the same field.