Request Body¶
When you need to send data from a client (e.g., a browser) to your API, you send it as a request body.
A request body is the data sent by the client to the API, while the response body is the data the API sends back to the client.
Your API almost always needs to return a response body. But, clients don't always need to send a request body. Sometimes, they may only request a path or include some query parameters without sending a body.
To declare a request body, you use Pydantic models with all their power and benefits.
Info
When sending data, you should use one of the following HTTP methods: POST
(most common), PUT
, DELETE
, or PATCH
.
Sending a body with a GET request has an undefined behavior in the specifications, nevertheless, it is supported by Nexify, only for very complex/extreme use cases.
As it is discouraged, the interactive docs with Swagger UI won't show the documentation for the body when using GET
, and proxies in the middle might not support it.
Import Pydantic's BaseModel
¶
First, you need to import BaseModel
from pydantic
:
from typing import Annotated
from nexify import Body, Nexify
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = Nexify()
@app.post("/items")
def create_item(item: Annotated[Item, Body()]):
return item
Create your Data Model¶
Next, you declare your data model as a class that inherits from BaseModel
.
Use standard Python types for all the attributes:
from typing import Annotated
from nexify import Body, Nexify
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = Nexify()
@app.post("/items")
def create_item(item: Annotated[Item, Body()]):
return item
Like query parameters, if a model attribute has a default value, it is optional. Otherwise, it is required. Setting None
as the default value makes it optional.
For example, this model above declares a JSON "object
" (or Python dict
) like:
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
Since description
and tax
are optional, the following JSON is also valid:
{
"name": "Foo",
"price": 45.2
}
Declare it as a Parameter¶
To add the request body to your API, declare it the same way you declared path and query parameters:
from typing import Annotated
from nexify import Body, Nexify
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = Nexify()
@app.post("/items")
def create_item(item: Annotated[Item, Body()]):
return item
Just declare it by putting Body()
with Annotated
.
Data Validation¶
If you send a request to /items
with the following body
{
“name": “Foo”,
“description": “Optional description field”,
“price": 45.2,
“tax": “USA TAX”
}
In this case, The tax
should be a float
but was incorrectly declared as a str
.
So that you might see a 422 response like this:
{
"detail": [
{
"type": "float_parsing",
"loc": ["body", "item", "tax"],
"msg": "Input should be a valid number, unable to parse string as a number",
"input": "USA TAX"
}
]
}
Just like in the path and query parameters tutorial, an internal Pydantic-based validation error occurs, and Nexify returns a 422 response with a detailed error message.
Documentation¶
The JSON schema of the model is included in the generated OpenAPI schema and is included in the Swagger UI.