Browse Source

Fix: clarify 'Required, can be None' query parameter docs

The documentation incorrectly stated that clients could send None as
a query parameter value. In reality, omitting a required parameter
returns 422, and there is no standard HTTP mechanism to pass None
as a query string value.

Changes:
- Updated docs to clarify that None in the type annotation means
  the OpenAPI schema marks the parameter as nullable
- Added info box explaining the actual behavior
- Fixed xfail tests to verify correct 422 behavior instead of
  expecting impossible 200 responses

Closes #12419
pull/15195/head
r266-tech 4 months ago
parent
commit
58afccb275
  1. 8
      docs/en/docs/tutorial/query-params-str-validations.md
  2. 35
      tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py

8
docs/en/docs/tutorial/query-params-str-validations.md

@ -222,10 +222,16 @@ So, when you need to declare a value as required while using `Query`, you can si
### Required, can be `None` { #required-can-be-none } ### Required, can be `None` { #required-can-be-none }
You can declare that a parameter can accept `None`, but that it's still required. This would force clients to send a value, even if the value is `None`. You can declare that a parameter's type can be `None`, but that it's still **required** (it must be included in the request). This is useful when you want to require the parameter to be present, but allow the value to be `None`.
To do that, you can declare that `None` is a valid type but simply do not declare a default value: To do that, you can declare that `None` is a valid type but simply do not declare a default value:
/// info
When the parameter is required (no default value), omitting it will result in a **422 Validation Error**. The `None` type is included so that the OpenAPI schema correctly represents the parameter as **nullable**, and it allows your code to handle a `None` value explicitly. However, note that there's no standard HTTP mechanism to send `None` as a query parameter value from a client.
///
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} {* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
## Query parameter list / multiple values { #query-parameter-list-multiple-values } ## Query parameter list / multiple values { #query-parameter-list-multiple-values }

35
tests/test_tutorial/test_query_params_str_validations/test_tutorial006c.py

@ -22,25 +22,36 @@ def get_client(request: pytest.FixtureRequest):
return client 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): def test_query_params_str_validations_no_query(client: TestClient):
"""When q is required (no default), omitting it returns 422."""
response = client.get("/items/") response = client.get("/items/")
assert response.status_code == 200 assert response.status_code == 422
assert response.json() == { # pragma: no cover assert response.json() == {
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}], "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): def test_query_params_str_validations_empty_str(client: TestClient):
"""Empty string fails min_length validation."""
response = client.get("/items/?q=") response = client.get("/items/?q=")
assert response.status_code == 200 assert response.status_code == 422
assert response.json() == { # pragma: no cover assert response.json() == {
"items": [{"item_id": "Foo"}, {"item_id": "Bar"}], "detail": [
{
"type": "string_too_short",
"loc": ["query", "q"],
"msg": "String should have at least 3 characters",
"input": "",
"ctx": {"min_length": 3},
}
]
} }

Loading…
Cancel
Save