inherit choices validators and class validators for fields in generated pydantic models

This commit is contained in:
collerek
2021-10-11 16:22:50 +02:00
parent f6458be157
commit 9559c0f7f6
6 changed files with 46 additions and 25 deletions

View File

@ -50,9 +50,10 @@ def get_pydantic_field(field_name: str, model: Type["Model"]) -> "ModelField":
:return: newly created pydantic field
:rtype: pydantic.ModelField
"""
type_ = model.Meta.model_fields[field_name].__type__
return ModelField(
name=field_name,
type_=model.Meta.model_fields[field_name].__type__, # type: ignore
type_=type_, # type: ignore
model_config=model.__config__,
required=not model.Meta.model_fields[field_name].nullable,
class_validators={},

View File

@ -101,6 +101,7 @@ def register_reverse_model_fields(model_field: "ForeignKeyField") -> None:
:type model_field: relation Field
"""
related_name = model_field.get_related_name()
# TODO: Reverse relations does not register pydantic fields?
if model_field.is_multi:
model_field.to.Meta.model_fields[related_name] = ManyToMany( # type: ignore
model_field.owner,

View File

@ -1,3 +1,4 @@
import copy
import string
from random import choices
from typing import (
@ -82,7 +83,9 @@ class PydanticMixin(RelationMixin):
(pydantic.BaseModel,),
{"__annotations__": fields_dict, **defaults},
)
return cast(Type[pydantic.BaseModel], model)
model = cast(Type[pydantic.BaseModel], model)
cls._copy_field_validators(model=model)
return model
@classmethod
def _determine_pydantic_field_type(
@ -111,3 +114,33 @@ class PydanticMixin(RelationMixin):
if target is not None and field.nullable:
target = Optional[target]
return target
@classmethod
def _copy_field_validators(cls, model: Type[pydantic.BaseModel]) -> None:
"""
Copy field validators from ormar model to generated pydantic model.
"""
for field_name, field in model.__fields__.items():
if (
field_name not in cls.__fields__
or cls.Meta.model_fields[field_name].is_relation
):
continue
validators = cls.__fields__[field_name].validators
already_attached = [
validator.__wrapped__ for validator in field.validators # type: ignore
]
validators_to_copy = [
validator
for validator in validators
if validator.__wrapped__ not in already_attached # type: ignore
]
field.validators.extend(copy.deepcopy(validators_to_copy))
class_validators = cls.__fields__[field_name].class_validators
field.class_validators.update(copy.deepcopy(class_validators))
field.pre_validators = copy.deepcopy(
cls.__fields__[field_name].pre_validators
)
field.post_validators = copy.deepcopy(
cls.__fields__[field_name].post_validators
)