Rename code example file and add variants

This commit is contained in:
Yurii Motov 2025-11-28 10:51:41 +01:00
parent 98bc4dbab7
commit 1a4cdb35eb
8 changed files with 35 additions and 88 deletions

View File

@ -262,7 +262,7 @@ In other words, `None` is not an acceptable runtime value for query parameters
If you want to accept special values (like `"None"` or an empty string) and interpret them as `None` in your application, you can handle them manually in your function:
{* ../../docs_src/query_params_str_validations/tutorial006d_an_py310.py hl[10:13,18] *}
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9:12,17] *}
/// note

View File

@ -1,12 +1,21 @@
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BeforeValidator
app = FastAPI()
def nullable_str(val: str) -> str | None:
if val in ("None", "", "null"):
return None
return val
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(min_length=3)]):
async def read_items(
q: Annotated[str | None, Query(min_length=3), BeforeValidator(nullable_str)],
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})

View File

@ -1,12 +1,21 @@
from typing import Annotated, Union
from fastapi import FastAPI, Query
from pydantic import BeforeValidator
app = FastAPI()
def nullable_str(val: str) -> Union[str, None]:
if val in ("None", "", "null"):
return None
return val
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
async def read_items(
q: Annotated[Union[str, None], Query(min_length=3), BeforeValidator(nullable_str)],
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})

View File

@ -1,11 +0,0 @@
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results

View File

@ -1,13 +0,0 @@
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results

View File

@ -1,20 +0,0 @@
from typing import Optional, Union
from fastapi import FastAPI, Query
from pydantic import BeforeValidator
from typing_extensions import Annotated
app = FastAPI()
def nullable_str(val: str) -> Union[str, None]:
if val in ("None", "", "null"):
return None
return val
@app.get("/items/")
async def read_items(
q: Annotated[Optional[str], Query(min_length=3), BeforeValidator(nullable_str)],
):
return {"q": q}

View File

@ -9,8 +9,6 @@ from ...utils import needs_py310
@pytest.fixture(
name="client",
params=[
pytest.param("tutorial006c_py39"),
pytest.param("tutorial006c_py310", marks=needs_py310),
pytest.param("tutorial006c_an_py39"),
pytest.param("tutorial006c_an_py310", marks=needs_py310),
],
@ -23,24 +21,26 @@ def get_client(request: pytest.FixtureRequest):
return client
@pytest.mark.xfail(
reason="Code example is not valid. See https://github.com/fastapi/fastapi/issues/12419"
)
def test_query_params_str_validations_no_query(client: TestClient):
response = client.get("/items/")
assert response.status_code == 200
assert response.json() == { # pragma: no cover
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
assert response.status_code == 422
assert response.json() == {
"detail": [
{
"type": "missing",
"loc": ["query", "q"],
"msg": "Field required",
"input": None,
}
]
}
@pytest.mark.xfail(
reason="Code example is not valid. See https://github.com/fastapi/fastapi/issues/12419"
)
def test_query_params_str_validations_empty_str(client: TestClient):
response = client.get("/items/?q=")
@pytest.mark.parametrize("q_value", ["None", "null", ""])
def test_query_params_str_validations_send_explicit_none(client: TestClient, q_value: str):
response = client.get("/items/", params={"q": q_value})
assert response.status_code == 200
assert response.json() == { # pragma: no cover
assert response.json() == {
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}],
}

View File

@ -1,27 +0,0 @@
import pytest
from fastapi.testclient import TestClient
from tests.utils import needs_pydanticv2
@pytest.fixture
def client():
from docs_src.query_params_str_validations.tutorial006d_an_py310 import app
yield TestClient(app)
@needs_pydanticv2
@pytest.mark.parametrize(
"q_value,expected",
[
("None", None),
("", None),
("null", None),
("hello", "hello"),
],
)
def test_read_items(q_value, expected, client: TestClient):
response = client.get("/items/", params={"q": q_value})
assert response.status_code == 200
assert response.json() == {"q": expected}