Skip to content

Instantly share code, notes, and snippets.

@mazlum
Last active May 6, 2021 14:55
Show Gist options
  • Save mazlum/7c73e4366f47e017ae13dc2c5a0673aa to your computer and use it in GitHub Desktop.
Save mazlum/7c73e4366f47e017ae13dc2c5a0673aa to your computer and use it in GitHub Desktop.
pydantic_like_rest_framework.py
from typing import Optional, Any, Dict, TYPE_CHECKING
from pydantic import BaseModel, validator, validate_model, PrivateAttr
from pydantic.error_wrappers import ValidationError
object_setattr = object.__setattr__
class Foobar(BaseModel):
_errors = PrivateAttr()
foo: str
bar: str
class Config:
orm_mode = True
validate_assignment = True
def __init__(__pydantic_self__, **data: Any) -> None:
"""
Create a new model by parsing and validating input data from keyword arguments.
Raises ValidationError if the input data cannot be parsed to form a valid model.
"""
# Uses something other than `self` the first arg to allow "self" as a settable attribute
values, fields_set, validation_error = validate_model(__pydantic_self__.__class__, data)
if validation_error:
object_setattr(__pydantic_self__, '_errors', validation_error)
try:
object_setattr(__pydantic_self__, '__dict__', values)
except TypeError as e:
raise TypeError(
'Model values must be a dict; you may not have returned a dictionary from a root validator'
) from e
object_setattr(__pydantic_self__, '__fields_set__', fields_set)
__pydantic_self__._init_private_attributes()
def is_valid(self, raise_exception=False):
if self._errors and raise_exception:
raise self._errors
return not bool(self._errors)
@property
def errors(self):
if not hasattr(self, '_errors'):
msg = 'You must call `.is_valid()` before accessing `.errors`.'
raise AssertionError(msg)
return self._errors.raw_errors
@property
def data(self):
return self.dict()
f = Foobar(foo='x')
f.is_valid(raise_exception=False)
print(f.errors)
print(f.data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment