2 changed files with 89 additions and 7 deletions
@ -19,11 +19,67 @@ Here's a general idea of how the models could look like with their password fiel |
|||||
{!./src/extra_models/tutorial001.py!} |
{!./src/extra_models/tutorial001.py!} |
||||
``` |
``` |
||||
|
|
||||
#### About `**user_dict` |
### About `**user_in.dict()` |
||||
|
|
||||
`UserInDB(**user_dict)` means: |
#### Pydantic's `.dict()` |
||||
|
|
||||
Pass the keys and values of the `user_dict` directly as key-value arguments, equivalent to: |
`user_in` is a Pydantic model of class `UserIn`. |
||||
|
|
||||
|
Pydantic models have a `.dict()` method that returns a `dict` with the model's data. |
||||
|
|
||||
|
So, if we create a Pydantic object `user_in` like: |
||||
|
|
||||
|
```Python |
||||
|
user_in = UserIn(username="john", password="secret", email="[email protected]") |
||||
|
``` |
||||
|
|
||||
|
and then we call: |
||||
|
|
||||
|
```Python |
||||
|
user_dict = user_in.dict() |
||||
|
``` |
||||
|
|
||||
|
we now have a `dict` with the data in the variable `user_dict` (it's a `dict` instead of a Pydantic model object). |
||||
|
|
||||
|
And if we call: |
||||
|
|
||||
|
```Python |
||||
|
print(user_dict) |
||||
|
``` |
||||
|
|
||||
|
we would get a Python `dict` with: |
||||
|
|
||||
|
```Python |
||||
|
{ |
||||
|
'username': 'john', |
||||
|
'password': 'secret', |
||||
|
'email': '[email protected]', |
||||
|
'full_name': None, |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
#### Unwrapping a `dict` |
||||
|
|
||||
|
If we take a `dict` like `user_dict` and pass it to a function (or class) with `**user_dict`, Python will "unwrap" it. It will pass the keys and values of the `user_dict` directly as key-value arguments. |
||||
|
|
||||
|
So, continuing with the `user_dict` from above, writing: |
||||
|
|
||||
|
```Python |
||||
|
UserInDB(**user_dict) |
||||
|
``` |
||||
|
|
||||
|
Would result in something equivalent to: |
||||
|
|
||||
|
```Python |
||||
|
UserInDB( |
||||
|
username="john", |
||||
|
password="secret", |
||||
|
email="[email protected]", |
||||
|
full_name=None, |
||||
|
) |
||||
|
``` |
||||
|
|
||||
|
Or more exactly, using `user_dict` directly, with whatever contents it might have in the future: |
||||
|
|
||||
```Python |
```Python |
||||
UserInDB( |
UserInDB( |
||||
@ -34,7 +90,28 @@ UserInDB( |
|||||
) |
) |
||||
``` |
``` |
||||
|
|
||||
And then adding the extra `hashed_password=hashed_password`, like in: |
#### A Pydantic model from the contents of another |
||||
|
|
||||
|
As in the example above we got `user_dict` from `user_in.dict()`, this code: |
||||
|
|
||||
|
```Python |
||||
|
user_dict = user_in.dict() |
||||
|
UserInDB(**user_dict) |
||||
|
``` |
||||
|
|
||||
|
would be equivalent to: |
||||
|
|
||||
|
```Python |
||||
|
UserInDB(**user_in.dict()) |
||||
|
``` |
||||
|
|
||||
|
...because `user_in.dict()` is a `dict`, and then we make Python "unwrap" it by passing it to `UserInDB` prepended with `**`. |
||||
|
|
||||
|
So, we get a Pydantic model from the data in another Pydantic model. |
||||
|
|
||||
|
#### Unrapping a `dict` and extra keywords |
||||
|
|
||||
|
And then adding the extra keyword argument `hashed_password=hashed_password`, like in: |
||||
|
|
||||
```Python |
```Python |
||||
UserInDB(**user_in.dict(), hashed_password=hashed_password) |
UserInDB(**user_in.dict(), hashed_password=hashed_password) |
||||
@ -65,7 +142,7 @@ And these models are all sharing a lot of the data and duplicating attribute nam |
|||||
|
|
||||
We could do better. |
We could do better. |
||||
|
|
||||
We can declare a `Userbase` model that serves as a base for our other models. And then we can make subclasses of that model that inherit its attributes (type declarations, validation, etc). |
We can declare a `UserBase` model that serves as a base for our other models. And then we can make subclasses of that model that inherit its attributes (type declarations, validation, etc). |
||||
|
|
||||
All the data conversion, validation, documentation, etc. will still work as normally. |
All the data conversion, validation, documentation, etc. will still work as normally. |
||||
|
|
||||
@ -77,4 +154,6 @@ That way, we can declare just the differences between the models (with plaintext |
|||||
|
|
||||
## Recap |
## Recap |
||||
|
|
||||
Use multiple Pydantic models and inherit freely for each case. You don't need to have a single data model per entity if that entity must be able to have different "states". As the case with the user "entity" with a state including `password`, `password_hash` and no password. |
Use multiple Pydantic models and inherit freely for each case. |
||||
|
|
||||
|
You don't need to have a single data model per entity if that entity must be able to have different "states". As the case with the user "entity" with a state including `password`, `password_hash` and no password. |
||||
|
Loading…
Reference in new issue