Browse Source

Improve path params documentation with validation example

pull/15144/head
venkatasaikumarguntupalli 4 months ago
parent
commit
335d1aedca
  1. 82
      docs/en/docs/tutorial/path-params.md
  2. 7
      docs_src/path_params/tutorial006_py310.py

82
docs/en/docs/tutorial/path-params.md

@ -2,7 +2,7 @@
You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
{_ ../../docs_src/path_params/tutorial001_py310.py hl[6:7] _}
The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.
@ -16,7 +16,7 @@ So, if you run this example and go to [http://127.0.0.1:8000/items/foo](http://1
You can declare the type of a path parameter in the function, using standard Python type annotations:
{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
{_ ../../docs_src/path_params/tutorial002_py310.py hl[7] _}
In this case, `item_id` is declared to be an `int`.
@ -110,27 +110,27 @@ Several of these are explored in the next chapters of the tutorial.
## Order matters { #order-matters }
When creating *path operations*, you can find situations where you have a fixed path.
When creating _path operations_, you can find situations where you have a fixed path.
Like `/users/me`, let's say that it's to get data about the current user.
And then you can also have a path `/users/{user_id}` to get data about a specific user by some user ID.
Because *path operations* are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
Because _path operations_ are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
{_ ../../docs_src/path_params/tutorial003_py310.py hl[6,11] _}
Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
Similarly, you cannot redefine a path operation:
{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
{_ ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] _}
The first one will always be used since the path matches first.
## Predefined values { #predefined-values }
If you have a *path operation* that receives a *path parameter*, but you want the possible valid *path parameter* values to be predefined, you can use a standard Python <abbr title="Enumeration">`Enum`</abbr>.
If you have a _path operation_ that receives a _path parameter_, but you want the possible valid _path parameter_ values to be predefined, you can use a standard Python <abbr title="Enumeration">`Enum`</abbr>.
### Create an `Enum` class { #create-an-enum-class }
@ -140,7 +140,7 @@ By inheriting from `str` the API docs will be able to know that the values must
Then create class attributes with fixed values, which will be the available valid values:
{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
{_ ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] _}
/// tip
@ -148,33 +148,33 @@ If you are wondering, "AlexNet", "ResNet", and "LeNet" are just names of Machine
///
### Declare a *path parameter* { #declare-a-path-parameter }
### Declare a _path parameter_ { #declare-a-path-parameter }
Then create a *path parameter* with a type annotation using the enum class you created (`ModelName`):
Then create a _path parameter_ with a type annotation using the enum class you created (`ModelName`):
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
{_ ../../docs_src/path_params/tutorial005_py310.py hl[16] _}
### Check the docs { #check-the-docs }
Because the available values for the *path parameter* are predefined, the interactive docs can show them nicely:
Because the available values for the _path parameter_ are predefined, the interactive docs can show them nicely:
<img src="/img/tutorial/path-params/image03.png">
### Working with Python *enumerations* { #working-with-python-enumerations }
### Working with Python _enumerations_ { #working-with-python-enumerations }
The value of the *path parameter* will be an *enumeration member*.
The value of the _path parameter_ will be an _enumeration member_.
#### Compare *enumeration members* { #compare-enumeration-members }
#### Compare _enumeration members_ { #compare-enumeration-members }
You can compare it with the *enumeration member* in your created enum `ModelName`:
You can compare it with the _enumeration member_ in your created enum `ModelName`:
{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
{_ ../../docs_src/path_params/tutorial005_py310.py hl[17] _}
#### Get the *enumeration value* { #get-the-enumeration-value }
#### Get the _enumeration value_ { #get-the-enumeration-value }
You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
{_ ../../docs_src/path_params/tutorial005_py310.py hl[20] _}
/// tip
@ -182,13 +182,13 @@ You could also access the value `"lenet"` with `ModelName.lenet.value`.
///
#### Return *enumeration members* { #return-enumeration-members }
#### Return _enumeration members_ { #return-enumeration-members }
You can return *enum members* from your *path operation*, even nested in a JSON body (e.g. a `dict`).
You can return _enum members_ from your _path operation_, even nested in a JSON body (e.g. a `dict`).
They will be converted to their corresponding values (strings in this case) before returning them to the client:
{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
{_ ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] _}
In your client you will get a JSON response like:
@ -201,15 +201,15 @@ In your client you will get a JSON response like:
## Path parameters containing paths { #path-parameters-containing-paths }
Let's say you have a *path operation* with a path `/files/{file_path}`.
Let's say you have a _path operation_ with a path `/files/{file_path}`.
But you need `file_path` itself to contain a *path*, like `home/johndoe/myfile.txt`.
But you need `file_path` itself to contain a _path_, like `home/johndoe/myfile.txt`.
So, the URL for that file would be something like: `/files/home/johndoe/myfile.txt`.
### OpenAPI support { #openapi-support }
OpenAPI doesn't support a way to declare a *path parameter* to contain a *path* inside, as that could lead to scenarios that are difficult to test and define.
OpenAPI doesn't support a way to declare a _path parameter_ to contain a _path_ inside, as that could lead to scenarios that are difficult to test and define.
Nevertheless, you can still do it in **FastAPI**, using one of the internal tools from Starlette.
@ -217,17 +217,17 @@ And the docs would still work, although not adding any documentation telling tha
### Path convertor { #path-convertor }
Using an option directly from Starlette you can declare a *path parameter* containing a *path* using a URL like:
Using an option directly from Starlette you can declare a _path parameter_ containing a _path_ using a URL like:
```
/files/{file_path:path}
```
In this case, the name of the parameter is `file_path`, and the last part, `:path`, tells it that the parameter should match any *path*.
In this case, the name of the parameter is `file_path`, and the last part, `:path`, tells it that the parameter should match any _path_.
So, you can use it with:
{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
{_ ../../docs_src/path_params/tutorial004_py310.py hl[6] _}
/// tip
@ -241,11 +241,29 @@ In that case, the URL would be: `/files//home/johndoe/myfile.txt`, with a double
With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
* Editor support: error checks, autocompletion, etc.
* Data "<dfn title="converting the string that comes from an HTTP request into Python data">parsing</dfn>"
* Data validation
* API annotation and automatic documentation
- Editor support: error checks, autocompletion, etc.
- Data "<dfn title="converting the string that comes from an HTTP request into Python data">parsing</dfn>"
- Data validation
- API annotation and automatic documentation
And you only have to declare them once.
That's probably the main visible advantage of **FastAPI** compared to alternative frameworks (apart from the raw performance).
### Path Parameters with Validation { #path-params-validation }
You can also add validation to your path parameters using Path.
For example, you can define minimum and maximum allowed values:
{_ ../../docs_src/path_params/tutorial006_py310.py hl[6] _}
In this example:
ge=1 means the value must be greater than or equal to 1
le=1000 means the value must be less than or equal to 1000
If a request is made with a value outside this range, FastAPI will automatically return a validation error.
This helps ensure that invalid data is rejected early and improves the reliability of your API.

7
docs_src/path_params/tutorial006_py310.py

@ -0,0 +1,7 @@
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int = Path(..., ge=1, le=1000)):
return {"item_id": item_id}
Loading…
Cancel
Save