Handling Body Fields in Esmerald¶
In Esmerald, body fields are used to parse and validate incoming request bodies. The Body
class in Esmerald allows you to define structured data within the body of a request. This guide will cover how to handle and validate body fields using Esmerald.
📂 Using the Body
Class¶
The Body
class in Esmerald is used to define fields in the body of an HTTP request. These fields can be validated and documented using Pydantic models. You can also specify the media type of the body content, such as application/json
, application/x-www-form-urlencoded
, or multipart/form-data
.
Example: Simple Body Field¶
from pydantic import BaseModel
from esmerald import Esmerald, Gateway, JSONResponse, post, Body
class User(BaseModel):
name: str
email: str
@post("/create")
async def create_user(data: User = Body(...)) -> JSONResponse:
"""
Creates a new user based on the request body.
"""
return JSONResponse({"message": "User created", "user": data.model_dump()})
app = Esmerald(routes=[Gateway(handler=create_user)])
Explanation:¶
- The
User
Pydantic model defines the structure of the incoming data. - The
data
parameter is annotated withBody(...)
, indicating that the body of the request should be parsed into theUser
model. - The
create_user
endpoint accepts the user data in JSON format and returns the same data in the response.
🌐 Setting the media_type
for Body Fields¶
Esmerald allows you to define the media_type
for body fields, specifying the format of the data being sent.
Available Media Types:¶
application/json
(default)application/x-www-form-urlencoded
multipart/form-data
You can define the media_type
when using the Body
decorator to specify how Esmerald should parse the incoming request body.
Example: Body with media_type
¶
from pydantic import BaseModel
from esmerald import Esmerald, Gateway, JSONResponse, post, Body
from esmerald.utils.enums import EncodingType
class User(BaseModel):
name: str
email: str
@post("/create")
async def create_user(
data: User = Body(..., media_type=EncodingType.URL_ENCODED)
) -> JSONResponse:
"""
Creates a user with the body sent as x-www-form-urlencoded.
"""
return JSONResponse({"message": "User created", "user": data.model_dump()})
app = Esmerald(routes=[Gateway(handler=create_user)])
Explanation:¶
- The
media_type=EncodingType.URL_ENCODED
specifies that the body content should be parsed asapplication/x-www-form-urlencoded
, commonly used in forms. - This allows you to work with URL-encoded form data instead of JSON.
🧩 Using Body
with Pydantic Models¶
Esmerald leverages Pydantic for automatic data validation and serialization. You can define more complex data structures using Pydantic models and use them as body fields.
Example: Using Body
with Nested Pydantic Models¶
from pydantic import BaseModel
from esmerald import Esmerald, Gateway, JSONResponse, post, Body
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
email: str
address: Address
@post("/create")
async def create_user(data: User = Body(...)) -> JSONResponse:
"""
Creates a user with a nested address.
"""
return JSONResponse({"message": "User created", "user": data.model_dump()})
app = Esmerald(routes=[Gateway(handler=create_user)])
Explanation:¶
- The
User
model contains a nestedAddress
model. Thedata
parameter in thecreate_user
function is annotated asBody(...)
, which will automatically parse the incoming request body into the nestedUser
andAddress
models. - This allows you to work with complex, nested data structures while keeping the validation and parsing automatic.
📝 Optional and Default Fields in Body
¶
In Esmerald, body fields can be optional or have default values. You can use Python's typing and Pydantic features to define whether a field is required or optional.
Example: Optional Fields in Body¶
from typing import Optional
from pydantic import BaseModel
from esmerald import Esmerald, Gateway, JSONResponse, post, Body
class User(BaseModel):
name: str
email: Optional[str] = None # Optional field
@post("/create")
async def create_user(data: User = Body(...)) -> JSONResponse:
"""
Creates a user, with an optional email.
"""
return JSONResponse({"message": "User created", "user": data.model_dump()})
app = Esmerald(routes=[Gateway(handler=create_user)])
Explanation:¶
- The
email
field is marked asOptional[str]
, meaning it is not required in the request body. If the email is not provided, it will default toNone
. - This allows you to handle flexible form submissions where some fields may be omitted.
⚙️ Advanced Field Validation in Body
¶
You can apply advanced validation to body fields using Pydantic's Field
class, which provides attributes like min_length
, max_length
, and custom validation.
Example: Using Field
for Validation¶
from pydantic import BaseModel, Field
from esmerald import Esmerald, Gateway, JSONResponse, post, Body
class User(BaseModel):
name: str = Field(..., min_length=3) # Ensures the name has at least 3 characters
email: str = Field(..., regex=r"^[\w\.-]+@[\w\.-]+\.\w{2,3}$") # Email validation
@post("/create")
async def create_user(data: User = Body(...)) -> JSONResponse:
"""
Creates a user with field validation.
"""
return JSONResponse({"message": "User created", "user": data.model_dump()})
app = Esmerald(routes=[Gateway(handler=create_user)])
Explanation:¶
- The
Field(..., min_length=3)
ensures that thename
field has at least three characters. - The
Field(..., regex=r"^[\w\.-]+@[\w\.-]+\.\w{2,3}$")
validates that theemail
field is in a correct email format. - These validations ensure that the request data meets specific requirements before reaching your handler logic.
📂 Summary¶
Body
allows you to handle and validate request bodies in Esmerald, using Pydantic models or simple Python data structures.- You can customize the body content using
media_type
, choosing betweenapplication/json
,application/x-www-form-urlencoded
, andmultipart/form-data
. - Esmerald makes it easy to handle complex, nested models and apply custom validations using Pydantic’s powerful features.
- Optional fields and default values allow you to create flexible API endpoints that can handle a variety of input scenarios.