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

Access to orm_mode object in root validator #821

dmontagu opened this issue Sep 18, 2019 · 2 comments

Access to orm_mode object in root validator #821

dmontagu opened this issue Sep 18, 2019 · 2 comments


Copy link

@dmontagu dmontagu commented Sep 18, 2019

Feature Request

It would be nice if you could access the "source" object in a root_validator (coming soon; see #817) when the model was being initialized via a call to from_orm. This would enable almost any form of custom loading from an orm object possible by use of a root validator.

I think this can be accomplished now by making changes only to the GetterDict class:

class GetterDict:
    Hack to make object's smell just enough like dicts for validate_model.

    __slots__ = ('_obj', '_overrides')

    def __init__(self, obj: Any):
        self._obj = obj
        self._overrides: Optional[Dict] = None  # NEWLY ADDED

    def source_object(self):
        return self._obj

    def __setitem__(self, key, value):
        if self._overrides is None:
            self._overrides = {}
        self._overrides.__setitem__(key, value)

    def get(self, item: Any, default: Any) -> Any:
        if self._overrides is None:
            # This check could be removed if we make the _overrides non-optional
            # but I think that would come with a *slightly* larger performance penalty if not used
            return getattr(self._obj, item, default)
        return self._overrides.get(item) or getattr(self._obj, item, default)

    def keys(self) -> Set[Any]:
        We don't want to get any other attributes of obj if the model didn't explicitly ask for them
        return set()

The only performance sacrifice if not making use of the feature is the check if self._overrides is None (it seems to me like the impact would be miniscule in practice).

This would allow things like:

from pydantic import BaseModel, Schema, root_validator
from pydantic.utils import GetterDict

class MyModelORM:
    def __init__(self, x):
        self.x = x

    def orm_property(self) -> str:
        return "hello"

class MyModel(BaseModel):
    x: int
    y: str = Schema(None)

    def get_y(cls, values):
        if isinstance(values, GetterDict):
            # This is how you know it got called via from_orm
            values['y'] = values.source_object().orm_property
        return values

    class Config:
        orm_mode = True

# MyModel x=1 y='hello'

@samuelcolvin I can't think of any breaking changes this would introduce, can you? Would this be interesting to you?

@dmontagu dmontagu mentioned this issue Sep 18, 2019
8 of 8 tasks complete

This comment has been minimized.

Copy link
Collaborator Author

@dmontagu dmontagu commented Sep 18, 2019

Also, it might make sense to change the name of GetterDict to OrmGetterDict if this is the only way it is used. (And maybe to OrmDict if it now supports setting, as above.)


This comment has been minimized.

Copy link

@samuelcolvin samuelcolvin commented Sep 20, 2019

Please review #822, I've tried to implement what you need a PR into the existing #817 PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
2 participants
You can’t perform that action at this time.