Add Custom Base Model point description
This commit is contained in:
53
README.md
53
README.md
@@ -368,8 +368,57 @@ In short, GIL allows only one thread to work at a time, which makes it useless f
|
|||||||
2. https://stackoverflow.com/questions/65342833/fastapi-uploadfile-is-slow-compared-to-flask
|
2. https://stackoverflow.com/questions/65342833/fastapi-uploadfile-is-slow-compared-to-flask
|
||||||
3. https://stackoverflow.com/questions/71516140/fastapi-runs-api-calls-in-serial-instead-of-parallel-fashion
|
3. https://stackoverflow.com/questions/71516140/fastapi-runs-api-calls-in-serial-instead-of-parallel-fashion
|
||||||
|
|
||||||
### 9. Custom base model model from day 0,
|
### 9. Custom base model from day 0.
|
||||||
convert datetime to common standard
|
Having a controllable global pydantic base model allows us to customize all the models within the app.
|
||||||
|
For example, we could have a standard datetime format or add a super method for all subclasses of the base model.
|
||||||
|
```python
|
||||||
|
from datetime import datetime
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
import orjson
|
||||||
|
from fastapi.encoders import jsonable_encoder
|
||||||
|
from pydantic import BaseModel, root_validator
|
||||||
|
|
||||||
|
|
||||||
|
def orjson_dumps(v, *, default):
|
||||||
|
# orjson.dumps returns bytes, to match standard json.dumps we need to decode
|
||||||
|
return orjson.dumps(v, default=default).decode()
|
||||||
|
|
||||||
|
|
||||||
|
def convert_datetime_to_gmt(dt: datetime) -> str:
|
||||||
|
if not dt.tzinfo:
|
||||||
|
dt = dt.replace(tzinfo=ZoneInfo("UTC"))
|
||||||
|
|
||||||
|
return dt.strftime("%Y-%m-%dT%H:%M:%S%z")
|
||||||
|
|
||||||
|
|
||||||
|
class ORJSONModel(BaseModel):
|
||||||
|
class Config:
|
||||||
|
json_loads = orjson.loads
|
||||||
|
json_dumps = orjson_dumps
|
||||||
|
json_encoders = {datetime: convert_datetime_to_gmt} # method for customer JSON encoding of datetime fields
|
||||||
|
|
||||||
|
@root_validator()
|
||||||
|
def set_null_microseconds(cls, data: dict) -> dict:
|
||||||
|
"""Drops microseconds in all the datetime field values."""
|
||||||
|
datetime_fields = {
|
||||||
|
k: v.replace(microsecond=0)
|
||||||
|
for k, v in data.items()
|
||||||
|
if isinstance(k, datetime)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {**data, **datetime_fields}
|
||||||
|
|
||||||
|
def serializable_dict(self, **kwargs):
|
||||||
|
"""Return a dict which contains only serializable fields."""
|
||||||
|
default_dict = super().dict(**kwargs)
|
||||||
|
|
||||||
|
return jsonable_encoder(default_dict)
|
||||||
|
```
|
||||||
|
In the example above we have decided to make a global base model which:
|
||||||
|
- uses [orjson](https://github.com/ijl/orjson) to serialize data
|
||||||
|
- drops microseconds to 0 in all date formats
|
||||||
|
- serializes all datetime fields to standard format with explicit timezone
|
||||||
### 10. Docs
|
### 10. Docs
|
||||||
1. Unless your API is public, hide docs by default. Show it explicitly on the selected envs only.
|
1. Unless your API is public, hide docs by default. Show it explicitly on the selected envs only.
|
||||||
```python
|
```python
|
||||||
|
|||||||
Reference in New Issue
Block a user