Skip to content

validation

construct_schema_function()

Modifies model example and description if needed.

Note that schema extra has to be a function, otherwise it's called to soon before all the relations are expanded.

:return: callable that will be run by pydantic to modify the schema :rtype: Callable

Source code in ormar/models/helpers/validation.py
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
def construct_schema_function() -> Callable:
    """
    Modifies model example and description if needed.

    Note that schema extra has to be a function, otherwise it's called to soon
    before all the relations are expanded.

    :return: callable that will be run by pydantic to modify the schema
    :rtype: Callable
    """

    def schema_extra(schema: Dict[str, Any], model: Type["Model"]) -> None:
        overwrite_example_and_description(schema=schema, model=model)
        overwrite_binary_format(schema=schema, model=model)

    return staticmethod(schema_extra)  # type: ignore

generate_example_for_nested_types(type_)

Process nested types like Union[X, Y] or List[X]

Source code in ormar/models/helpers/validation.py
150
151
152
153
154
155
156
157
def generate_example_for_nested_types(type_: Any) -> Any:
    """
    Process nested types like Union[X, Y] or List[X]
    """
    if type_.__origin__ == Union:
        return generate_example_for_union(type_=type_)
    if type_.__origin__ is list:
        return [get_pydantic_example_repr(type_.__args__[0])]

generate_example_for_union(type_)

Generates a pydantic example for Union[X, Y, ...]. Note that Optional can also be set as Union[X, None]

Source code in ormar/models/helpers/validation.py
160
161
162
163
164
165
166
167
168
def generate_example_for_union(type_: Any) -> Any:
    """
    Generates a pydantic example for Union[X, Y, ...].
    Note that Optional can also be set as Union[X, None]
    """
    values = tuple(
        get_pydantic_example_repr(x) for x in type_.__args__ if x is not type(None)
    )
    return values[0] if len(values) == 1 else values

generate_model_example(model, relation_map=None)

Generates example to be included in schema in fastapi.

:param model: ormar.Model :type model: Type["Model"] :param relation_map: dict with relations to follow :type relation_map: Optional[Dict] :return: dict with example values :rtype: Dict[str, int]

Source code in ormar/models/helpers/validation.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
def generate_model_example(
    model: Type["Model"], relation_map: Optional[Dict] = None
) -> Dict:
    """
    Generates example to be included in schema in fastapi.

    :param model: ormar.Model
    :type model: Type["Model"]
    :param relation_map: dict with relations to follow
    :type relation_map: Optional[Dict]
    :return: dict with example values
    :rtype: Dict[str, int]
    """
    example: Dict[str, Any] = dict()
    relation_map = (
        relation_map
        if relation_map is not None
        else translate_list_to_dict(model._iterate_related_models())
    )
    for name, field in model.ormar_config.model_fields.items():
        populates_sample_fields_values(
            example=example, name=name, field=field, relation_map=relation_map
        )
    to_exclude = {name for name in model.ormar_config.model_fields}
    pydantic_repr = generate_pydantic_example(pydantic_model=model, exclude=to_exclude)
    example.update(pydantic_repr)

    return example

generate_pydantic_example(pydantic_model, exclude=None)

Generates dict with example.

:param pydantic_model: model to parse :type pydantic_model: Type[pydantic.BaseModel] :param exclude: list of fields to exclude :type exclude: Optional[Set] :return: dict with fields and sample values :rtype: Dict

Source code in ormar/models/helpers/validation.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def generate_pydantic_example(
    pydantic_model: Type[pydantic.BaseModel], exclude: Optional[Set] = None
) -> Dict:
    """
    Generates dict with example.

    :param pydantic_model: model to parse
    :type pydantic_model: Type[pydantic.BaseModel]
    :param exclude: list of fields to exclude
    :type exclude: Optional[Set]
    :return: dict with fields and sample values
    :rtype: Dict
    """
    example: Dict[str, Any] = dict()
    exclude = exclude or set()
    name_to_check = [
        name for name in pydantic_model.model_fields if name not in exclude
    ]
    for name in name_to_check:
        field = pydantic_model.model_fields[name]
        type_ = field.annotation
        example[name] = get_pydantic_example_repr(type_)
    return example

get_nested_model_example(name, field, relation_map)

Gets representation of nested model.

:param name: name of the field to follow :type name: str :param field: ormar field :type field: BaseField :param relation_map: dict with relation map :type relation_map: Dict :return: nested model or list of nested model repr :rtype: Union[List, Dict]

Source code in ormar/models/helpers/validation.py
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def get_nested_model_example(
    name: str, field: "BaseField", relation_map: Dict
) -> Union[List, Dict]:
    """
    Gets representation of nested model.

    :param name: name of the field to follow
    :type name: str
    :param field: ormar field
    :type field: BaseField
    :param relation_map: dict with relation map
    :type relation_map: Dict
    :return: nested model or list of nested model repr
    :rtype: Union[List, Dict]
    """
    value = generate_model_example(field.to, relation_map=relation_map.get(name, {}))
    new_value: Union[List, Dict] = [value] if field.is_multi or field.virtual else value
    return new_value

get_pydantic_example_repr(type_)

Gets sample representation of pydantic field for example dict.

:param type_: type of pydantic field :type type_: Any :return: representation to include in example :rtype: Any

Source code in ormar/models/helpers/validation.py
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
def get_pydantic_example_repr(type_: Any) -> Any:
    """
    Gets sample representation of pydantic field for example dict.

    :param type_: type of pydantic field
    :type type_: Any
    :return: representation to include in example
    :rtype: Any
    """
    if hasattr(type_, "__origin__"):
        return generate_example_for_nested_types(type_)
    if issubclass(type_, (numbers.Number, decimal.Decimal)):
        return 0
    if issubclass(type_, pydantic.BaseModel):
        return generate_pydantic_example(pydantic_model=type_)
    return "string"

modify_schema_example(model)

Modifies the schema example in openapi schema.

:param model: newly constructed Model :type model: Model class

Source code in ormar/models/helpers/validation.py
222
223
224
225
226
227
228
229
230
def modify_schema_example(model: Type["Model"]) -> None:  # noqa CCR001
    """
    Modifies the schema example in openapi schema.

    :param model: newly constructed Model
    :type model: Model class
    """
    if not config_field_not_set(model=model, field_name="model_fields"):
        model.model_config["json_schema_extra"] = construct_schema_function()

overwrite_binary_format(schema, model)

Overwrites format of the field if it's a LargeBinary field with a flag to represent the field as base64 encoded string.

:param schema: schema of current model :type schema: Dict[str, Any] :param model: model class :type model: Type["Model"]

Source code in ormar/models/helpers/validation.py
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
def overwrite_binary_format(schema: Dict[str, Any], model: Type["Model"]) -> None:
    """
    Overwrites format of the field if it's a LargeBinary field with
    a flag to represent the field as base64 encoded string.

    :param schema: schema of current model
    :type schema: Dict[str, Any]
    :param model: model class
    :type model: Type["Model"]
    """
    for field_id, prop in schema.get("properties", {}).items():
        if (
            field_id in model._bytes_fields
            and model.ormar_config.model_fields[field_id].represent_as_base64_str
        ):
            prop["format"] = "base64"

overwrite_example_and_description(schema, model)

Overwrites the example with properly nested children models. Overwrites the description if it's taken from ormar.Model.

:param schema: schema of current model :type schema: Dict[str, Any] :param model: model class :type model: Type["Model"]

Source code in ormar/models/helpers/validation.py
171
172
173
174
175
176
177
178
179
180
181
182
183
def overwrite_example_and_description(
    schema: Dict[str, Any], model: Type["Model"]
) -> None:
    """
    Overwrites the example with properly nested children models.
    Overwrites the description if it's taken from ormar.Model.

    :param schema: schema of current model
    :type schema: Dict[str, Any]
    :param model: model class
    :type model: Type["Model"]
    """
    schema["example"] = generate_model_example(model=model)

populates_sample_fields_values(example, name, field, relation_map=None)

Iterates the field and sets fields to sample values

:param field: ormar field :type field: BaseField :param name: name of the field :type name: str :param example: example dict :type example: Dict[str, Any] :param relation_map: dict with relations to follow :type relation_map: Optional[Dict]

Source code in ormar/models/helpers/validation.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def populates_sample_fields_values(
    example: Dict[str, Any],
    name: str,
    field: "BaseField",
    relation_map: Optional[Dict] = None,
) -> None:
    """
    Iterates the field and sets fields to sample values

    :param field: ormar field
    :type field: BaseField
    :param name: name of the field
    :type name: str
    :param example: example dict
    :type example: Dict[str, Any]
    :param relation_map: dict with relations to follow
    :type relation_map: Optional[Dict]
    """
    if not field.is_relation:
        is_bytes_str = field.__type__ is bytes and field.represent_as_base64_str
        example[name] = field.__sample__ if not is_bytes_str else "string"
    elif isinstance(relation_map, dict) and name in relation_map:
        example[name] = get_nested_model_example(
            name=name, field=field, relation_map=relation_map
        )