]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:memo: Update docs, add first tutorials
authorSebastián Ramírez <tiangolo@gmail.com>
Fri, 14 Dec 2018 10:27:02 +0000 (14:27 +0400)
committerSebastián Ramírez <tiangolo@gmail.com>
Fri, 14 Dec 2018 10:27:02 +0000 (14:27 +0400)
90 files changed:
docs/img/tutorial/path-params/image01.png [new file with mode: 0644]
docs/img/tutorial/path-params/image02.png [new file with mode: 0644]
docs/index.md
docs/tutorial/first-steps.md [new file with mode: 0644]
docs/tutorial/index.md [deleted file]
docs/tutorial/intro.md [new file with mode: 0644]
docs/tutorial/path-params.md [new file with mode: 0644]
docs/tutorial/query-params.md [new file with mode: 0644]
docs/tutorial/src/all/tutorial001.py [moved from docs/tutorial/src/tutorial14.py with 100% similarity]
docs/tutorial/src/all/tutorial002.py [moved from docs/tutorial/src/tutorial15.py with 100% similarity]
docs/tutorial/src/all/tutorial003.py [moved from docs/tutorial/src/tutorial16.py with 100% similarity]
docs/tutorial/src/all/tutorial004.py [moved from docs/tutorial/src/tutorial17.py with 100% similarity]
docs/tutorial/src/all/tutorial005.py [moved from docs/tutorial/src/tutorial18.py with 100% similarity]
docs/tutorial/src/all/tutorial006.py [moved from docs/tutorial/src/tutorial19.py with 100% similarity]
docs/tutorial/src/all/tutorial007.py [moved from docs/tutorial/src/tutorial20.py with 100% similarity]
docs/tutorial/src/all/tutorial008.py [moved from docs/tutorial/src/tutorial21.py with 100% similarity]
docs/tutorial/src/all/tutorial009.py [moved from docs/tutorial/src/tutorial22.py with 100% similarity]
docs/tutorial/src/all/tutorial010.py [moved from docs/tutorial/src/tutorial23.py with 100% similarity]
docs/tutorial/src/all/tutorial011.py [moved from docs/tutorial/src/tutorial24.py with 100% similarity]
docs/tutorial/src/all/tutorial012.py [moved from docs/tutorial/src/tutorial25.py with 100% similarity]
docs/tutorial/src/all/tutorial013.py [moved from docs/tutorial/src/tutorial26.py with 100% similarity]
docs/tutorial/src/all/tutorial014.py [moved from docs/tutorial/src/tutorial27.py with 100% similarity]
docs/tutorial/src/all/tutorial015.py [moved from docs/tutorial/src/tutorial28.py with 100% similarity]
docs/tutorial/src/all/tutorial016.py [moved from docs/tutorial/src/tutorial29.py with 100% similarity]
docs/tutorial/src/all/tutorial017.py [moved from docs/tutorial/src/tutorial30.py with 100% similarity]
docs/tutorial/src/all/tutorial018.py [moved from docs/tutorial/src/tutorial31.py with 100% similarity]
docs/tutorial/src/all/tutorial019.py [moved from docs/tutorial/src/tutorial32.py with 100% similarity]
docs/tutorial/src/all/tutorial020.py [moved from docs/tutorial/src/tutorial33.py with 100% similarity]
docs/tutorial/src/all/tutorial021.py [moved from docs/tutorial/src/tutorial34.py with 100% similarity]
docs/tutorial/src/all/tutorial022.py [moved from docs/tutorial/src/tutorial35.py with 100% similarity]
docs/tutorial/src/all/tutorial023.py [moved from docs/tutorial/src/tutorial36.py with 100% similarity]
docs/tutorial/src/all/tutorial024.py [moved from docs/tutorial/src/tutorial37.py with 100% similarity]
docs/tutorial/src/all/tutorial025.py [moved from docs/tutorial/src/tutorial38.py with 100% similarity]
docs/tutorial/src/all/tutorial026.py [moved from docs/tutorial/src/tutorial39.py with 100% similarity]
docs/tutorial/src/all/tutorial027.py [moved from docs/tutorial/src/tutorial40.py with 100% similarity]
docs/tutorial/src/all/tutorial028.py [moved from docs/tutorial/src/tutorial41.py with 100% similarity]
docs/tutorial/src/all/tutorial029.py [moved from docs/tutorial/src/tutorial42.py with 100% similarity]
docs/tutorial/src/all/tutorial030.py [moved from docs/tutorial/src/tutorial43.py with 100% similarity]
docs/tutorial/src/all/tutorial031.py [moved from docs/tutorial/src/tutorial44.py with 100% similarity]
docs/tutorial/src/all/tutorial032.py [moved from docs/tutorial/src/tutorial45.py with 100% similarity]
docs/tutorial/src/all/tutorial033.py [moved from docs/tutorial/src/tutorial46.py with 100% similarity]
docs/tutorial/src/all/tutorial034.py [moved from docs/tutorial/src/tutorial47.py with 100% similarity]
docs/tutorial/src/all/tutorial035.py [moved from docs/tutorial/src/tutorial48.py with 100% similarity]
docs/tutorial/src/all/tutorial036.py [moved from docs/tutorial/src/tutorial49.py with 100% similarity]
docs/tutorial/src/all/tutorial037.py [moved from docs/tutorial/src/tutorial50.py with 100% similarity]
docs/tutorial/src/all/tutorial038.py [moved from docs/tutorial/src/tutorial51.py with 100% similarity]
docs/tutorial/src/all/tutorial039.py [moved from docs/tutorial/src/tutorial52.py with 100% similarity]
docs/tutorial/src/all/tutorial040.py [moved from docs/tutorial/src/tutorial53.py with 100% similarity]
docs/tutorial/src/all/tutorial041.py [moved from docs/tutorial/src/tutorial54.py with 100% similarity]
docs/tutorial/src/all/tutorial042.py [moved from docs/tutorial/src/tutorial55.py with 100% similarity]
docs/tutorial/src/all/tutorial043.py [moved from docs/tutorial/src/tutorial56.py with 100% similarity]
docs/tutorial/src/all/tutorial044.py [moved from docs/tutorial/src/tutorial57.py with 100% similarity]
docs/tutorial/src/all/tutorial045.py [moved from docs/tutorial/src/tutorial58.py with 100% similarity]
docs/tutorial/src/all/tutorial046.py [moved from docs/tutorial/src/tutorial59.py with 100% similarity]
docs/tutorial/src/all/tutorial047.py [moved from docs/tutorial/src/tutorial60.py with 100% similarity]
docs/tutorial/src/all/tutorial048.py [moved from docs/tutorial/src/tutorial61.py with 100% similarity]
docs/tutorial/src/all/tutorial049.py [moved from docs/tutorial/src/tutorial62.py with 100% similarity]
docs/tutorial/src/all/tutorial050.py [moved from docs/tutorial/src/tutorial63.py with 100% similarity]
docs/tutorial/src/all/tutorial051.py [moved from docs/tutorial/src/tutorial64.py with 100% similarity]
docs/tutorial/src/all/tutorial052.py [moved from docs/tutorial/src/tutorial65.py with 100% similarity]
docs/tutorial/src/all/tutorial053.py [moved from docs/tutorial/src/tutorial66.py with 100% similarity]
docs/tutorial/src/all/tutorial054.py [moved from docs/tutorial/src/tutorial67.py with 100% similarity]
docs/tutorial/src/all/tutorial055.py [moved from docs/tutorial/src/tutorial68.py with 100% similarity]
docs/tutorial/src/all/tutorial056.py [moved from docs/tutorial/src/tutorial69.py with 100% similarity]
docs/tutorial/src/all/tutorial057.py [moved from docs/tutorial/src/tutorial70.py with 100% similarity]
docs/tutorial/src/all/tutorial058.py [moved from docs/tutorial/src/tutorial71.py with 100% similarity]
docs/tutorial/src/all/tutorial059.py [moved from docs/tutorial/src/tutorial72.py with 100% similarity]
docs/tutorial/src/all/tutorial060.py [moved from docs/tutorial/src/tutorial73.py with 100% similarity]
docs/tutorial/src/all/tutorial061.py [moved from docs/tutorial/src/tutorial74.py with 100% similarity]
docs/tutorial/src/all/tutorial062.py [moved from docs/tutorial/src/tutorial75.py with 100% similarity]
docs/tutorial/src/all/tutorial063.py [moved from docs/tutorial/src/tutorial76.py with 100% similarity]
docs/tutorial/src/all/tutorial064.py [moved from docs/tutorial/src/tutorial77.py with 100% similarity]
docs/tutorial/src/all/tutorial065.py [moved from docs/tutorial/src/tutorial78.py with 100% similarity]
docs/tutorial/src/all/tutorial066.py [moved from docs/tutorial/src/tutorial79.py with 100% similarity]
docs/tutorial/src/body/tutorial001.py [moved from docs/tutorial/src/tutorial10.py with 100% similarity]
docs/tutorial/src/body/tutorial002.py [moved from docs/tutorial/src/tutorial11.py with 100% similarity]
docs/tutorial/src/body/tutorial003.py [moved from docs/tutorial/src/tutorial12.py with 100% similarity]
docs/tutorial/src/body/tutorial004.py [moved from docs/tutorial/src/tutorial13.py with 100% similarity]
docs/tutorial/src/first-steps/tutorial001.py [moved from docs/tutorial/src/tutorial01.py with 100% similarity]
docs/tutorial/src/first-steps/tutorial002.py [new file with mode: 0644]
docs/tutorial/src/first-steps/tutorial003.py [new file with mode: 0644]
docs/tutorial/src/path-params/tutorial001.py [moved from docs/tutorial/src/tutorial02.py with 100% similarity]
docs/tutorial/src/path-params/tutorial002.py [moved from docs/tutorial/src/tutorial03.py with 100% similarity]
docs/tutorial/src/path-params/tutorial003.py [moved from docs/tutorial/src/tutorial04.py with 100% similarity]
docs/tutorial/src/query-params/tutorial001.py [moved from docs/tutorial/src/tutorial05.py with 100% similarity]
docs/tutorial/src/query-params/tutorial002.py [moved from docs/tutorial/src/tutorial06.py with 100% similarity]
docs/tutorial/src/query-params/tutorial003.py [moved from docs/tutorial/src/tutorial07.py with 100% similarity]
docs/tutorial/src/query-params/tutorial004.py [moved from docs/tutorial/src/tutorial08.py with 100% similarity]
docs/tutorial/src/query-params/tutorial005.py [new file with mode: 0644]
docs/tutorial/src/tutorial09.py [deleted file]

diff --git a/docs/img/tutorial/path-params/image01.png b/docs/img/tutorial/path-params/image01.png
new file mode 100644 (file)
index 0000000..b5187c6
Binary files /dev/null and b/docs/img/tutorial/path-params/image01.png differ
diff --git a/docs/img/tutorial/path-params/image02.png b/docs/img/tutorial/path-params/image02.png
new file mode 100644 (file)
index 0000000..b86cf49
Binary files /dev/null and b/docs/img/tutorial/path-params/image02.png differ
index 40df4afbe09cb0ba6dae7631ee9a94ac1572f58a..39d40509c112dad1ba8541c8fd8647463f7d246b 100644 (file)
@@ -20,6 +20,8 @@
 
 **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+.
@@ -97,11 +99,12 @@ async def read_root():
 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").
-* `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.
+    * `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.
 
 ### Check it
 
@@ -214,7 +217,7 @@ item: Item
 * Validation of data:
     * Automatic and clear errors when the data is invalid.
     * 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.
     * Forms.
     * Files.
@@ -222,7 +225,7 @@ item: Item
     * Query parameters.
     * Cookies.
     * 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).
     * `datetime` objects.
     * `UUID` objects.
@@ -276,7 +279,7 @@ Try changing the line with:
 ![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
 
 
-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:
 
@@ -293,7 +296,7 @@ For a more complete example including more features, [see the tutorial](tutorial
 
 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.
 
 
@@ -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="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="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://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.
diff --git a/docs/tutorial/first-steps.md b/docs/tutorial/first-steps.md
new file mode 100644 (file)
index 0000000..a09a144
--- /dev/null
@@ -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>):
+
+![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
+
+
+### 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>):
+
+![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
+
+## 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.
diff --git a/docs/tutorial/index.md b/docs/tutorial/index.md
deleted file mode 100644 (file)
index 39fe646..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Sorry! Coming soon... come back in a couple days.
\ No newline at end of file
diff --git a/docs/tutorial/intro.md b/docs/tutorial/intro.md
new file mode 100644 (file)
index 0000000..a5fb9bf
--- /dev/null
@@ -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.
diff --git a/docs/tutorial/path-params.md b/docs/tutorial/path-params.md
new file mode 100644 (file)
index 0000000..5a38158
--- /dev/null
@@ -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).
\ No newline at end of file
diff --git a/docs/tutorial/query-params.md b/docs/tutorial/query-params.md
new file mode 100644 (file)
index 0000000..e58fe27
--- /dev/null
@@ -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"
+}
+```
\ No newline at end of file
diff --git a/docs/tutorial/src/first-steps/tutorial002.py b/docs/tutorial/src/first-steps/tutorial002.py
new file mode 100644 (file)
index 0000000..ca7d48c
--- /dev/null
@@ -0,0 +1,8 @@
+from fastapi import FastAPI
+
+my_awesome_api = FastAPI()
+
+
+@my_awesome_api.get("/")
+async def root():
+    return {"message": "Hello World"}
diff --git a/docs/tutorial/src/first-steps/tutorial003.py b/docs/tutorial/src/first-steps/tutorial003.py
new file mode 100644 (file)
index 0000000..e30b827
--- /dev/null
@@ -0,0 +1,8 @@
+from fastapi import FastAPI
+
+app = FastAPI()
+
+
+@app.get("/")
+def root():
+    return {"message": "Hello World"}
diff --git a/docs/tutorial/src/query-params/tutorial005.py b/docs/tutorial/src/query-params/tutorial005.py
new file mode 100644 (file)
index 0000000..62da63f
--- /dev/null
@@ -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
diff --git a/docs/tutorial/src/tutorial09.py b/docs/tutorial/src/tutorial09.py
deleted file mode 100644 (file)
index 125bce9..0000000
+++ /dev/null
@@ -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