Compare commits

...

7 Commits

Author SHA1 Message Date
Sebastián Ramírez
9484f939ed 🔖 Bump version, after fix, release 2019-02-12 21:46:35 +04:00
Sebastián Ramírez
9745a5d1ae 🐛 Fix jsonable_encoder for models with Config (#29)
but without json_encoders
2019-02-12 21:43:34 +04:00
Sebastián Ramírez
92c825be6a 🔖 Release 0.2.0 2019-02-08 16:09:48 +04:00
euri10
32438c85f6 Using pydantic custom encoders (#21)
Add support for Pydantic custom JSON encoders.
2019-02-08 16:06:19 +04:00
Sebastián Ramírez
02e53fde90 📝 Update release notes 2019-02-08 15:43:00 +04:00
Ken Kinder
902cdaf010 Fix typos (#24)
Fix typos in security section.
2019-02-08 15:41:13 +04:00
Sebastián Ramírez
04d77bb1c4 ✏️ Fix typos in index and alternatives 2019-02-08 15:39:26 +04:00
10 changed files with 114 additions and 18 deletions

View File

@@ -24,7 +24,7 @@
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+.
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
The key features are:
@@ -166,7 +166,7 @@ You will see the alternative automatic documentation (provided by <a href="https
## Example upgrade
Now modify the file `main.py` to recive a body from a `PUT` request.
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
@@ -257,7 +257,7 @@ item: Item
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network, to Python data and types. Reading from:
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
@@ -292,7 +292,7 @@ Coming back to the previous code example, **FastAPI** will:
* All this would also work for deeply nested JSON objects.
* Convert from and to JSON automatically.
* Document everything with OpenAPI, that can be used by:
* Interactive documentation sytems.
* Interactive documentation systems.
* Automatic client code generation systems, for many languages.
* Provide 2 interactive documentation web interfaces directly.
@@ -329,7 +329,7 @@ For a more complete example including more features, see the <a href="https://fa
**Spoiler alert**: the tutorial - user guide includes:
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constrains** as `maximum_length` or `regex`.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).

View File

@@ -6,7 +6,7 @@ What inspired **FastAPI**, how it compares to other alternatives and what it lea
There have been many tools created before that have helped inspire its creation.
I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins and tools.
I have been avoiding the creation of a new framework for several years. First I tried to solve all the features covered by **FastAPI** using many different frameworks, plug-ins, and tools.
But at some point, there was no other option than creating something that provided all these features, taking the best ideas from previous tools, and combining them in the best way possible, using language features that weren't even available before (Python 3.6+ type hints).

View File

@@ -24,7 +24,7 @@
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+.
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
The key features are:
@@ -166,7 +166,7 @@ You will see the alternative automatic documentation (provided by <a href="https
## Example upgrade
Now modify the file `main.py` to recive a body from a `PUT` request.
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
@@ -257,7 +257,7 @@ item: Item
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network, to Python data and types. Reading from:
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
@@ -292,7 +292,7 @@ Coming back to the previous code example, **FastAPI** will:
* All this would also work for deeply nested JSON objects.
* Convert from and to JSON automatically.
* Document everything with OpenAPI, that can be used by:
* Interactive documentation sytems.
* Interactive documentation systems.
* Automatic client code generation systems, for many languages.
* Provide 2 interactive documentation web interfaces directly.
@@ -329,7 +329,7 @@ For a more complete example including more features, see the <a href="https://fa
**Spoiler alert**: the tutorial - user guide includes:
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constrains** as `maximum_length` or `regex`.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).

View File

@@ -1,3 +1,13 @@
## 0.2.1
* Fix `jsonable_encoder` for Pydantic models with `Config` but without `json_encoders`: <a href="https://github.com/tiangolo/fastapi/pull/29" target="_blank">#29</a>.
## 0.2.0
* Fix typos in Security section: <a href="https://github.com/tiangolo/fastapi/pull/24" target="_blank">#24</a> by <a href="https://github.com/kkinder" target="_blank">@kkinder</a>
* Add support for Pydantic custom JSON encoders: <a href="https://github.com/tiangolo/fastapi/pull/21" target="_blank">#21</a> by <a href="https://github.com/euri10" target="_blank">@euri10</a>
## 0.1.19
* Upgrade Starlette version to the current latest `0.10.1`: <a href="https://github.com/tiangolo/fastapi/pull/17" target="_blank">#17</a> by <a href="https://github.com/euri10" target="_blank">@euri10</a>

View File

@@ -1,4 +1,4 @@
There are many ways to handle security, authentication and autorization.
There are many ways to handle security, authentication and authorization.
And it normally is a complex and "difficult" topic.
@@ -14,9 +14,9 @@ If you don't care about any of these terms and you just need to add security wit
## OAuth2
OAuth2 is a specification that defines several ways to handle authentication and autorization.
OAuth2 is a specification that defines several ways to handle authentication and authorization.
It is quite an extensive especification and covers several complex use cases.
It is quite an extensive specification and covers several complex use cases.
It includes ways to authenticate using a "third party".

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.1.19"
__version__ = "0.2.1"
from .applications import FastAPI
from .routing import APIRouter

View File

@@ -12,11 +12,14 @@ def jsonable_encoder(
exclude: Set[str] = set(),
by_alias: bool = False,
include_none: bool = True,
custom_encoder: dict = {},
) -> Any:
if isinstance(obj, BaseModel):
encoder = getattr(obj.Config, "json_encoders", custom_encoder)
return jsonable_encoder(
obj.dict(include=include, exclude=exclude, by_alias=by_alias),
include_none=include_none,
custom_encoder=encoder,
)
if isinstance(obj, Enum):
return obj.value
@@ -25,8 +28,16 @@ def jsonable_encoder(
if isinstance(obj, dict):
return {
jsonable_encoder(
key, by_alias=by_alias, include_none=include_none
): jsonable_encoder(value, by_alias=by_alias, include_none=include_none)
key,
by_alias=by_alias,
include_none=include_none,
custom_encoder=custom_encoder,
): jsonable_encoder(
value,
by_alias=by_alias,
include_none=include_none,
custom_encoder=custom_encoder,
)
for key, value in obj.items()
if value is not None or include_none
}
@@ -38,12 +49,16 @@ def jsonable_encoder(
exclude=exclude,
by_alias=by_alias,
include_none=include_none,
custom_encoder=custom_encoder,
)
for item in obj
]
errors = []
try:
encoder = ENCODERS_BY_TYPE[type(obj)]
if custom_encoder and type(obj) in custom_encoder:
encoder = custom_encoder[type(obj)]
else:
encoder = ENCODERS_BY_TYPE[type(obj)]
return encoder(obj)
except KeyError as e:
errors.append(e)

0
scripts/test.sh Normal file → Executable file
View File

View File

@@ -0,0 +1,34 @@
from datetime import datetime, timezone
from fastapi import FastAPI
from pydantic import BaseModel
from starlette.testclient import TestClient
class ModelWithDatetimeField(BaseModel):
dt_field: datetime
class Config:
json_encoders = {
datetime: lambda dt: dt.replace(
microsecond=0, tzinfo=timezone.utc
).isoformat()
}
app = FastAPI()
model = ModelWithDatetimeField(dt_field=datetime(2019, 1, 1, 8))
@app.get("/model", response_model=ModelWithDatetimeField)
def get_model():
return model
client = TestClient(app)
def test_dt():
with client:
response = client.get("/model")
assert response.json() == {"dt_field": "2019-01-01T08:00:00+00:00"}

View File

@@ -1,5 +1,9 @@
from datetime import datetime, timezone
from enum import Enum
import pytest
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
class Person:
@@ -32,6 +36,29 @@ class Unserializable:
raise NotImplementedError()
class ModelWithCustomEncoder(BaseModel):
dt_field: datetime
class Config:
json_encoders = {
datetime: lambda dt: dt.replace(
microsecond=0, tzinfo=timezone.utc
).isoformat()
}
class RoleEnum(Enum):
admin = "admin"
normal = "normal"
class ModelWithConfig(BaseModel):
role: RoleEnum = None
class Config:
use_enum_values = True
def test_encode_class():
person = Person(name="Foo")
pet = Pet(owner=person, name="Firulais")
@@ -48,3 +75,13 @@ def test_encode_unsupported():
unserializable = Unserializable()
with pytest.raises(ValueError):
jsonable_encoder(unserializable)
def test_encode_custom_json_encoders_model():
model = ModelWithCustomEncoder(dt_field=datetime(2019, 1, 1, 8))
assert jsonable_encoder(model) == {"dt_field": "2019-01-01T08:00:00+00:00"}
def test_encode_model_with_config():
model = ModelWithConfig(role=RoleEnum.admin)
assert jsonable_encoder(model) == {"role": "admin"}