Skip to content

pydantic

create_pydantic_field(field_name, model, model_field)

Registers pydantic field on through model that leads to passed model and is registered as field_name passed.

Through model is fetched from through attributed on passed model_field.

Parameters:

Name Type Description Default
field_name str

field name to register

required
model Type['Model']

type of field to register

required
model_field 'ManyToManyField'

relation field from which through model is extracted

required
Source code in ormar/models/helpers/pydantic.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def create_pydantic_field(
    field_name: str, model: Type["Model"], model_field: "ManyToManyField"
) -> None:
    """
    Registers pydantic field on through model that leads to passed model
    and is registered as field_name passed.

    Through model is fetched from through attributed on passed model_field.

    :param field_name: field name to register
    :type field_name: str
    :param model: type of field to register
    :type model: Model class
    :param model_field: relation field from which through model is extracted
    :type model_field: ManyToManyField class
    """
    model_field.through.__fields__[field_name] = ModelField(
        name=field_name,
        type_=model,
        model_config=model.__config__,
        required=False,
        class_validators={},
    )

get_potential_fields(attrs)

Gets all the fields in current class namespace that are Fields.

Parameters:

Name Type Description Default
attrs Union[Dict, MappingProxyType]

current class namespace

required

Returns:

Type Description
Dict

extracted fields that are ormar Fields

Source code in ormar/models/helpers/pydantic.py
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def get_potential_fields(attrs: Union[Dict, MappingProxyType]) -> Dict:
    """
    Gets all the fields in current class namespace that are Fields.

    :param attrs: current class namespace
    :type attrs: Dict
    :return: extracted fields that are ormar Fields
    :rtype: Dict
    """
    return {
        k: v
        for k, v in attrs.items()
        if (lenient_issubclass(v, BaseField) or isinstance(v, BaseField))
    }

get_pydantic_base_orm_config()

Returns empty pydantic Config with orm_mode set to True.

Returns:

Type Description
pydantic Config

empty default config with orm_mode set.

Source code in ormar/models/helpers/pydantic.py
126
127
128
129
130
131
132
133
134
135
136
137
138
def get_pydantic_base_orm_config() -> Type[pydantic.BaseConfig]:
    """
    Returns empty pydantic Config with orm_mode set to True.

    :return: empty default config with orm_mode set.
    :rtype: pydantic Config
    """

    class Config(pydantic.BaseConfig):
        orm_mode = True
        validate_assignment = True

    return Config

get_pydantic_field(field_name, model)

Extracts field type and if it's required from Model model_fields by passed field_name. Returns a pydantic field with type of field_name field type.

Parameters:

Name Type Description Default
field_name str

field name to fetch from Model and name of pydantic field

required
model Type['Model']

type of field to register

required

Returns:

Type Description
pydantic.ModelField

newly created pydantic field

Source code in ormar/models/helpers/pydantic.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def get_pydantic_field(field_name: str, model: Type["Model"]) -> "ModelField":
    """
    Extracts field type and if it's required from Model model_fields by passed
    field_name. Returns a pydantic field with type of field_name field type.

    :param field_name: field name to fetch from Model and name of pydantic field
    :type field_name: str
    :param model: type of field to register
    :type model: Model class
    :return: newly created pydantic field
    :rtype: pydantic.ModelField
    """
    type_ = model.Meta.model_fields[field_name].__type__
    return ModelField(
        name=field_name,
        type_=type_,  # type: ignore
        model_config=model.__config__,
        required=not model.Meta.model_fields[field_name].nullable,
        class_validators={},
    )

merge_or_generate_pydantic_config(attrs, name)

Checks if the user provided pydantic Config, and if he did merges it with the default one.

Updates the attrs in place with a new config.

Source code in ormar/models/helpers/pydantic.py
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def merge_or_generate_pydantic_config(attrs: Dict, name: str) -> None:
    """
    Checks if the user provided pydantic Config,
    and if he did merges it with the default one.

    Updates the attrs in place with a new config.

    :rtype: None
    """
    DefaultConfig = get_pydantic_base_orm_config()
    if "Config" in attrs:
        ProvidedConfig = attrs["Config"]
        if not inspect.isclass(ProvidedConfig):
            raise ModelDefinitionError(
                f"Config provided for class {name} has to be a class."
            )

        class Config(ProvidedConfig, DefaultConfig):  # type: ignore
            pass

        attrs["Config"] = Config
    else:
        attrs["Config"] = DefaultConfig

populate_pydantic_default_values(attrs)

Extracts ormar fields from annotations (deprecated) and from namespace dictionary of the class. Fields declared on model are all subclasses of the BaseField class.

Trigger conversion of ormar field into pydantic FieldInfo, which has all needed parameters saved.

Overwrites the annotations of ormar fields to corresponding types declared on ormar fields (constructed dynamically for relations). Those annotations are later used by pydantic to construct it's own fields.

Parameters:

Name Type Description Default
attrs Dict

current class namespace

required

Returns:

Type Description
Tuple[Dict, Dict]

namespace of the class updated, dict of extracted model_fields

Source code in ormar/models/helpers/pydantic.py
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def populate_pydantic_default_values(attrs: Dict) -> Tuple[Dict, Dict]:
    """
    Extracts ormar fields from annotations (deprecated) and from namespace
    dictionary of the class. Fields declared on model are all subclasses of the
    BaseField class.

    Trigger conversion of ormar field into pydantic FieldInfo, which has all needed
    parameters saved.

    Overwrites the annotations of ormar fields to corresponding types declared on
    ormar fields (constructed dynamically for relations).
    Those annotations are later used by pydantic to construct it's own fields.

    :param attrs: current class namespace
    :type attrs: Dict
    :return: namespace of the class updated, dict of extracted model_fields
    :rtype: Tuple[Dict, Dict]
    """
    model_fields = {}
    potential_fields = {}

    potential_fields.update(get_potential_fields(attrs))
    for field_name, field in potential_fields.items():
        field.name = field_name
        model_fields[field_name] = field
        default_type = (
            field.__type__ if not field.nullable else Optional[field.__type__]
        )
        overwrite_type = (
            field.__pydantic_type__
            if field.__type__ != field.__pydantic_type__
            else None
        )
        attrs["__annotations__"][field_name] = overwrite_type or default_type
    return attrs, model_fields

remove_excluded_parent_fields(model)

Removes pydantic fields that should be excluded from parent models

Parameters:

Name Type Description Default
model Type['Model'] required
Source code in ormar/models/helpers/pydantic.py
157
158
159
160
161
162
163
164
165
166
167
168
def remove_excluded_parent_fields(model: Type["Model"]) -> None:
    """
    Removes pydantic fields that should be excluded from parent models

    :param model:
    :type model: Type["Model"]
    """
    excludes = {*model.Meta.exclude_parent_fields} - {*model.Meta.model_fields.keys()}
    if excludes:
        model.__fields__ = {
            k: v for k, v in model.__fields__.items() if k not in excludes
        }