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

Add GetterDict example #2463

Merged
merged 2 commits into from
May 12, 2021
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
1 change: 1 addition & 0 deletions changes/2463-nuno-andre.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an example and a short explanation of subclassing `GetterDict` to docs.
43 changes: 43 additions & 0 deletions docs/examples/models_orm_mode_data_binding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from pydantic import BaseModel
from typing import Any, Optional
from pydantic.utils import GetterDict
from xml.etree.ElementTree import fromstring


xmlstring = """
<User Id="2138">
<FirstName />
<LoggedIn Value="true" />
</User>
"""


class UserGetter(GetterDict):

def get(self, key: str, default: Any) -> Any:

# element attributes
if key in {'Id', 'Status'}:
return self._obj.attrib.get(key, default)

# element children
else:
try:
return self._obj.find(key).attrib['Value']
except (AttributeError, KeyError):
return default


class User(BaseModel):
Id: int
Status: Optional[str]
FirstName: Optional[str]
LastName: Optional[str]
LoggedIn: bool

class Config:
orm_mode = True
getter_dict = UserGetter


user = User.from_orm(fromstring(xmlstring))
6 changes: 3 additions & 3 deletions docs/usage/model_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ Options:
[Field Types](types.md#arbitrary-types-allowed).

**`orm_mode`**
: whether to allow usage of [ORM mode](models.md#orm-mode)
: whether to allow usage of [ORM mode](models.md#orm-mode-aka-arbitrary-class-instances)

**`getter_dict`**
: a custom class (which should inherit from `GetterDict`) to use when decomposing ORM classes for validation,
for use with `orm_mode`
: a custom class (which should inherit from `GetterDict`) to use when decomposing arbitrary classes
for validation, for use with `orm_mode`; see [Data binding](models.md#data-binding).

**`alias_generator`**
: a callable that takes a field name and returns an alias for it
Expand Down
17 changes: 15 additions & 2 deletions docs/usage/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,27 @@ Here a vanilla class is used to demonstrate the principle, but any ORM class cou
```
_(This script is complete, it should run "as is")_

Arbitrary classes are processed by *pydantic* using the `GetterDict` class
(see [utils.py](https://github.com/samuelcolvin/pydantic/blob/master/pydantic/utils.py)), which attempts to

### Data binding

Arbitrary classes are processed by *pydantic* using the `GetterDict` class (see
[utils.py](https://github.com/samuelcolvin/pydantic/blob/master/pydantic/utils.py)), which attempts to
provide a dictionary-like interface to any class. You can customise how this works by setting your own
sub-class of `GetterDict` as the value of `Config.getter_dict` (see [config](model_config.md)).

You can also customise class validation using [root_validators](validators.md#root-validators) with `pre=True`.
In this case your validator function will be passed a `GetterDict` instance which you may copy and modify.

The `GetterDict` instance will be called for each field with a sentinel as a fallback (if no other default
value is set). Returning this sentinel means that the field is missing. Any other value will
be interpreted as the value of the field.

```py
{!.tmp_examples/models_orm_mode_data_binding.py!}
```
_(This script is complete, it should run "as is")_


## Error Handling

*pydantic* will raise `ValidationError` whenever it finds an error in the data it's validating.
Expand Down