Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Schema Validation Refactor #9

Merged
merged 4 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ninja_schema/orm/getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.db.models import Manager, QuerySet
from django.db.models.fields.files import FieldFile

from ..pydanticutils import IS_PYDANTIC_V1
from ninja_schema.pydanticutils import IS_PYDANTIC_V1

__all__ = [
"DjangoGetter",
Expand Down
45 changes: 39 additions & 6 deletions ninja_schema/orm/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@

from django.db.models import Model as DjangoModel

from ..pydanticutils import IS_PYDANTIC_V1
from ..types import DictStrAny
from .getters import DjangoGetter
from ninja_schema.orm.getters import DjangoGetter
from ninja_schema.pydanticutils import IS_PYDANTIC_V1
from ninja_schema.types import DictStrAny

if t.TYPE_CHECKING:
from pydantic.functional_validators import ModelWrapValidatorHandler

ModelWrapValidatorHandlerAny = t.TypeVar(
"ModelWrapValidatorHandlerAny", bound=ModelWrapValidatorHandler[t.Any]
)


class BaseMixins:
Expand All @@ -22,10 +29,36 @@ def apply_to_model(
from pydantic_core.core_schema import ValidationInfo

class BaseMixinsV2(BaseMixins):
@model_validator(mode="before")
def _run_root_validator(cls, values: t.Any, info: ValidationInfo) -> t.Any:
model_config: t.Dict[str, t.Any]

@model_validator(mode="wrap")
@classmethod
def _run_root_validator(
cls,
values: t.Any,
handler: "ModelWrapValidatorHandlerAny",
info: ValidationInfo,
) -> t.Any:
"""
If Pydantic intends to validate against the __dict__ of the immediate Schema
object, then we need to call `handler` directly on `values` before the conversion
to DjangoGetter, since any checks or modifications on DjangoGetter's __dict__
will not persist to the original object.
"""
forbids_extra = cls.model_config.get("extra") == "forbid"
should_validate_assignment = cls.model_config.get(
"validate_assignment", False
)
if forbids_extra or should_validate_assignment:
handler(values)

values = DjangoGetter(values, cls, info.context)
return values
return handler(values)

# @model_validator(mode="before")
# def _run_root_validator(cls, values: t.Any, info: ValidationInfo) -> t.Any:
# values = DjangoGetter(values, cls, info.context)
# return values

@classmethod
def from_orm(cls, obj: t.Any, **options: t.Any) -> BaseModel:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ test = [
"pytest-cov",
"pytest-django",
"pytest-asyncio",
"mypy == 1.11.1",
"mypy == 1.13.0",
"ruff == 0.7.4",
"django-stubs",
]
Expand Down
Loading