Skip to content

Commit

Permalink
stuff is working
Browse files Browse the repository at this point in the history
  • Loading branch information
nofalx committed Sep 9, 2023
1 parent db8e69e commit 1f929b0
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 30 deletions.
27 changes: 10 additions & 17 deletions ninja/operation.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Iterable,
List,
Optional,
Sequence,
Type,
Union,
cast,
)
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, List,
Optional, Sequence, Type, Union, cast)

import django
import pydantic
Expand Down Expand Up @@ -204,13 +193,17 @@ def _result_to_response(
return temporal_response

resp_object = ResponseObject(result)
# ^ we need object because getter_dict seems work only with from_orm
result = response_model.from_orm(resp_object).model_dump(
# ^ we need object because getter_dict seems work only with model_validate
result = response_model.model_validate(
resp_object
).model_dump(
by_alias=self.by_alias,
exclude_unset=self.exclude_unset,
exclude_defaults=self.exclude_defaults,
exclude_none=self.exclude_none,
)["response"]
)[
"response"
]
return self.api.create_response(
request, result, temporal_response=temporal_response
)
Expand Down Expand Up @@ -419,7 +412,7 @@ def _not_allowed(self) -> HttpResponse:


class ResponseObject:
"Basically this is just a helper to be able to pass response to pydantic's from_orm"
"Basically this is just a helper to be able to pass response to pydantic's model_validate"

def __init__(self, response: HttpResponse) -> None:
self.response = response
35 changes: 29 additions & 6 deletions ninja/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ def resolve_initials(self, obj):
return "".join(n[:1] for n in self.name.split())
"""
import copy
import warnings
from typing import Any, Callable, Dict, Type, TypeVar, Union, no_type_check

import pydantic
from django.db import models
from django.db.models import Manager, QuerySet
from django.db.models.fields.files import FieldFile
from django.template import Variable, VariableDoesNotExist
from pydantic import BaseModel, Field, ValidationInfo, model_validator, validator
from pydantic import (BaseModel, Field, ValidationInfo, model_validator,
validator)
from pydantic._internal._model_construction import ModelMetaclass
from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue

Expand Down Expand Up @@ -200,16 +201,38 @@ class Config:
from_attributes = True # aka orm_mode

@model_validator(mode="wrap")
def _run_root_validator2(cls, values: Any, handler: Callable, info: ValidationInfo) -> Any:
# we skip pydantic before validation if it is an orm object
if not (info and info.context and info.context.get("from_orm", False)):
def _run_root_validator(
cls, values: Any, handler: Callable, info: ValidationInfo
) -> Any:
print(info)
# we perform 'before' validations only if
is_dict = bool(
info and info.context and info.context.get("is_dict", False)
)
if not is_dict :
handler(values)
values = DjangoGetter(values, cls, info.context)
return handler(values)

@classmethod
def from_orm(cls: Type[S], obj: Any) -> S:
return cls.model_validate(obj, context={"from_orm":True})
return cls.model_validate(obj)

@classmethod
def model_validate(
cls: type[BaseModel],
obj: Any,
*args,
strict: bool | None = None,
from_attributes: bool | None = None,
context: dict[str, Any] | None = None,
) -> BaseModel:
context = context or {}
if not isinstance(obj, dict):
context = {"is_dict": True}
return super().model_validate(
obj, *args, strict=strict, from_attributes=from_attributes, context=context
)

def dict(self, *a: Any, **kw: Any) -> DictStrAny:
"Backward compatibility with pydantic 1.x"
Expand Down
10 changes: 3 additions & 7 deletions ninja/signature/details.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,8 @@
from pydantic_core import PydanticUndefined

from ninja import UploadedFile, params
from ninja.compatibility.util import (
UNION_TYPES,
get_args,
)
from ninja.compatibility.util import (
get_origin as get_collection_origin,
)
from ninja.compatibility.util import UNION_TYPES, get_args
from ninja.compatibility.util import get_origin as get_collection_origin
from ninja.errors import ConfigError
from ninja.params import Body, File, Form, _MultiPartBody
from ninja.params_models import TModel, TModels
Expand Down Expand Up @@ -164,6 +159,7 @@ def _create_models(self) -> TModels:
)

base_cls = param_cls._model
base_cls.model_config["from_attributes"] = True
model_cls = type(cls_name, (base_cls,), attrs)
# TODO: https://pydantic-docs.helpmanual.io/usage/models/#dynamic-model-creation - check if anything special in create_model method that I did not use
result.append(model_cls)
Expand Down

0 comments on commit 1f929b0

Please sign in to comment.