Replace custom field validators with Extra.forbid by @anton-shum
This commit is contained in:
43
README.md
43
README.md
@@ -664,28 +664,17 @@ print(type(post.content))
|
|||||||
# OUTPUT: Article
|
# OUTPUT: Article
|
||||||
# Article is very inclusive and all fields are optional, allowing any dict to become valid
|
# Article is very inclusive and all fields are optional, allowing any dict to become valid
|
||||||
```
|
```
|
||||||
**Not Terrible Solutions:**
|
**Solutions:**
|
||||||
1. Order field types properly: from the most strict ones to loose ones.
|
1. Validate input has only valid fields
|
||||||
```python
|
```python
|
||||||
class Post(BaseModel):
|
from pydantic import BaseModel, Extra, root_validator
|
||||||
content: Video | Article
|
|
||||||
```
|
|
||||||
2. Validate input has only valid fields
|
|
||||||
```python
|
|
||||||
from pydantic import BaseModel, root_validator
|
|
||||||
|
|
||||||
class Article(BaseModel):
|
class Article(BaseModel):
|
||||||
text: str | None
|
text: str | None
|
||||||
extra: str | None
|
extra: str | None
|
||||||
|
|
||||||
@root_validator(pre=True) # validate all values before pydantic
|
class Config:
|
||||||
def has_only_article_fields(cls, data: dict):
|
extra = Extra.forbid
|
||||||
"""Silly and ugly solution to validate data has only article fields."""
|
|
||||||
fields = set(data.keys())
|
|
||||||
if fields != {"text", "extra"}:
|
|
||||||
raise ValueError("invalid fields")
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
class Video(BaseModel):
|
class Video(BaseModel):
|
||||||
@@ -693,20 +682,14 @@ class Video(BaseModel):
|
|||||||
text: str | None
|
text: str | None
|
||||||
extra: str | None
|
extra: str | None
|
||||||
|
|
||||||
@root_validator(pre=True)
|
class Config:
|
||||||
def has_only_video_fields(cls, data: dict):
|
extra = Extra.forbid
|
||||||
"""Silly and ugly solution to validate data has only video fields."""
|
|
||||||
fields = set(data.keys())
|
|
||||||
if fields != {"text", "extra", "video_id"}:
|
|
||||||
raise ValueError("invalid fields")
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
class Post(BaseModel):
|
class Post(BaseModel):
|
||||||
content: Article | Video
|
content: Article | Video
|
||||||
```
|
```
|
||||||
3. Use Pydantic's Smart Union (>v1.9) if fields are simple
|
2. Use Pydantic's Smart Union (>v1.9) if fields are simple
|
||||||
|
|
||||||
It's a good solution if the fields are simple like `int` or `bool`,
|
It's a good solution if the fields are simple like `int` or `bool`,
|
||||||
but it doesn't work for complex fields like classes.
|
but it doesn't work for complex fields like classes.
|
||||||
@@ -748,6 +731,16 @@ print(type(p.field_2))
|
|||||||
print(type(p.content))
|
print(type(p.content))
|
||||||
# OUTPUT: Article, because smart_union doesn't work for complex fields like classes
|
# OUTPUT: Article, because smart_union doesn't work for complex fields like classes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Fast Workaround:**
|
||||||
|
|
||||||
|
Order field types properly: from the most strict ones to loose ones.
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Post(BaseModel):
|
||||||
|
content: Video | Article
|
||||||
|
```
|
||||||
|
|
||||||
### 19. SQL-first, Pydantic-second
|
### 19. SQL-first, Pydantic-second
|
||||||
- Usually, database handles data processing much faster and cleaner than CPython will ever do.
|
- Usually, database handles data processing much faster and cleaner than CPython will ever do.
|
||||||
- It's preferable to do all the complex joins and simple data manipulations with SQL.
|
- It's preferable to do all the complex joins and simple data manipulations with SQL.
|
||||||
|
|||||||
Reference in New Issue
Block a user