Browse Source

📝 Add docs for response_model

pull/11/head
Sebastián Ramírez 6 years ago
parent
commit
222b75ac0c
  1. BIN
      docs/img/tutorial/response-model/image01.png
  2. BIN
      docs/img/tutorial/response-model/image02.png
  3. 13
      docs/tutorial/first-steps.md
  4. 84
      docs/tutorial/response-model.md
  5. 19
      docs/tutorial/src/response-model/tutorial001.py
  6. 18
      docs/tutorial/src/response-model/tutorial002.py
  7. 23
      docs/tutorial/src/response-model/tutorial003.py
  8. 1
      mkdocs.yml

BIN
docs/img/tutorial/response-model/image01.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
docs/img/tutorial/response-model/image02.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

13
docs/tutorial/first-steps.md

@ -130,6 +130,19 @@ uvicorn main:my_awesome_api --debug
The `@app.get("/")` tells **FastAPI** that the function right below is an endpoint and that it should go to the path route `/`.
You can also use other HTTP methods:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
And more exotic ones:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
### Step 4: define the endpoint function
```Python hl_lines="7"

84
docs/tutorial/response-model.md

@ -0,0 +1,84 @@
You can declare the model used for the response with the parameter `response_model` in any of the endpoint creation methods:
* `@app.get()`
* `@app.post()`
* `@app.put()`
* `@app.delete()`
* etc.
```Python hl_lines="17"
{!./tutorial/src/response-model/tutorial001.py!}
```
!!! note
Notice that `response_model` is a parameter of the "decorator" method (`get`, `post`, etc), not of your endpoint function like all the parameters and body.
It receives a standard Pydantic model and will:
* Convert the output data to the type declarations of the model
* Validate the data
* Add a JSON Schema for the response, in the OpenAPI endpoint
* Will be used by the automatic documentation systems
But most importantly:
* Will limit the output data to that of the model. We'll see how that's important below.
## Return the same input data
Here we are declaring a `UserIn` model, it will contain a plaintext password:
```Python hl_lines="8 10"
{!./tutorial/src/response-model/tutorial002.py!}
```
And we are using this model to declare our input and the same model to declare our output:
```Python hl_lines="16 17"
{!./tutorial/src/response-model/tutorial002.py!}
```
Now, whenever a browser is creating a user with a password, the API will return the same password in the response.
In this case, it might not be a problem, becase the user himself is sending the password.
But if we use sthe same model for another endpoint, we could be sending the passwords of our users to every client.
!!! danger
Never send the plain password of a user in a response.
## Add an output model
We can instead create an input model with the plaintext password and an output model without it:
```Python hl_lines="8 10 15"
{!./tutorial/src/response-model/tutorial003.py!}
```
Here, even though our endpoint function is returning the same input user that contains the password:
```Python hl_lines="23"
{!./tutorial/src/response-model/tutorial003.py!}
```
...we declared the `response_model` to be our model `UserOut`, that doesn't include the password:
```Python hl_lines="21"
{!./tutorial/src/response-model/tutorial003.py!}
```
So, **FastAPI** will take care of filtering out all the data that is not declared in the output model (using Pydantic).
## See it in the docs
When you see the automatic docs, you can check that the input model and output model will both have their own JSON Schema:
<img src="/img/tutorial/response-model/image01.png">
And both models will be used for the interactive API documentation:
<img src="/img/tutorial/response-model/image02.png">
## Recap
Use the endpoint decorator's parameter `response_model` to define response models and especially to ensure private data is filtered out.

19
docs/tutorial/src/response-model/tutorial001.py

@ -0,0 +1,19 @@
from typing import Set
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
tags: Set[str] = []
@app.post("/items/", response_model=Item)
async def create_item(*, item: Item):
return item

18
docs/tutorial/src/response-model/tutorial002.py

@ -0,0 +1,18 @@
from fastapi import FastAPI
from pydantic import BaseModel
from pydantic.types import EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str = None
# Don't do this in production!
@app.post("/user/", response_model=UserIn)
async def create_user(*, user: UserIn):
return user

23
docs/tutorial/src/response-model/tutorial003.py

@ -0,0 +1,23 @@
from fastapi import FastAPI
from pydantic import BaseModel
from pydantic.types import EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: str = None
@app.post("/user/", response_model=UserOut)
async def create_user(*, user: UserIn):
return user

1
mkdocs.yml

@ -29,6 +29,7 @@ nav:
- Body - Nested Models: 'tutorial/body-nested-models.md'
- Cookie Parameters: 'tutorial/cookie-params.md'
- Header Parameters: 'tutorial/header-params.md'
- Response Model: 'tutorial/response-model.md'
- Concurrency and async / await: 'async.md'
- Deployment: 'deployment.md'

Loading…
Cancel
Save