mirror of https://github.com/tiangolo/fastapi.git
📝 Update docs, add first tutorials
This commit is contained in:
parent
400a4a99af
commit
093bb4cd19
Binary file not shown.
|
After Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
**Documentation**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com)
|
**Documentation**: [https://fastapi.tiangolo.com](https://fastapi.tiangolo.com)
|
||||||
|
|
||||||
|
**Source**: [https://github.com/tiangolo/fastapi](https://github.com/tiangolo/fastapi)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+.
|
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+.
|
||||||
|
|
@ -97,7 +99,8 @@ async def read_root():
|
||||||
uvicorn main:app --debug
|
uvicorn main:app --debug
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: the command `uvicorn main:app` refers to:
|
!!! note
|
||||||
|
The command `uvicorn main:app` refers to:
|
||||||
|
|
||||||
* `main`: the file `main.py` (the Python "module").
|
* `main`: the file `main.py` (the Python "module").
|
||||||
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||||
|
|
@ -214,7 +217,7 @@ item: Item
|
||||||
* Validation of data:
|
* Validation of data:
|
||||||
* Automatic and clear errors when the data is invalid.
|
* Automatic and clear errors when the data is invalid.
|
||||||
* Validation even for deeply nested JSON objects.
|
* Validation even for deeply nested JSON objects.
|
||||||
* Serialization of input data: from the network to Python, reading from:
|
* Serialization of input data: conversion of data coming from the network to Python data and types. Reading from:
|
||||||
* JSON.
|
* JSON.
|
||||||
* Forms.
|
* Forms.
|
||||||
* Files.
|
* Files.
|
||||||
|
|
@ -222,7 +225,7 @@ item: Item
|
||||||
* Query parameters.
|
* Query parameters.
|
||||||
* Cookies.
|
* Cookies.
|
||||||
* Headers.
|
* Headers.
|
||||||
* Serialization of output data: from Python to network (as JSON):
|
* Serialization of output data: converting from Python data and types to network data (as JSON):
|
||||||
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
* Convert Python types (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||||
* `datetime` objects.
|
* `datetime` objects.
|
||||||
* `UUID` objects.
|
* `UUID` objects.
|
||||||
|
|
@ -276,7 +279,7 @@ Try changing the line with:
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
For a more complete example including more features, [see the tutorial](tutorial).
|
For a more complete example including more features, [see the tutorial]().
|
||||||
|
|
||||||
**Spoiler alert**: the tutorial, although very short, includes:
|
**Spoiler alert**: the tutorial, although very short, includes:
|
||||||
|
|
||||||
|
|
@ -293,7 +296,7 @@ For a more complete example including more features, [see the tutorial](tutorial
|
||||||
|
|
||||||
Used by Pydantic:
|
Used by Pydantic:
|
||||||
|
|
||||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON parsing.
|
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - for faster JSON <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - for email validation.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -302,7 +305,7 @@ Used by Starlette:
|
||||||
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
* <a href="http://docs.python-requests.org" target="_blank"><code>requests</code></a> - Required if you want to use the `TestClient`.
|
||||||
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Required if you want to use `FileResponse` or `StaticFiles`.
|
* <a href="https://github.com/Tinche/aiofiles" target="_blank"><code>aiofiles</code></a> - Required if you want to use `FileResponse` or `StaticFiles`.
|
||||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
|
||||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form parsing, with `request.form()`.
|
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
|
||||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
|
||||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for `SchemaGenerator` support.
|
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for `SchemaGenerator` support.
|
||||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
The simplest FastAPI file could look like this:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{!tutorial/src/first-steps/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy that to a file `main.py`.
|
||||||
|
|
||||||
|
Run the live server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
The command `uvicorn main:app` refers to:
|
||||||
|
|
||||||
|
* `main`: the file `main.py` (the Python "module").
|
||||||
|
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
|
||||||
|
* `--debug`: make the server restart after code changes. Only use for development.
|
||||||
|
|
||||||
|
You will see an output like:
|
||||||
|
|
||||||
|
```hl_lines="4"
|
||||||
|
INFO: Started reloader process [17961]
|
||||||
|
INFO: Started server process [17962]
|
||||||
|
INFO: Waiting for application startup.
|
||||||
|
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||||
|
```
|
||||||
|
|
||||||
|
That last line shows the URL where your app is being served, in your local machine.
|
||||||
|
|
||||||
|
### Check it
|
||||||
|
|
||||||
|
Open your browser at <a href="http://127.0.0.1:8000" target="_blank">http://127.0.0.1:8000</a>.
|
||||||
|
|
||||||
|
You will see the JSON response as:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{"hello": "world"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Interactive API docs
|
||||||
|
|
||||||
|
Now go to <a href="http://127.0.0.1:8000/docs" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||||
|
|
||||||
|
You will see the automatic interactive API documentation (provided by <a href="https://github.com/swagger-api/swagger-ui" target="_blank">Swagger UI</a>):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### Alternative API docs
|
||||||
|
|
||||||
|
And now, go to <a href="http://127.0.0.1:8000/redoc" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||||
|
|
||||||
|
You will see the alternative automatic documentation (provided by <a href="https://github.com/Rebilly/ReDoc" target="_blank">ReDoc</a>):
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Recap, step by step
|
||||||
|
|
||||||
|
### Step 1: import `FastAPI`
|
||||||
|
|
||||||
|
```Python hl_lines="1"
|
||||||
|
{!tutorial/src/first-steps/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
`FastAPI` is a Python class that provides all the functionality for your API.
|
||||||
|
|
||||||
|
### Step 2: create a `FastAPI` "instance"
|
||||||
|
|
||||||
|
```Python hl_lines="3"
|
||||||
|
{!tutorial/src/first-steps/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here the `app` variable will be an "instance" of the class `FastAPI`.
|
||||||
|
|
||||||
|
This will be the main point of interaction to create all your API endpoints.
|
||||||
|
|
||||||
|
This `app` is the same one referred by `uvicorn` in thet command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
If you create your app like:
|
||||||
|
|
||||||
|
```Python hl_lines="3"
|
||||||
|
{!tutorial/src/first-steps/tutorial002.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
And put it in a file `main.py`, then you would call `uvicorn` like:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:my_awesome_api --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: create an endpoint
|
||||||
|
|
||||||
|
```Python hl_lines="6"
|
||||||
|
{!tutorial/src/first-steps/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `@app.get("/")` tells **FastAPI** that the function right below is an endpoint and that it should go to the path route `/`.
|
||||||
|
|
||||||
|
### Step 4: define the endpoint function
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!tutorial/src/first-steps/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a Python function.
|
||||||
|
|
||||||
|
It will be called by FastAPI whenever it receives a request to the URL "`/`".
|
||||||
|
|
||||||
|
In this case, it is an `async` function.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
You could also define it as a normal function instead of `async def`:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!tutorial/src/first-steps/tutorial003.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
To know the difference, read the section about [Concurrency and `async` / `await`](/async/).
|
||||||
|
|
||||||
|
### Step 5: return the content
|
||||||
|
|
||||||
|
```Python hl_lines="8"
|
||||||
|
{!tutorial/src/first-steps/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can return a `dict`, `list`, singular values as `str`, `int`, etc.
|
||||||
|
|
||||||
|
You can also return Pydantic models (you'll see more about that later).
|
||||||
|
|
||||||
|
There are many other objects and models that will be automatically converted to JSON.
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Sorry! Coming soon... come back in a couple days.
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
This tutorial shows you how to use **FastAPI** with all its features, step by step.
|
||||||
|
|
||||||
|
Eeach section gradually builds on the previous ones, but it's structured to separate topics, so that you can go directly to any specific one to solve your specific API needs.
|
||||||
|
|
||||||
|
It is also built to work as a future reference. So you can come back and see exactly what you need.
|
||||||
|
|
||||||
|
And each section is very short, so you can go directly to what you need and get the information fast.
|
||||||
|
|
||||||
|
## Run the code
|
||||||
|
|
||||||
|
All the code blocks can be copied and used directly (they are actually tested Python files).
|
||||||
|
|
||||||
|
To run any of the examples, copy the code to a file `main.py`, and start `uvicorn` with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uvicorn main:app --debug
|
||||||
|
```
|
||||||
|
|
||||||
|
It is **HIGHLY encouraged** that you write or copy the code, edit it and run it locally.
|
||||||
|
|
||||||
|
Using it in your editor is what really shows you the benefits of FastAPI, seeing how little code you have to write, all the type checks, autocompletion, etc.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Install FastAPI
|
||||||
|
|
||||||
|
The first step is to install FastAPI.
|
||||||
|
|
||||||
|
For the tutorial, you might want to install it with all the optional dependencies and features:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install fastapi[all]
|
||||||
|
```
|
||||||
|
|
||||||
|
...that also includes `uvicorn`, that you can use as the server that runs your code.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
You can also install it part by part.
|
||||||
|
|
||||||
|
This is what you would probably do once you want to deploy your application to production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install fastapi
|
||||||
|
```
|
||||||
|
|
||||||
|
Also install `uvicorn` to work as the server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install uvicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
And the same for each of the optional dependencies that you want to use.
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
You can declare path "parameters" or "variables" with the same syntax used by Python format strings:
|
||||||
|
|
||||||
|
```Python hl_lines="6 7"
|
||||||
|
{!./tutorial/src/path-params/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
The value of the path parameter `item_id` will be passed to your function as the argument `item_id`.
|
||||||
|
|
||||||
|
So, if you run this example and go to <a href="http://127.0.0.1:8000/items/foo" target="_blank">http://127.0.0.1:8000/items/foo</a>, you will see a response of:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{"item_id":"foo"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Path parameters with types
|
||||||
|
|
||||||
|
You can declare the type of a path parameter in the function, using standard Python type annotations:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!./tutorial/src/path-params/tutorial002.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, `item_id` is declared to be an `int`.
|
||||||
|
|
||||||
|
!!! check
|
||||||
|
This will give you editor support inside of your function, with error checks, completion, etc.
|
||||||
|
|
||||||
|
## Data "parsing"
|
||||||
|
|
||||||
|
If you run this example and open your browser at <a href="http://127.0.0.1:8000/items/3" target="_blank">http://127.0.0.1:8000/items/3</a>, you will see a response of:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{"item_id":3}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! check
|
||||||
|
Notice that the value your function received (and returned) is `3`, as a Python `int`, not a string `"3"`.
|
||||||
|
|
||||||
|
So, with that type declaration, **FastAPI** gives you automatic request <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||||
|
|
||||||
|
## Data validation
|
||||||
|
|
||||||
|
But if you go to the browser at <a href="http://127.0.0.1:8000/items/foo" target="_blank">http://127.0.0.1:8000/items/foo</a>, you will see a nice HTTP error of:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": [
|
||||||
|
"path",
|
||||||
|
"item_id"
|
||||||
|
],
|
||||||
|
"msg": "value is not a valid integer",
|
||||||
|
"type": "type_error.integer"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
because the path parameter `item_id` had a value of `"foo"`, which is not an `int`.
|
||||||
|
|
||||||
|
The same error would appear if you provided a `foat` instead of an int, as in: <a href="http://127.0.0.1:8000/items/4.2" target="_blank">http://127.0.0.1:8000/items/4.2</a>
|
||||||
|
|
||||||
|
|
||||||
|
!!! check
|
||||||
|
So, with the same Python type declaration, **FastAPI** gives you data validation.
|
||||||
|
|
||||||
|
Notice that the error also clearly states exactly the point where the validaton didn't pass.
|
||||||
|
|
||||||
|
This is incredibly helpful while developing and debugging code that interacts with your API.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
And when you open your browser at <a href="http://127.0.0.1:8000/docs" target="_blank">http://127.0.0.1:8000/docs</a>, you will see an automatic, interactive, API documentation like:
|
||||||
|
|
||||||
|
<img src="/img/tutorial/path-params/image01.png">
|
||||||
|
|
||||||
|
!!! check
|
||||||
|
Again, just with that same Python type declaration, **FastAPI** gives you automatic, interactive documentation (integrating Swagger UI).
|
||||||
|
|
||||||
|
Notice that the path parameter is declared to be an integer.
|
||||||
|
|
||||||
|
## Standards-based benefits, alternative documentation
|
||||||
|
|
||||||
|
And because the generated schema is from the <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" target="_blank">OpenAPI</a> standard, there are many compatible tools.
|
||||||
|
|
||||||
|
Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc):
|
||||||
|
|
||||||
|
<img src="/img/tutorial/path-params/image02.png">
|
||||||
|
|
||||||
|
The same way, there are many compatible tools. Including code generation tools for many languages.
|
||||||
|
|
||||||
|
## Pydantic
|
||||||
|
|
||||||
|
All the data validation is performed under the hood by <a href="https://pydantic-docs.helpmanual.io/" target="_blank">Pydantic</a>, so you get all the benefits from it. And you know you are in good hands.
|
||||||
|
|
||||||
|
You can use the same type declarations with `str`, `float`, `bool` and many other complex data types.
|
||||||
|
|
||||||
|
These are explored in the next sections of the tutorial.
|
||||||
|
|
||||||
|
## Recap
|
||||||
|
|
||||||
|
With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
|
||||||
|
|
||||||
|
* Editor support: error checks, autocompletion, etc.
|
||||||
|
* Data "<abbr title="converting the string that comes from an HTTP request into Python data">parsing</abbr>"
|
||||||
|
* 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 (appart from the raw performance).
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
When you declare other function parameters that are not part of the path parameters, they are automatically interpreted as "query" parameters.
|
||||||
|
|
||||||
|
```Python hl_lines="9"
|
||||||
|
{!./tutorial/src/query-params/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
The query is the set of key-value pairs that go after the `?` in a URL, separated by `&` characters.
|
||||||
|
|
||||||
|
For example, in the url:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?skip=0&limit=10
|
||||||
|
```
|
||||||
|
|
||||||
|
...the query parameters are:
|
||||||
|
|
||||||
|
* `skip`: with a value of `0`
|
||||||
|
* `limit`: with a value of `10`
|
||||||
|
|
||||||
|
As they are part of the URL, they are "naturally" strings.
|
||||||
|
|
||||||
|
But when you declare them with Python types (in the example above, as `int`), they are converted to that type and validated against it.
|
||||||
|
|
||||||
|
All the same process that applied for path parameters also applies for query parameters:
|
||||||
|
|
||||||
|
* Editor support (obviously)
|
||||||
|
* Data <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>
|
||||||
|
* Data validation
|
||||||
|
* Automatic documentation
|
||||||
|
|
||||||
|
## Defaults
|
||||||
|
|
||||||
|
As query parameters are not a fixed part of a path, they can be optional and can have default values.
|
||||||
|
|
||||||
|
In the example above they have default values of `skip=0` and `limit=10`.
|
||||||
|
|
||||||
|
So, going to the URL:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/
|
||||||
|
```
|
||||||
|
|
||||||
|
would be the same as going to:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?skip=0&limit=10
|
||||||
|
```
|
||||||
|
|
||||||
|
But if you go to, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?skip=20
|
||||||
|
```
|
||||||
|
|
||||||
|
The parameter values in your function will be:
|
||||||
|
|
||||||
|
* `skip=20`: because you set it in the URL
|
||||||
|
* `limit=10`: because that was the default value
|
||||||
|
|
||||||
|
## Optional parameters
|
||||||
|
|
||||||
|
The same way, you can declare optional query parameters, by setting their default to `None`:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!./tutorial/src/query-params/tutorial002.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, the function parameter `q` will be optional, and will be `None` by default.
|
||||||
|
|
||||||
|
!!! check
|
||||||
|
Also notice that **FastAPI** is smart enough to notice that the path parameter `item_id` is a path parameter and `q` is not, so, it's a query parameter.
|
||||||
|
|
||||||
|
## Query parameter type conversion
|
||||||
|
|
||||||
|
You can also declare `bool` types, and they will be converted:
|
||||||
|
|
||||||
|
```Python hl_lines="7"
|
||||||
|
{!./tutorial/src/query-params/tutorial003.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, if you go to:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?short=1
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?short=True
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?short=true
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?short=on
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/items/?short=yes
|
||||||
|
```
|
||||||
|
|
||||||
|
or any other case variation (uppercase, first letter in uppercase, etc), your function will see the parameter `short` with a `bool` value of `True`. Otherwise as `False`.
|
||||||
|
|
||||||
|
|
||||||
|
## Multiple path and query parameters
|
||||||
|
|
||||||
|
You can declare multiple path parameters and query parameters at the same time, **FastAPI** knows which is which.
|
||||||
|
|
||||||
|
And you don't have to declare them in any specific order.
|
||||||
|
|
||||||
|
They will be detected by name:
|
||||||
|
|
||||||
|
```Python hl_lines="6 8"
|
||||||
|
{!./tutorial/src/query-params/tutorial004.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Required query parameters
|
||||||
|
|
||||||
|
When you declare a default value for non-path parameters (for now, we have only seen query parameters), then it is not required.
|
||||||
|
|
||||||
|
If you don't want to add a specific value but just make it optional, set the default as `None`.
|
||||||
|
|
||||||
|
But when you want to make a query parameter required, you can just do not declare any default value:
|
||||||
|
|
||||||
|
```Python hl_lines="6 8"
|
||||||
|
{!./tutorial/src/query-params/tutorial005.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
Here the query parameter `needy` is a required query parameter of type `str`.
|
||||||
|
|
||||||
|
If you open in your browser a URL like:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/users/2/items/foo-item
|
||||||
|
```
|
||||||
|
|
||||||
|
...without adding the required parameter `needy`, you will see an error like:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": [
|
||||||
|
"query",
|
||||||
|
"needy"
|
||||||
|
],
|
||||||
|
"msg": "field required",
|
||||||
|
"type": "value_error.missing"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
As `needy` is a required parameter, you would need to set it in the URL:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://127.0.0.1:8000/users/2/items/foo-item?needy=sooooneedy
|
||||||
|
```
|
||||||
|
|
||||||
|
...this would work:
|
||||||
|
|
||||||
|
```JSON
|
||||||
|
{
|
||||||
|
"item_id": "foo-item",
|
||||||
|
"owner_id": 2,
|
||||||
|
"needy": "sooooneedy"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
my_awesome_api = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@my_awesome_api.get("/")
|
||||||
|
async def root():
|
||||||
|
return {"message": "Hello World"}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/")
|
||||||
|
def root():
|
||||||
|
return {"message": "Hello World"}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/users/{user_id}/items/{item_id}")
|
||||||
|
async def read_user_item(
|
||||||
|
user_id: int, item_id: str, needy: str
|
||||||
|
):
|
||||||
|
item = {"item_id": item_id, "owner_id": user_id, "needy": needy}
|
||||||
|
return item
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
from fastapi import FastAPI
|
|
||||||
|
|
||||||
app = FastAPI()
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/users/{user_id}/items/{item_id}")
|
|
||||||
async def read_user_item(
|
|
||||||
user_id: int, item_id: str, needy: str, q: str = None, short: bool = False
|
|
||||||
):
|
|
||||||
item = {"item_id": item_id, "owner_id": user_id, "needy": needy}
|
|
||||||
if q:
|
|
||||||
item.update({"q": q})
|
|
||||||
if not short:
|
|
||||||
item.update(
|
|
||||||
{"description": "This is an amazing item that has a long description"}
|
|
||||||
)
|
|
||||||
return item
|
|
||||||
Loading…
Reference in New Issue