Browse Source
* Fix exclude_unset and aliases in response model validation. * ✨ Use by_alias from param 🤷 Co-authored-by: Sebastián Ramírez <[email protected]>pull/1112/head
committed by
GitHub
2 changed files with 179 additions and 7 deletions
@ -0,0 +1,154 @@ |
|||||
|
from typing import Dict, List |
||||
|
|
||||
|
from fastapi import FastAPI |
||||
|
from pydantic import BaseModel, Field |
||||
|
from starlette.testclient import TestClient |
||||
|
|
||||
|
app = FastAPI() |
||||
|
|
||||
|
|
||||
|
class Item(BaseModel): |
||||
|
name: str = Field(..., alias="aliased_name") |
||||
|
price: float = None |
||||
|
owner_ids: List[int] = None |
||||
|
|
||||
|
|
||||
|
@app.get("/items/valid", response_model=Item) |
||||
|
def get_valid(): |
||||
|
return Item(aliased_name="valid", price=1.0) |
||||
|
|
||||
|
|
||||
|
@app.get("/items/coerce", response_model=Item) |
||||
|
def get_coerce(): |
||||
|
return Item(aliased_name="coerce", price="1.0") |
||||
|
|
||||
|
|
||||
|
@app.get("/items/validlist", response_model=List[Item]) |
||||
|
def get_validlist(): |
||||
|
return [ |
||||
|
Item(aliased_name="foo"), |
||||
|
Item(aliased_name="bar", price=1.0), |
||||
|
Item(aliased_name="baz", price=2.0, owner_ids=[1, 2, 3]), |
||||
|
] |
||||
|
|
||||
|
|
||||
|
@app.get("/items/validdict", response_model=Dict[str, Item]) |
||||
|
def get_validdict(): |
||||
|
return { |
||||
|
"k1": Item(aliased_name="foo"), |
||||
|
"k2": Item(aliased_name="bar", price=1.0), |
||||
|
"k3": Item(aliased_name="baz", price=2.0, owner_ids=[1, 2, 3]), |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@app.get( |
||||
|
"/items/valid-exclude-unset", response_model=Item, response_model_exclude_unset=True |
||||
|
) |
||||
|
def get_valid_exclude_unset(): |
||||
|
return Item(aliased_name="valid", price=1.0) |
||||
|
|
||||
|
|
||||
|
@app.get( |
||||
|
"/items/coerce-exclude-unset", |
||||
|
response_model=Item, |
||||
|
response_model_exclude_unset=True, |
||||
|
) |
||||
|
def get_coerce_exclude_unset(): |
||||
|
return Item(aliased_name="coerce", price="1.0") |
||||
|
|
||||
|
|
||||
|
@app.get( |
||||
|
"/items/validlist-exclude-unset", |
||||
|
response_model=List[Item], |
||||
|
response_model_exclude_unset=True, |
||||
|
) |
||||
|
def get_validlist_exclude_unset(): |
||||
|
return [ |
||||
|
Item(aliased_name="foo"), |
||||
|
Item(aliased_name="bar", price=1.0), |
||||
|
Item(aliased_name="baz", price=2.0, owner_ids=[1, 2, 3]), |
||||
|
] |
||||
|
|
||||
|
|
||||
|
@app.get( |
||||
|
"/items/validdict-exclude-unset", |
||||
|
response_model=Dict[str, Item], |
||||
|
response_model_exclude_unset=True, |
||||
|
) |
||||
|
def get_validdict_exclude_unset(): |
||||
|
return { |
||||
|
"k1": Item(aliased_name="foo"), |
||||
|
"k2": Item(aliased_name="bar", price=1.0), |
||||
|
"k3": Item(aliased_name="baz", price=2.0, owner_ids=[1, 2, 3]), |
||||
|
} |
||||
|
|
||||
|
|
||||
|
client = TestClient(app) |
||||
|
|
||||
|
|
||||
|
def test_valid(): |
||||
|
response = client.get("/items/valid") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == {"aliased_name": "valid", "price": 1.0, "owner_ids": None} |
||||
|
|
||||
|
|
||||
|
def test_coerce(): |
||||
|
response = client.get("/items/coerce") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == { |
||||
|
"aliased_name": "coerce", |
||||
|
"price": 1.0, |
||||
|
"owner_ids": None, |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def test_validlist(): |
||||
|
response = client.get("/items/validlist") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == [ |
||||
|
{"aliased_name": "foo", "price": None, "owner_ids": None}, |
||||
|
{"aliased_name": "bar", "price": 1.0, "owner_ids": None}, |
||||
|
{"aliased_name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]}, |
||||
|
] |
||||
|
|
||||
|
|
||||
|
def test_validdict(): |
||||
|
response = client.get("/items/validdict") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == { |
||||
|
"k1": {"aliased_name": "foo", "price": None, "owner_ids": None}, |
||||
|
"k2": {"aliased_name": "bar", "price": 1.0, "owner_ids": None}, |
||||
|
"k3": {"aliased_name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]}, |
||||
|
} |
||||
|
|
||||
|
|
||||
|
def test_valid_exclude_unset(): |
||||
|
response = client.get("/items/valid-exclude-unset") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == {"aliased_name": "valid", "price": 1.0} |
||||
|
|
||||
|
|
||||
|
def test_coerce_exclude_unset(): |
||||
|
response = client.get("/items/coerce-exclude-unset") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == {"aliased_name": "coerce", "price": 1.0} |
||||
|
|
||||
|
|
||||
|
def test_validlist_exclude_unset(): |
||||
|
response = client.get("/items/validlist-exclude-unset") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == [ |
||||
|
{"aliased_name": "foo"}, |
||||
|
{"aliased_name": "bar", "price": 1.0}, |
||||
|
{"aliased_name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]}, |
||||
|
] |
||||
|
|
||||
|
|
||||
|
def test_validdict_exclude_unset(): |
||||
|
response = client.get("/items/validdict-exclude-unset") |
||||
|
response.raise_for_status() |
||||
|
assert response.json() == { |
||||
|
"k1": {"aliased_name": "foo"}, |
||||
|
"k2": {"aliased_name": "bar", "price": 1.0}, |
||||
|
"k3": {"aliased_name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]}, |
||||
|
} |
Loading…
Reference in new issue