Input and Output Binding
This guide covers how to bind output fields to request input using Semblance links.
FromInput
Bind an output field to an input field by name:
from typing import Annotated
from semblance import FromInput
class User(BaseModel):
name: Annotated[str, FromInput("name")]
When the input has name="alice", the response will have name: "alice". If the input field is missing or None, Polyfactory generates a value instead.
Example (with GET /user?name=alice):
{"name": "alice"}
DateRangeFrom
Generate a datetime within a range defined by two input date fields:
from datetime import datetime
from typing import Annotated
from semblance import DateRangeFrom
class User(BaseModel):
created_at: Annotated[
datetime,
DateRangeFrom("start_date", "end_date"),
]
If start_date and end_date are present on the input, created_at is a random datetime in that range. When end <= start, the result is start.
Input Sources
Query Parameters (GET)
@api.get("/users", input=UserQuery, output=list[User])
def users():
pass
UserQuery is validated from the query string.
Request Body (POST)
@api.post("/users", input=CreateUserRequest, output=User)
def create_user():
pass
CreateUserRequest is validated from the JSON body.
Path Parameters
class UserGetInput(BaseModel):
id: str = "" # default required for query validation
name: str = "alice"
@api.get("/users/{id}", input=UserGetInput, output=User)
def get_user():
pass
Path params (e.g. id from /users/123) are merged into the validated input. Your input model must include path param names with defaults.
PUT, PATCH, DELETE
PUT and PATCH use the request body (like POST); path params are merged into the input. DELETE supports an optional body; path params are always available.
@api.put("/users/{id}", input=UpdateUserRequest, output=User)
def update_user():
pass
@api.patch("/users/{id}", input=PatchUserRequest, output=User)
def patch_user():
pass
@api.delete("/users/{id}", input=DeleteUserInput) # 204 No Content
def delete_user():
pass
@api.delete("/users/{id}", input=DeleteUserInput, output=User) # 200 with body
def delete_user_with_response():
pass
For DELETE, omit output for 204 No Content, or provide an output model for 200 with a generated body.
Output Types
- Single model:
output=User– one instance - List:
output=list[User]– list of instances (default 5, configurable) - Paginated:
output=PaginatedResponse[User]– see Pagination
list_count
Control list length:
# Fixed count
@api.get("/users", input=UserQuery, output=list[User], list_count=10)
def users():
pass
# From input field
@api.get("/users", input=UserQueryWithLimit, output=list[User], list_count="limit")
def users():
pass