You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This example shows how to do request validation using FastAPI's Form.
@router.post("/create", response_class=RedirectResponse)defcreate_organization(
name: Annotated[str, Form(
min_length=1,
strip_whitespace=True,
pattern=r"\S+",
description="Organization name cannot be empty or contain only whitespace",
title="Organization name"
)],
Where else in the repository should we be leveraging this pattern to better effect?
Okay, let's analyze the codebase to find other places where leveraging Annotated[..., Form(...)] for declarative validation would be beneficial.
The pattern is most useful for POST routes that receive form data, particularly simple string inputs where constraints like non-emptiness, length, whitespace stripping, or basic patterns are desired directly in the signature.
Here's a breakdown by router file:
routers/account.py
delete_account:
email: EmailStr = Form(...): EmailStr provides good validation already. Adding Form for description/title is minor.
password: str = Form(...): Candidate. Could add min_length=8 (as a basic check, though complex validation is elsewhere), description, title.
password: Annotated[str, Form(
min_length=8, # Or match the required minimumdescription="Account password for verification",
title="Password"
)],
register:
name: str = Form(...): Strong Candidate. Similar to the example, needs non-empty, strip whitespace.
email: EmailStr = Form(...): EmailStr is sufficient.
password: str = Form(...), confirm_password: str = Form(...): Candidates. Similar to delete_account, could add min_length, description, title. The complex pattern matching is handled by the validate_password_strength_and_match dependency, but basic checks can be added here.
password: Annotated[str, Form(
min_length=8, # Match required minimumdescription="Choose a strong password",
title="Password"
)],
confirm_password: Annotated[str, Form(
min_length=8, # Match required minimumdescription="Confirm your password",
title="Confirm Password"
)],
# Note: The Depends(validate_password_strength_and_match) still handles the comparison and complex pattern.
login:
email: EmailStr = Form(...): EmailStr is sufficient.
name: Annotated[str, Form(
min_length=1,
strip_whitespace=True,
pattern=r"\S+",
description="Name for the new role",
title="Role Name"
)],
organization_id: int = Form(...): int validation is implicit. Form could add gt=0, description, title.
permissions: List[ValidPermissions] = Form(...): List validation handled by FastAPI. Form could add description.
update_role:
id: int = Form(...), organization_id: int = Form(...), permissions: List[ValidPermissions] = Form(...): Similar to create_role.
name: str = Form(...): Strong Candidate. Same as in create_role.
name: Annotated[str, Form(
min_length=1,
strip_whitespace=True,
pattern=r"\S+",
description="Updated name for the role",
title="Role Name"
)],
delete_role:
id: int = Form(...), organization_id: int = Form(...): int validation is implicit.
routers/user.py
update_profile:
name: Optional[str] = Form(None): Candidate. Since it's optional, the rules apply if a value is provided. strip_whitespace is useful. A min_length if not None could also be added, but is harder to express declaratively. strip_whitespace is the main benefit here.
name: Annotated[Optional[str], Form(
None, # Keep default as None for optionalitystrip_whitespace=True,
# min_length=1, # Can't easily apply conditionally heredescription="User's updated full name (optional)",
title="Name"
)],
avatar_file: Optional[UploadFile] = File(None): Not applicable for Form.
Summary of Recommendations:
Apply the Annotated[..., Form(...)] pattern primarily to:
routers/account.py:
name in register (non-empty, strip whitespace).
password/confirm_password fields in register, reset_password, login, delete_account (at least min_length=1 or min_length=8, description, title).
token in reset_password (non-empty, strip whitespace).
routers/role.py:
name in create_role and update_role (non-empty, strip whitespace).
routers/user.py:
name in update_profile (strip_whitespace=True).
This makes the validation constraints clearer directly in the function signature and leverages FastAPI's built-in mechanisms more effectively for basic form field validation, reserving more complex or cross-field validation for dependencies or the route body.
The text was updated successfully, but these errors were encountered:
This example shows how to do request validation using FastAPI's
Form
.Where else in the repository should we be leveraging this pattern to better effect?
Okay, let's analyze the codebase to find other places where leveraging
Annotated[..., Form(...)]
for declarative validation would be beneficial.The pattern is most useful for POST routes that receive form data, particularly simple string inputs where constraints like non-emptiness, length, whitespace stripping, or basic patterns are desired directly in the signature.
Here's a breakdown by router file:
routers/account.py
delete_account
:email: EmailStr = Form(...)
:EmailStr
provides good validation already. AddingForm
fordescription
/title
is minor.password: str = Form(...)
: Candidate. Could addmin_length=8
(as a basic check, though complex validation is elsewhere),description
,title
.register
:name: str = Form(...)
: Strong Candidate. Similar to the example, needs non-empty, strip whitespace.email: EmailStr = Form(...)
:EmailStr
is sufficient.password: str = Form(...)
,confirm_password: str = Form(...)
: Candidates. Similar todelete_account
, could addmin_length
,description
,title
. The complex pattern matching is handled by thevalidate_password_strength_and_match
dependency, but basic checks can be added here.login
:email: EmailStr = Form(...)
:EmailStr
is sufficient.password: str = Form(...)
: Candidate. Needsmin_length
,description
,title
.forgot_password
:email: EmailStr = Form(...)
:EmailStr
is sufficient.reset_password
:email: EmailStr = Form(...)
:EmailStr
is sufficient.token: str = Form(...)
: Candidate. Should not be empty.new_password: str = Depends(...)
,confirm_password: str = Form(...)
: Handled by dependency, butconfirm_password
could benefit like inregister
.request_email_update
:email: EmailStr = Form(...)
,new_email: EmailStr = Form(...)
: BothEmailStr
are sufficient.routers/organization.py
create_organization
,update_organization
: Already use the pattern forname
.routers/role.py
create_role
:name: str = Form(...)
: Strong Candidate. Needs non-empty, strip whitespace.organization_id: int = Form(...)
:int
validation is implicit.Form
could addgt=0
,description
,title
.permissions: List[ValidPermissions] = Form(...)
: List validation handled by FastAPI.Form
could adddescription
.update_role
:id: int = Form(...)
,organization_id: int = Form(...)
,permissions: List[ValidPermissions] = Form(...)
: Similar tocreate_role
.name: str = Form(...)
: Strong Candidate. Same as increate_role
.delete_role
:id: int = Form(...)
,organization_id: int = Form(...)
:int
validation is implicit.routers/user.py
update_profile
:name: Optional[str] = Form(None)
: Candidate. Since it's optional, the rules apply if a value is provided.strip_whitespace
is useful. Amin_length
if notNone
could also be added, but is harder to express declaratively.strip_whitespace
is the main benefit here.avatar_file: Optional[UploadFile] = File(None)
: Not applicable forForm
.Summary of Recommendations:
Apply the
Annotated[..., Form(...)]
pattern primarily to:routers/account.py
:name
inregister
(non-empty, strip whitespace).password
/confirm_password
fields inregister
,reset_password
,login
,delete_account
(at leastmin_length=1
ormin_length=8
,description
,title
).token
inreset_password
(non-empty, strip whitespace).routers/role.py
:name
increate_role
andupdate_role
(non-empty, strip whitespace).routers/user.py
:name
inupdate_profile
(strip_whitespace=True
).This makes the validation constraints clearer directly in the function signature and leverages FastAPI's built-in mechanisms more effectively for basic form field validation, reserving more complex or cross-field validation for dependencies or the route body.
The text was updated successfully, but these errors were encountered: