Form with optional Email fails, what is the best practise here? #15743
-
First Check
Commit to Help
Example Codeimport sys, pytest
from pydantic import BaseModel, EmailStr
from fastapi import FastAPI, Form
from fastapi.testclient import TestClient
class Ce(BaseModel):
x: EmailStr | None = Field(None, min_length=6)
app = FastAPI()
@app.post('/post')
async def post(ce: Ce = Form()):
return ce
client = TestClient(app)
def test_write_noneok():
response = client.post("/post", data={})
assert response.status_code == 200
assert response.json() == {'x':None}
def test_write_emptyok():
response = client.post("/post", data={'x':''})
assert response.status_code == 200
assert response.json() == {'x': None}
if __name__ == "__main__":
sys.exit(pytest.main())DescriptionI try to model a Html Form that has an optional email field. The intention is to have it either be absent or validate with the properties set. The pydantic model works for manually instantiating a model, but fails when done via a HTML Form Post where the form has the email input not filled out. It seems in this case, broswers send this datum as emty-string, such that not providing an email tries to instantiate the model as if it would be Can I remedy that besides making (Expanded version of code here) Operating SystemLinux, macOS Operating System DetailsNo response FastAPI Version0.136.3 Pydantic Version2.13.4 Python VersionPython 3.14.5 Additional ContextNo response |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
Because HTML browsers submit empty form inputs as an empty string ( The best solution is to use Pydantic's If you apply constraints like To prevent this, the constraint should be nested inside the Solution using a nested reusable
|
Beta Was this translation helpful? Give feedback.
Because HTML browsers submit empty form inputs as an empty string (
"") rather than omitting them or sendingnull, Pydantic attempts to validate""against yourEmailStrandmin_lengthconstraints, resulting in a validation error.The best solution is to use Pydantic's
BeforeValidatorto intercept the data before standard validation runs, converting any empty string intoNone.If you apply constraints like
min_lengthat the top level of theAnnotatedtype (e.g.Field(min_length=6)), Pydantic will attempt to apply the constraint toNonevalues as well. This leads to aTypeError(e.g.,object of type 'NoneType' has no len()).To prevent this, the constraint should be nested inside the
EmailStr…