Compare commits

...

102 Commits

Author SHA1 Message Date
Sebastián Ramírez
b87072bc12 🔖 Release version 0.58.0 2020-06-15 13:18:36 +02:00
Sebastián Ramírez
04e2bfafbc 📝 Update release notes 2020-06-15 13:13:53 +02:00
Sebastián Ramírez
181a32236a Deep merge OpenAPI responses (#1577)
* override successful response

*  Add deep_dict_udpate

*  Merge additional responses with generated responses

* 🍱 Update docs screenshot

Co-authored-by: rkbeatss <rkaus053@uottawa.ca>
2020-06-15 13:12:12 +02:00
Sebastián Ramírez
1f54a8e0a1 📝 Update release notes 2020-06-15 12:42:48 +02:00
Andrew
d63475bb7d 📝 Mention in docs that subapps don't fire events (#1554)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-14 18:25:10 +02:00
Sebastián Ramírez
5a3c5f1523 📝 Update release notes 2020-06-14 18:12:51 +02:00
Andrew
12bc9285f7 🐛 Fix body validation error response, remove variable name when it is not embedded (#1553) 2020-06-14 18:07:39 +02:00
Sebastián Ramírez
31df2ea940 📝 Update release notes 2020-06-14 17:56:12 +02:00
Sebastián Ramírez
50b90dd6a4 📝 Update release notes 2020-06-14 17:55:13 +02:00
Andrew
7dd881334d 🐛 Fix testing security scopes when using dependency overrides (#1549)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-14 17:54:46 +02:00
Vinny Do
530fc8ff3f 🐛 Fix JSON Schema "not" keyword (#1548) 2020-06-14 15:46:49 +02:00
Sebastián Ramírez
ef460b4d23 📝 Update release notes 2020-06-14 15:40:18 +02:00
mikaello
b591de2ace Add support for OpenAPI servers metadata (#1547)
* feat: add servers option for OpenAPI

Closes #872

*  Use dicts for OpenAPI servers

* ♻️ Update OpenAPI Server model to support relative URLs

*  Add tests for OpenAPI servers

* ♻️ Re-order parameter location of servers for OpenAPI

* 🎨 Format code

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-14 15:38:29 +02:00
Sebastián Ramírez
34c857b7cb 🔖 Release version 0.57.0 2020-06-13 23:13:25 +02:00
Sebastián Ramírez
c78bc0c82d 📝 Update release notes 2020-06-13 23:08:20 +02:00
JAYATI SHRIVASTAVA
194446e51a 🔥 Remove broken external link (#1565) 2020-06-13 23:07:11 +02:00
Sebastián Ramírez
777e2151e6 📝 Update release notes 2020-06-13 22:55:30 +02:00
Sebastián Ramírez
5ce5bdba0b 📝 Update release notes 2020-06-13 22:52:59 +02:00
Chih Sean Hsu
e4300769ac 📝 Update tutorial for WebSockets with dependencies (#1540)
* fix websockets/tutorial002.py

* fix tutorial002 in ws to correspond with test case

* reformat websocket tutorial002

* fix websocket tutorial002 coverage

* 📝 Update example for WebSockets with Depends

*  Update and refactor tests for WebSockets with dependencies

* 👷 Trigger Travis, as it's not reporting to Codecov

*  Update WebSocket tests to raise coverage

Co-authored-by: Chih Sean Hsu <Sean@Sean-Mac.local>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 22:51:34 +02:00
retnikt
c6dd627bdd Add support for Python's http.HTTPStatus in status_code (#1534)
* Normalise IntEnums to ints for route status codes

Closes #1349

* add tests for status code enum support

* add docs for status code enum support

* add endpoint test for enum status code

* 📝 Update note about http.HTTPStatus

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 19:40:10 +02:00
Sebastián Ramírez
6576f724bb 📝 Update release notes 2020-06-13 19:22:08 +02:00
Sebastián Ramírez
91a6736d0e 📝 Update release notes 2020-06-13 19:20:48 +02:00
Patrick Wang
8fb755703d When using Pydantic models with __root__ use the internal value in jsonable_encoder (#1524) 2020-06-13 19:20:11 +02:00
Yankee
748bedd37c 📝 Updated docs for path-params (#1521)
* Added response example; URL for quick access; typo fixes

* Added line breaks for readability

* Fix typo on redoc url

* 📝 Update format, links, rewordings

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 19:14:23 +02:00
Sebastián Ramírez
bf58788f29 📝 Update release notes 2020-06-13 18:54:47 +02:00
Yankee
5f78ba4a31 📝 Update docs for first-steps, links, rewordings (#1518)
* ✏️ Typo/readability fixes for first-steps documentation

* 📝 Update link and small rewordings

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 18:53:31 +02:00
Sebastián Ramírez
db9f827263 📝 Update release notes 2020-06-13 18:18:27 +02:00
TiewKH
dd9e94cf21 Enable showCommonExtensions and showExtensions in SwaggerUI (#1466)
* Set showExtensions and showCommonExtensions to true

* Clean up comma

Co-authored-by: tiewkeehui <keehuitiew@airasia.com>
2020-06-13 18:16:34 +02:00
Sebastián Ramírez
e482d74241 📝 Update release notes 2020-06-13 18:13:06 +02:00
Richard Hoekstra
bd2acbcabb Export OAuth2PasswordRequestFormStrict from security (#1462)
* Update __init__.py

Fixes an import error:     

from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestFormStrict
ImportError: cannot import name 'OAuth2PasswordRequestFormStrict'

* Simplify import of OAuth2PasswordRequestFormStrict

* Simplify import of OAuth2PasswordRequestFormStrict
2020-06-13 18:08:08 +02:00
Sebastián Ramírez
f913d469a8 📝 Update release notes 2020-06-13 18:05:22 +02:00
Roman Tezikov
66cb266641 📝 Add docs for default_response_class (#1455)
*  Add docs to default_response_class

*  create a tip

*  fixing the tip

* 🚑 grammar

* 📝 Update docs for default response class

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 18:02:45 +02:00
Sebastián Ramírez
74954894c5 📝 Update release notes 2020-06-13 15:26:42 +02:00
William Hayes
ceedfccde0 📝 Document additional parameters for response_model (#1427)
* Documented additional parameters

These are included in a recent PR (https://github.com/tiangolo/fastapi/pull/1166) but not in the docs yet.
* response_model_exclude_none
* response_model_exclude_defaults

* 📝 Update note about response_model_exclude_defaults and response_model_exclude_none

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 15:23:29 +02:00
Sebastián Ramírez
2ee0eedf23 📝 Update release notes 2020-06-13 15:08:10 +02:00
Koudai Aono
c0f3019764 📝 Add PyCharm Pydantic plugin to docs (#1420)
* add pydantic pycharm plugin in document

* 📝 Update PyCharm Pydantic plugin note

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 15:05:59 +02:00
Sebastián Ramírez
dd6d0cb23c 📝 Update release notes 2020-06-13 14:51:21 +02:00
Chen Rotem Levy
fe15620df3 🎨 Update and clarify testing function name (#1395)
test_create_existing_token -> test_create_existing_item
2020-06-13 14:50:14 +02:00
Sebastián Ramírez
6af857f206 📝 Update release notes 2020-06-13 14:47:03 +02:00
obataku
7ce756f9dd 🐛 Fix duplicated headers set by indirect dependencies (#1386)
* Added test for repeating cookies in response headers

* update `response` headers, status code to match `sub_response` in `solve_dependencies` only if necessary; fix formatting of scottsmith2gmail's test

* restore code coverage, remove dead code from `solve_dependencies`

Co-authored-by: Scott Smith <scott.smith.2@gmail.com>
2020-06-13 14:44:51 +02:00
Sebastián Ramírez
c0b1fddb31 📝 Update release notes 2020-06-13 14:39:58 +02:00
Nick Rushton
9aea85a84e ⬆ Upgrade Starlette dependency to 0.13.4 (#1361) 2020-06-13 14:38:08 +02:00
Sebastián Ramírez
fddd1c12de 📝 Update release notes 2020-06-13 14:36:27 +02:00
Aviram Hassan
b13a4baf32 Add better JSON decode error handling, improve feedback for client after invalid JSON requests (#1354)
* Request body error, raise RequestValidationError instead of HTTPException in case JSON decode failure

* add missing test case for body general exception
2020-06-13 14:33:27 +02:00
Sebastián Ramírez
5ffa18f10f 📝 Update release notes 2020-06-13 14:06:12 +02:00
Sebastián Ramírez
828915baf5 📝 Update Tags metadata title 2020-06-13 14:02:58 +02:00
Thomas Maschler
a071ddf3cd Add support for tag metadata in OpenAPI (#1348)
* Allow to add OpenAPI tag descriptions

* fix type hint

* fix type hint 2

* refactor test to assure 100% coverage

* 📝 Update tags metadata example

* 📝 Update docs for tags metadata

*  Move tags metadata test to tutorial subdir

* 🎨 Update format in applications

* 🍱 Update docs UI image based on new example

* 🎨 Apply formatting after solving conflicts

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 13:58:06 +02:00
Sebastián Ramírez
3651b8a30f 📝 Update release notes 2020-06-13 12:27:00 +02:00
Sebastián Ramírez
0d73b9ff1c 🔧 Add basic setup for Russian translations (#1566) 2020-06-13 12:26:15 +02:00
Sebastián Ramírez
43235cf236 📝 Update release notes 2020-06-13 09:47:36 +02:00
Xie Wei
269a155583 🔥 Remove obsolete Chinese articles after translations (#1510) 2020-06-13 09:45:48 +02:00
Sebastián Ramírez
12433d51dd 📝 Update release notes 2020-06-13 01:25:29 +02:00
Rupsi Kaushik
3699e17212 Implement __repr__ methods for path parameters to simplify debugging (#1560)
* repr description added to Depends class

* repr description added to Security subclass

* get rid of __repr__ in security since it will inherit from super

* make code format consistent with rest

* add desc for rest of the classes

* Update fastapi/params.py

remove trailing whitespace

Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>

* Implement __repr__

* fix formatting

* formatting again

* ran formatting

* added basic testing

* basic tests added to rest of the classes

* added more test coverage and simplified test file

Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com>
Co-authored-by: Jayati Shrivastava <gaurijove@gmail.com>
2020-06-13 01:22:30 +02:00
Sebastián Ramírez
8231fbede4 🔖 Release version 0.56.1 2020-06-13 01:17:06 +02:00
Sebastián Ramírez
50bc14b835 📝 Update release notes 2020-06-13 01:14:58 +02:00
Kai Chen
4310c89c83 📝 Add link to Advanced User Guide: response status code (#1512) 2020-06-13 01:12:59 +02:00
Sebastián Ramírez
d39dd06a22 📝 Update release notes 2020-06-13 00:57:34 +02:00
kota matsuoka
a0ab47e89e 🎨 Remove unused f-string (#1526) 2020-06-13 00:56:00 +02:00
Sebastián Ramírez
5cbcb9a965 📝 Update release notes 2020-06-13 00:55:30 +02:00
Xie Wei
801ceaec80 🌐 Add Chinese translation for query-params-str-validations.md (#1500)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 00:53:00 +02:00
Sebastián Ramírez
c7334ae9f8 📝 Update release notes 2020-06-13 00:50:22 +02:00
Xie Wei
d737599a2c 🌐 Add Chinese translation for body.md (#1492)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 00:47:50 +02:00
Sebastián Ramírez
d2d72a8e4a 📝 Update release notes 2020-06-13 00:43:07 +02:00
Xie Wei
7895c12fa1 🌐 Add Chinese translation for help-fastapi.md (#1465)
* add chinese translation for help-fastapi.md

* improve translations

Co-authored-by: Waynerv <wei.xie@woqutech.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 00:40:05 +02:00
Sebastián Ramírez
5f6a14c413 📝 Update release notes 2020-06-13 00:29:43 +02:00
Xie Wei
2b4e88fa98 🌐 Add Chinese translation for query-params.md (#1454)
Co-authored-by: Waynerv <wei.xie@woqutech.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 00:26:40 +02:00
Sebastián Ramírez
11723bca27 📝 Update release notes 2020-06-13 00:21:53 +02:00
Xie Wei
b49517a64f 🌐 Add Chinese translation for contributing.md (#1460)
Co-authored-by: Waynerv <wei.xie@woqutech.com>
2020-06-13 00:18:57 +02:00
Sebastián Ramírez
f910e0c96c 📝 Update release notes 2020-06-13 00:18:20 +02:00
Xie Wei
c1ba2a3127 🌐 Add Chinese translation for path-params.md (#1453)
* add chinese translation for path-params.md

* improve translations

* improve translations

Co-authored-by: Waynerv <wei.xie@woqutech.com>
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-13 00:14:58 +02:00
Sebastián Ramírez
28396173c7 📝 Update release notes 2020-06-13 00:09:41 +02:00
Kabir Khan
69974b792e 📝 Add cookiecutter-spacy-fastapi to docs (#1390) 2020-06-13 00:06:53 +02:00
Sebastián Ramírez
352412a3cb 📝 Update release notes 2020-06-12 23:46:05 +02:00
yaegassy
745ab48d65 📝 Add docs in Python Types for Optional (#1377)
* docs: Fix pydantic example in python-types.md

* 📝 Update Python Types Intro to include Optional

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-12 23:44:23 +02:00
Sebastián Ramírez
4a5cda0d77 📝 Update release notes 2020-06-12 23:00:09 +02:00
Micah Rosales
b90bf2da9e 🐛 Fix callable class generator dependencies (#1365)
* Fix callable class generator dependencies

* workaround to support asynccontextmanager backfill for pre python3.7

Co-authored-by: Micah Rosales <mrosales@users.noreply.github.com>
2020-06-12 22:57:59 +02:00
Sebastián Ramírez
a552cbdf59 📝 Update release notes 2020-06-12 22:47:37 +02:00
Dylan Anthony
2351fb5623 🔇 Remove error log when parsing malformed JSON body as it's a client error (#1351) 2020-06-12 22:44:40 +02:00
Sebastián Ramírez
807522c616 📝 Update release notes 2020-06-12 22:42:40 +02:00
Xie Wei
81a529c251 🌐 Translate doc first steps to Chinese (#1323)
* WIP:add Chinese translation for first steps doc

* add Chinese translation for first steps doc

* improve translations

Co-authored-by: Waynerv <wei.xie@woqutech.com>
2020-06-12 22:39:26 +02:00
Sebastián Ramírez
7efc15aeef 📝 Update release notes 2020-06-12 22:37:34 +02:00
Nik
d66d8379c0 🐛 Fix OpenAPI generation when using callbacks with routers including Pydantic models (#1322)
* drop model class from additional responses when generating openapi

* ♻️ Copy response to be mutated early in get_openapi_path

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-12 22:35:59 +02:00
Sebastián Ramírez
5a00467951 📝 Update release notes 2020-06-12 22:01:22 +02:00
Kazantcev Andrey
434d32b891 Optimize regexp pattern in get_path_param_names (#1243) 2020-06-12 21:59:32 +02:00
Sebastián Ramírez
535247ffc4 📝 Update release notes 2020-06-12 21:43:17 +02:00
Pankaj Giri
7e2518350a 📝 Remove *, from functions where it's not needed #1234 (#1239)
* Fix for - [FEATURE] Remove *, where it's not needed #1234

* 🔥 Remove unnecessary arg *,

* 🎨 Update docs format highlight lines

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-12 21:41:44 +02:00
Sebastián Ramírez
1b2a7546af 📝 Update release notes 2020-06-12 18:58:15 +02:00
Cesare De Cal
2d9bb64047 🌐 Generated new translation directory to support Italian docs (#1557)
* Generated new translation directory to support Italian docs

* ⬆️ Upgrade/pin pytest to >= 5.4.3

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-12 18:53:52 +02:00
Sebastián Ramírez
072c2bc7f9 🔖 Release version 0.56.0 2020-06-12 00:22:17 +02:00
Sebastián Ramírez
da7826b0eb 📝 Update release notes 2020-06-12 00:05:17 +02:00
Ingmar Steen
2f478eeca6 Add support for ASGI root_path for openapi docs (#1199)
* Use ASGI root_path when it is provided and openapi_prefix is empty.

* Strip trailing slashes from root_path.

* Please mypy.

* Fix extending openapi test.

* 📝 Add docs and tutorial for using root_path behind a proxy

* ♻️ Refactor application root_path logic, use root_path, deprecate openapi_prefix

*  Add tests for Behind a Proxy with root_path

* ♻️ Refactor test

* 📝 Update/add docs for Sub-applications and Behind a Proxy

* 📝 Update Extending OpenAPI with openapi_prefix parameter

*  Add test for deprecated openapi_prefix

Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
2020-06-11 23:53:19 +02:00
Sebastián Ramírez
543ef7753a 📝 Update release notes 2020-06-07 22:02:36 +02:00
Sebastián Ramírez
88a887329e 📝 Update help and issue templates (#1531)
* 📝 Update help docs: Gitter, issues, links

also fix Gitter tab padding

* 📝 Update new GitHub issue templates

* 📝 Add note about extra help required for new issues
2020-06-07 22:00:15 +02:00
Sebastián Ramírez
8cfe254400 📝 Update release notes 2020-06-05 17:35:39 +02:00
Sebastián Ramírez
bfd46e562b 🔧 Update issue-manager GitHub action (#1520) 2020-06-05 17:34:43 +02:00
Sebastián Ramírez
a0e4d38bea 📝 Update release notes 2020-05-24 08:48:52 +02:00
Sebastián Ramírez
b0414b9929 📝 Add new links (#1467)
* 📝 Update opinions including Netflix and add format

* 📝 Add new external links

* 📝 Update README
2020-05-24 08:48:09 +02:00
Sebastián Ramírez
3b4413f9f5 📝 Update release notes 2020-05-24 07:47:19 +02:00
Xie Wei
374cdf29a9 🌐 Add Chinese translation for docs/python-types.md (#1197)
* Add Chinese tranlation for docs/python-types.md

* improve translation
2020-05-24 07:43:26 +02:00
Sebastián Ramírez
8d844bc5cf 🔖 Release version 0.55.1 2020-05-23 18:59:14 +02:00
Sebastián Ramírez
1092261ae1 📝 Update release notes 2020-05-23 18:59:14 +02:00
Sebastián Ramírez
5984233223 🐛 Fix Enum handling with their own schema definitions (#1463)
* 🐛 Fix extra support for enum with its own schema

*  Fix/update test for enum with its own schema

* 🐛 Fix type declarations

* 🔧 Update format and lint scripts to support locally installed Pydantic and Starlette

* 🐛 Add temporary type ignores while enum schemas are merged
2020-05-23 18:56:18 +02:00
131 changed files with 5207 additions and 561 deletions

View File

@@ -1,62 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG]"
labels: bug
assignees: ''
---
### Describe the bug
Write here a clear and concise description of what the bug is.
### To Reproduce
Steps to reproduce the behavior with a minimum self-contained file.
Replace each part with your own scenario:
1. Create a file with:
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
```
3. Open the browser and call the endpoint `/`.
4. It returns a JSON with `{"Hello": "World"}`.
5. But I expected it to return `{"Hello": "Sara"}`.
### Expected behavior
Add a clear and concise description of what you expected to happen.
### Screenshots
If applicable, add screenshots to help explain your problem.
### Environment
- OS: [e.g. Linux / Windows / macOS]
- FastAPI Version [e.g. 0.3.0], get it with:
```bash
python -c "import fastapi; print(fastapi.__version__)"
```
- Python version, get it with:
```bash
python --version
```
### Additional context
Add any other context about the problem here.

View File

@@ -1,26 +1,104 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[FEATURE]"
title: ""
labels: enhancement
assignees: ''
---
### Is your feature request related to a problem
### First check
Is your feature request related to a problem?
* [ ] I added a very descriptive title to this issue.
* [ ] I used the GitHub search to find a similar issue and didn't find it.
* [ ] I searched the FastAPI documentation, with the integrated search.
* [ ] I already searched in Google "How to X in FastAPI" and didn't find any information.
* [ ] I already read and followed all the tutorial in the docs and didn't find an answer.
* [ ] I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic).
* [ ] I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui).
* [ ] I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc).
* [ ] After submitting this, I commit to:
* Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
* Or, I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Implement a Pull Request for a confirmed bug.
Add a clear and concise description of what the problem is. Ex. I want to be able to [...] but I can't because [...]
<!--
I'm asking all this because answering questions and solving problems in GitHub issues consumes a lot of time. I end up not being able to add new features, fix bugs, review Pull Requests, etc. as fast as I wish because I have to spend too much time handling issues.
All that, on top of all the incredible help provided by a bunch of community members that give a lot of their time to come here and help others.
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
-->
### Example
Here's a self-contained [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with my use case:
<!-- Replace the code below with your own self-contained, minimal, reproducible, example -->
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
```
### Description
<!-- Replace the content below with your own feature request -->
* Open the browser and call the endpoint `/`.
* It returns a JSON with `{"Hello": "World"}`.
* I would like it to have an extra parameter to teleport me to the moon and back.
### The solution you would like
Add a clear and concise description of what you want to happen.
<!-- Replace this with your own content -->
I would like it to have a `teleport_to_moon` parameter that defaults to `False`, and can be set to `True` to teleport me:
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/", teleport_to_moon=True)
def read_root():
return {"Hello": "World"}
```
### Describe alternatives you've considered
Add a clear and concise description of any alternative solutions or features you've considered.
<!-- Replace this with your own ideas -->
To wait for Space X moon travel plans to drop down long after they release them. But I would rather teleport.
### Environment
* OS: [e.g. Linux / Windows / macOS]:
* FastAPI Version [e.g. 0.3.0]:
To know the FastAPI version use:
```bash
python -c "import fastapi; print(fastapi.__version__)"
```
* Python version:
To know the Python version use:
```bash
python --version
```
### Additional context
Add any other context or screenshots about the feature request here.
<!-- Add any other context or screenshots about the question here. -->

View File

@@ -1,24 +1,81 @@
---
name: Question
about: Ask a question
title: "[QUESTION]"
name: Question or Problem
about: Ask a question or ask about a problem
title: ""
labels: question
assignees: ''
assignees: ""
---
### First check
* [ ] I added a very descriptive title to this issue.
* [ ] I used the GitHub search to find a similar issue and didn't find it.
* [ ] I searched the FastAPI documentation, with the integrated search.
* [ ] I already searched in Google "How to X in FastAPI" and didn't find any information.
* [ ] I already read and followed all the tutorial in the docs and didn't find an answer.
* [ ] I already checked if it is not related to FastAPI but to [Pydantic](https://github.com/samuelcolvin/pydantic).
* [ ] I already checked if it is not related to FastAPI but to [Swagger UI](https://github.com/swagger-api/swagger-ui).
* [ ] I already checked if it is not related to FastAPI but to [ReDoc](https://github.com/Redocly/redoc).
* [ ] After submitting this, I commit to one of:
* Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.
* I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.
* Implement a Pull Request for a confirmed bug.
<!--
I'm asking all this because answering questions and solving problems in GitHub issues consumes a lot of time. I end up not being able to add new features, fix bugs, review Pull Requests, etc. as fast as I wish because I have to spend too much time handling issues.
All that, on top of all the incredible help provided by a bunch of community members that give a lot of their time to come here and help others.
That's a lot of work they are doing, but if more FastAPI users came to help others like them just a little bit more, it would be much less effort for them (and you and me 😅).
-->
### Example
Here's a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with my use case:
<!-- Replace the code below with your own self-contained, minimal, reproducible, example, if I (or someone) can copy it, run it, and see it right away, there's a much higher chance I (or someone) will be able to help you -->
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
```
### Description
How can I [...]?
<!-- Replace the content below with your own problem, question, or error -->
Is it possible to [...]?
* Open the browser and call the endpoint `/`.
* It returns a JSON with `{"Hello": "World"}`.
* But I expected it to return `{"Hello": "Sara"}`.
### Environment
* OS: [e.g. Linux / Windows / macOS]:
* FastAPI Version [e.g. 0.3.0]:
To know the FastAPI version use:
```bash
python -c "import fastapi; print(fastapi.__version__)"
```
* Python version:
To know the Python version use:
```bash
python --version
```
### Additional context
Add any other context or screenshots about the question here.
<!-- Add any other context or screenshots about the question here. -->

View File

@@ -1,15 +1,24 @@
name: Issue Manager
on:
schedule:
- cron: "0 0 * * *"
- cron: "0 0 * * *"
issue_comment:
types:
- created
- edited
issues:
types:
- labeled
jobs:
issue-manager:
runs-on: ubuntu-latest
steps:
- uses: tiangolo/issue-manager@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
config: >
- uses: tiangolo/issue-manager@0.2.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config: >
{
"answered": {
"users": ["tiangolo", "dmontagu"],

View File

@@ -45,38 +45,44 @@ The key features are:
## Opinions
"*[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products.*"
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"*Im over the moon excited about **FastAPI**. Its so fun!*"
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, the FastAPI of CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>

View File

@@ -0,0 +1,281 @@
# Behind a Proxy
In some situations, you might need to use a **proxy** server like Traefik or Nginx with a configuration that adds an extra path prefix that is not seen by your application.
In these cases you can use `root_path` to configure your application.
The `root_path` is a mechanism provided by the ASGI specification (that FastAPI is built on, through Starlette).
The `root_path` is used to handle these specific cases.
And it's also used internally when mounting sub-applications.
## Proxy with a stripped path prefix
Having a proxy with a stripped path prefix, in this case, means that you could declare a path at `/app` in your code, but then, you add a layer on top (the proxy) that would put your **FastAPI** application under a path like `/api/v1`.
In this case, the original path `/app` would actually be served at `/api/v1/app`.
Even though all your code is written assuming there's just `/app`.
And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to Uvicorn, keep your application convinced that it is serving at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`.
Up to here, everything would work as normally.
But then, when you open the integrated docs UI (the frontend), it would expect to get the OpenAPI schema at `/openapi.json`, instead of `/api/v1/openapi.json`.
So, the frontend (that runs in the browser) would try to reach `/openapi.json` and wouldn't be able to get the OpenAPI schema.
Because we have a proxy with a path prefix of `/api/v1` for our app, the frontend needs to fetch the OpenAPI schema at `/api/v1/openapi.json`.
```mermaid
graph LR
browser("Browser")
proxy["Proxy on http://0.0.0.0:9999/api/v1/app"]
server["Server on http://127.0.0.1:8000/app"]
browser --> proxy
proxy --> server
```
!!! tip
The IP `0.0.0.0` is commonly used to mean that the program listens on all the IPs available in that machine/server.
The docs UI would also need that the JSON payload with the OpenAPI schema has the path defined as `/api/v1/app` (behind the proxy) instead of `/app`. For example, something like:
```JSON hl_lines="5"
{
"openapi": "3.0.2",
// More stuff here
"paths": {
"/api/v1/app": {
// More stuff here
}
}
}
```
In this example, the "Proxy" could be something like **Traefik**. And the server would be something like **Uvicorn**, running your FastAPI application.
### Providing the `root_path`
To achieve this, you can use the command line option `--root-path` like:
<div class="termy">
```console
$ uvicorn main:app --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
If you use Hypercorn, it also has the option `--root-path`.
!!! note "Technical Details"
The ASGI specification defines a `root_path` for this use case.
And the `--root-path` command line option provides that `root_path`.
### Checking the current `root_path`
You can get the current `root_path` used by your application for each request, it is part of the `scope` dictionary (that's part of the ASGI spec).
Here we are including it in the message just for demonstration purposes.
```Python hl_lines="8"
{!../../../docs_src/behind_a_proxy/tutorial001.py!}
```
Then, if you start Uvicorn with:
<div class="termy">
```console
$ uvicorn main:app --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
The response would be something like:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
### Setting the `root_path` in the FastAPI app
Alternatively, if you don't have a way to provide a command line option like `--root-path` or equivalent, you can set the `root_path` parameter when creating your FastAPI app:
```Python hl_lines="3"
{!../../../docs_src/behind_a_proxy/tutorial002.py!}
```
Passing the `root_path` to `FastAPI` would be the equivalent of passing the `--root-path` command line option to Uvicorn or Hypercorn.
### About `root_path`
Have in mind that the server (Uvicorn) won't use that `root_path` for anything else than passing it to the app.
But if you go with your browser to <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> you will see the normal response:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
So, it won't expect to be accessed at `http://127.0.0.1:8000/api/v1/app`.
Uvicorn will expect the proxy to access Uvicorn at `http://127.0.0.1:8000/app`, and then it would be the proxy's responsibility to add the extra `/api/v1` prefix on top.
## About proxies with a stripped path prefix
Have in mind that a proxy with stripped path prefix is only one of the ways to configure it.
Probably in many cases the default will be that the proxy doesn't have a stripped path prefix.
In a case like that (without a stripped path prefix), the proxy would listen on something like `https://myawesomeapp.com`, and then if the browser goes to `https://myawesomeapp.com/api/v1/app` and your server (e.g. Uvicorn) listens on `http://127.0.0.1:8000` the proxy (without a stripped path prefix) would access Uvicorn at the same path: `http://127.0.0.1:8000/api/v1/app`.
## Testing locally with Traefik
You can easily run the experiment locally with a stripped path prefix using <a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a>.
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Download Traefik</a>, it's a single binary, you can extract the compressed file and run it directly from the terminal.
Then create a file `traefik.toml` with:
```TOML hl_lines="3"
[entryPoints]
[entryPoints.http]
address = ":9999"
[providers]
[providers.file]
filename = "routes.toml"
```
This tells Traefik to listen on port 9999 and to use another file `routes.toml`.
!!! tip
We are using port 9999 instead of the standard HTTP port 80 so that you don't have to run it with admin (`sudo`) privileges.
Now create that other file `routes.toml`:
```TOML hl_lines="5 12 20"
[http]
[http.middlewares]
[http.middlewares.api-stripprefix.stripPrefix]
prefixes = ["/api/v1"]
[http.routers]
[http.routers.app-http]
entryPoints = ["http"]
service = "app"
rule = "PathPrefix(`/api/v1`)"
middlewares = ["api-stripprefix"]
[http.services]
[http.services.app]
[http.services.app.loadBalancer]
[[http.services.app.loadBalancer.servers]]
url = "http://127.0.0.1:8000"
```
This file configures Traefik to use the path prefix `/api/v1`.
And then it will redirect its requests to your Uvicorn running on `http://127.0.0.1:8000`.
Now start Traefik:
<div class="termy">
```console
$ ./traefik --configFile=traefik.toml
INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
```
</div>
And now start your app with Uvicorn, using the `--root-path` option:
<div class="termy">
```console
$ uvicorn main:app --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Check the responses
Now, if you go to the URL with the port for Uvicorn: <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a>, you will see the normal response:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
!!! tip
Notice that even though you are accessing it at `http://127.0.0.1:8000/app` it shows the `root_path` of `/api/v1`, taken from the option `--root-path`.
And now open the URL with the port for Traefik, including the path prefix: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/vi/app</a>.
We get the same response:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
but this time at the URL with the prefix path provided by the proxy: `/api/v1`.
Of course, the idea here is that everyone would access the app through the proxy, so the version with the path prefix `/app/v1` is the "correct" one.
And the version without the path prefix (`http://127.0.0.1:8000/app`), provided by Uvicorn directly, would be exclusively for the _proxy_ (Traefik) to access it.
That demonstrates how the Proxy (Traefik) uses the path prefix and how the server (Uvicorn) uses the `root_path` from the option `--root-path`.
### Check the docs UI
But here's the fun part. ✨
The "official" way to access the app would be through the proxy with the path prefix that we defined. So, as we would expect, if you try the docs UI served by Uvicorn directly, without the path prefix in the URL, it won't work, because it expects to be accessed through the proxy.
You can check it at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>:
<img src="/img/tutorial/behind-a-proxy/image01.png">
But if we access the docs UI at the "official" URL using the proxy, at `/api/v1/docs`, it works correctly! 🎉
Right as we wanted it. ✔️
This is because FastAPI uses this `root_path` internally to tell the docs UI to use the URL for OpenAPI with the path prefix provided by `root_path`.
You can check it at <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>:
<img src="/img/tutorial/behind-a-proxy/image02.png">
## Mounting a sub-application
If you need to mount a sub-application (as described in [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}) while also using a proxy with `root_path`, you can do it normally, as you would expect.
FastAPI will internally use the `root_path` smartly, so it will just work. ✨

View File

@@ -203,6 +203,21 @@ File responses will include appropriate `Content-Length`, `Last-Modified` and `E
{!../../../docs_src/custom_response/tutorial009.py!}
```
## Default response class
When creating a **FastAPI** class instance or an `APIRouter` you can specify which response class to use by default.
The parameter that defines this is `default_response_class`.
In the example below, **FastAPI** will use `ORJSONResponse` by default, in all *path operations*, instead of `JSONResponse`.
```Python hl_lines="2 4"
{!../../../docs_src/custom_response/tutorial010.py!}
```
!!! tip
You can still override `response_class` in *path operations* as before.
## Additional documentation
You can also declare the media type and many other details in OpenAPI using `responses`: [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank}.

View File

@@ -4,6 +4,9 @@ You can define event handlers (functions) that need to be executed before the ap
These functions can be declared with `async def` or normal `def`.
!!! warning
Only event handlers for the main application will be executed, not for [Sub Applications - Mounts](./sub-applications.md){.internal-link target=_blank}.
## `startup` event
To add a function that should be run before the application starts, declare it with the event `"startup"`:
@@ -41,4 +44,4 @@ Here, the `shutdown` event handler function will write a text line `"Application
So, we declare the event handler function with standard `def` instead of `async def`.
!!! info
You can read more about these event handlers in <a href="https://www.starlette.io/events/" class="external-link" target="_blank">Starlette's Events' docs</a>.
You can read more about these event handlers in <a href="https://www.starlette.io/events/" class="external-link" target="_blank">Starlette's Events' docs</a>.

View File

@@ -52,15 +52,22 @@ First, write all your **FastAPI** application as normally:
Then, use the same utility function to generate the OpenAPI schema, inside a `custom_openapi()` function:
```Python hl_lines="2 15 16 17 18 19 20"
```Python hl_lines="2 15 16 17 18 19 20 21"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
!!! tip
The `openapi_prefix` will contain any prefix needed for the generated OpenAPI *path operations*.
FastAPI will automatically use the `root_path` to pass it in the `openapi_prefix`.
But the important thing is that your function should receive that parameter `openapi_prefix` and pass it along.
### Modify the OpenAPI schema
Now you can add the ReDoc extension, adding a custom `x-logo` to the `info` "object" in the OpenAPI schema:
```Python hl_lines="21 22 23"
```Python hl_lines="22 23 24"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
@@ -72,7 +79,7 @@ That way, your application won't have to generate the schema every time a user o
It will be generated only once, and then the same cached schema will be used for the next requests.
```Python hl_lines="13 14 24 25"
```Python hl_lines="13 14 25 26"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```
@@ -80,7 +87,7 @@ It will be generated only once, and then the same cached schema will be used for
Now you can replace the `.openapi()` method with your new function.
```Python hl_lines="28"
```Python hl_lines="29"
{!../../../docs_src/extending_openapi/tutorial001.py!}
```

View File

@@ -1,100 +0,0 @@
# Sub Applications - Behind a Proxy, Mounts
There are at least two situations where you could need to create your **FastAPI** application using some specific paths.
But then you need to set them up to be served with a path prefix.
It could happen if you have a:
* **Proxy** server.
* You are "**mounting**" a FastAPI application inside another FastAPI application (or inside another ASGI application, like Starlette).
## Proxy
Having a proxy in this case means that you could declare a path at `/app`, but then, you could need to add a layer on top (the Proxy) that would put your **FastAPI** application under a path like `/api/v1`.
In this case, the original path `/app` will actually be served at `/api/v1/app`.
Even though your application "thinks" it is serving at `/app`.
And the Proxy could be re-writing the path "on the fly" to keep your application convinced that it is serving at `/app`.
Up to here, everything would work as normally.
But then, when you open the integrated docs, they would expect to get the OpenAPI schema at `/openapi.json`, instead of `/api/v1/openapi.json`.
So, the frontend (that runs in the browser) would try to reach `/openapi.json` and wouldn't be able to get the OpenAPI schema.
So, it's needed that the frontend looks for the OpenAPI schema at `/api/v1/openapi.json`.
And it's also needed that the returned JSON OpenAPI schema has the defined path at `/api/v1/app` (behind the proxy) instead of `/app`.
---
For these cases, you can declare an `openapi_prefix` parameter in your `FastAPI` application.
See the section below, about "mounting", for an example.
## Mounting a **FastAPI** application
"Mounting" means adding a complete "independent" application in a specific path, that then takes care of handling all the sub-paths.
You could want to do this if you have several "independent" applications that you want to separate, having their own independent OpenAPI schema and user interfaces.
### Top-level application
First, create the main, top-level, **FastAPI** application, and its *path operations*:
```Python hl_lines="3 6 7 8"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
### Sub-application
Then, create your sub-application, and its *path operations*.
This sub-application is just another standard FastAPI application, but this is the one that will be "mounted".
When creating the sub-application, use the parameter `openapi_prefix`. In this case, with a prefix of `/subapi`:
```Python hl_lines="11 14 15 16"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
### Mount the sub-application
In your top-level application, `app`, mount the sub-application, `subapi`.
Here you need to make sure you use the same path that you used for the `openapi_prefix`, in this case, `/subapi`:
```Python hl_lines="11 19"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
## Check the automatic API docs
Now, run `uvicorn`, if your file is at `main.py`, it would be:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
And open the docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
You will see the automatic API docs for the main app, including only its own paths:
<img src="/img/tutorial/sub-applications/image01.png">
And then, open the docs for the sub-application, at <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
You will see the automatic API docs for the sub-application, including only its own sub-paths, with their correct prefix:
<img src="/img/tutorial/sub-applications/image02.png">
If you try interacting with any of the two user interfaces, they will work, because the browser will be able to talk to the correct path (or sub-path).

View File

@@ -0,0 +1,73 @@
# Sub Applications - Mounts
If you need to have two independent FastAPI applications, with their own independent OpenAPI and their own docs UIs, you can have a main app and "mount" one (or more) sub-application(s).
## Mounting a **FastAPI** application
"Mounting" means adding a completely "independent" application in a specific path, that then takes care of handling all everything under that path, with the _path operations_ declared in that sub-application.
### Top-level application
First, create the main, top-level, **FastAPI** application, and its *path operations*:
```Python hl_lines="3 6 7 8"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
### Sub-application
Then, create your sub-application, and its *path operations*.
This sub-application is just another standard FastAPI application, but this is the one that will be "mounted":
```Python hl_lines="11 14 15 16"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
### Mount the sub-application
In your top-level application, `app`, mount the sub-application, `subapi`.
In this case, it will be mounted at the path `/subapi`:
```Python hl_lines="11 19"
{!../../../docs_src/sub_applications/tutorial001.py!}
```
### Check the automatic API docs
Now, run `uvicorn` with the main app, if your file is `main.py`, it would be:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
And open the docs at <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
You will see the automatic API docs for the main app, including only its own _path operations_:
<img src="/img/tutorial/sub-applications/image01.png">
And then, open the docs for the sub-application, at <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a>.
You will see the automatic API docs for the sub-application, including only its own _path operations_, all under the correct sub-path prefix `/subapi`:
<img src="/img/tutorial/sub-applications/image02.png">
If you try interacting with any of the two user interfaces, they will work correctly, because the browser will be able to talk to each specific app or sub-app.
### Technical Details: `root_path`
When you mount a sub-application as described above, FastAPI will take care of communicating the mount path for the sub-application using a mechanism from the ASGI specification called a `root_path`.
That way, the sub-application will know to use that path prefix for the docs UI.
And the sub-application could also have its own mounted sub-applications and everything would work correctly, because FastAPI handles all these `root_path`s automatically.
You will learn more about the `root_path` and how to use it explicitly in the section about [Behind a Proxy](./behind-a-proxy.md){.internal-link target=_blank}.

View File

@@ -51,38 +51,7 @@ In your WebSocket route you can `await` for messages and send messages.
You can receive and send binary, text, and JSON data.
## Using `Depends` and others
In WebSocket endpoints you can import from `fastapi` and use:
* `Depends`
* `Security`
* `Cookie`
* `Header`
* `Path`
* `Query`
They work the same way as for other FastAPI endpoints/*path operations*:
```Python hl_lines="53 54 55 56 57 58 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76"
{!../../../docs_src/websockets/tutorial002.py!}
```
!!! info
In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
You can use a closing code from the <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">valid codes defined in the specification</a>.
In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the <a href="https://github.com/encode/starlette/pull/527" class="external-link" target="_blank">PR #527</a> in Starlette.
## More info
To learn more about the options, check Starlette's documentation for:
* <a href="https://www.starlette.io/websockets/" class="external-link" target="_blank">The `WebSocket` class</a>.
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" class="external-link" target="_blank">Class-based WebSocket handling</a>.
## Test it
## Try it
If your file is named `main.py`, run your application with:
@@ -115,3 +84,62 @@ You can send (and receive) many messages:
<img src="/img/tutorial/websockets/image04.png">
And all of them will use the same WebSocket connection.
## Using `Depends` and others
In WebSocket endpoints you can import from `fastapi` and use:
* `Depends`
* `Security`
* `Cookie`
* `Header`
* `Path`
* `Query`
They work the same way as for other FastAPI endpoints/*path operations*:
```Python hl_lines="56 57 58 59 60 61 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79"
{!../../../docs_src/websockets/tutorial002.py!}
```
!!! info
In a WebSocket it doesn't really make sense to raise an `HTTPException`. So it's better to close the WebSocket connection directly.
You can use a closing code from the <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">valid codes defined in the specification</a>.
In the future, there will be a `WebSocketException` that you will be able to `raise` from anywhere, and add exception handlers for it. It depends on the <a href="https://github.com/encode/starlette/pull/527" class="external-link" target="_blank">PR #527</a> in Starlette.
### Try the WebSockets with dependencies
If your file is named `main.py`, run your application with:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Open your browser at <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
There you can set:
* The "Item ID", used in the path.
* The "Token" used as a query parameter.
!!! tip
Notice that the query `token` will be handled by a dependency.
With that you can connect the WebSocket and then send and receive messages:
<img src="/img/tutorial/websockets/image05.png">
## More info
To learn more about the options, check Starlette's documentation for:
* <a href="https://www.starlette.io/websockets/" class="external-link" target="_blank">The `WebSocket` class</a>.
* <a href="https://www.starlette.io/endpoints/#websocketendpoint" class="external-link" target="_blank">Class-based WebSocket handling</a>.

View File

@@ -11,3 +11,8 @@ a.internal-link::after {
*/
content: "\00A0↪";
}
/* Give space to lower icons so Gitter chat doesn't get on top of them */
.md-footer-meta {
padding-bottom: 2em;
}

View File

@@ -25,8 +25,6 @@ Here's an incomplete list of some of them.
* <a href="https://medium.com/data-rebels/fastapi-authentication-revisited-enabling-api-key-authentication-122dc5975680" class="external-link" target="_blank">FastAPI authentication revisited: Enabling API key authentication</a> by <a href="https://medium.com/@nils_29588" class="external-link" target="_blank">Nils de Bruin</a>.
* <a href="https://blog.bartab.fr/fastapi-logging-on-the-fly/" class="external-link" target="_blank">FastAPI, a simple use case on logging</a> by <a href="https://blog.bartab.fr/" class="external-link" target="_blank">@euri10</a>.
* <a href="https://medium.com/@nico.axtmann95/deploying-a-scikit-learn-model-with-onnx-und-fastapi-1af398268915" class="external-link" target="_blank">Deploying a scikit-learn model with ONNX and FastAPI</a> by <a href="https://www.linkedin.com/in/nico-axtmann" class="external-link" target="_blank">Nico Axtmann</a>.
* <a href="https://geekflare.com/python-asynchronous-web-frameworks/" class="external-link" target="_blank">Top 5 Asynchronous Web Frameworks for Python</a> by <a href="https://geekflare.com/author/ankush/" class="external-link" target="_blank">Ankush Thakur</a> on <a href="https://geekflare.com" class="external-link" target="_blank">GeekFlare</a>.
@@ -61,6 +59,23 @@ Here's an incomplete list of some of them.
* <a href="https://iwpnd.pw/articles/2020-03/apache-kafka-fastapi-geostream" class="external-link" target="_blank">Apache Kafka producer and consumer with FastAPI and aiokafka</a> by <a href="https://iwpnd.pw" class="external-link" target="_blank">Benjamin Ramser</a>.
* <a href="https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/" class="external-link" target="_blank">Real-time Notifications with Python and Postgres</a> by <a href="https://wuilly.com/" class="external-link" target="_blank">Guillermo Cruz</a>.
* <a href="https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc" class="external-link" target="_blank">Microservice in Python using FastAPI</a> by <a href="https://twitter.com/PaurakhSharma" class="external-link" target="_blank">Paurakh Sharma Humagain</a>.
* <a href="https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o" class="external-link" target="_blank">Build simple API service with Python FastAPI — Part 1</a> by <a href="https://dev.to/cuongld2" class="external-link" target="_blank">cuongld2</a>.
* <a href="https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/" class="external-link" target="_blank">FastAPI + Zeit.co = 🚀
</a> by <a href="https://twitter.com/PaulWebSec" class="external-link" target="_blank">Paul Sec</a>.
* <a href="https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe" class="external-link" target="_blank">Build a web API from scratch with FastAPI - the workshop</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
* <a href="https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi" class="external-link" target="_blank">Build a Secure Twilio Webhook with Python and FastAPI</a> by <a href="https://www.twilio.com" class="external-link" target="_blank">Twilio</a>.
* <a href="https://www.stavros.io/posts/fastapi-with-django/" class="external-link" target="_blank">Using FastAPI with Django</a> by <a href="https://twitter.com/Stavros" class="external-link" target="_blank">Stavros Korokithakis</a>.
* <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" class="external-link" target="_blank">Introducing Dispatch</a> by <a href="https://netflixtechblog.com/" class="external-link" target="_blank">Netflix</a>.
### Japanese
* <a href="https://qiita.com/mtitg/items/47770e9a562dd150631d" class="external-link" target="_blank">FastAPIDB接続してCRUDするPython製APIサーバーを構築</a> by <a href="https://qiita.com/mtitg" class="external-link" target="_blank">@mtitg</a>.
@@ -87,12 +102,6 @@ Here's an incomplete list of some of them.
* <a href="https://qiita.com/bee2/items/75d9c0d7ba20e7a4a0e9" class="external-link" target="_blank">[FastAPI] Python製のASGI Web フレームワーク FastAPIに入門する</a> by <a href="https://qiita.com/bee2" class="external-link" target="_blank">@bee2</a>.
### Chinese
* <a href="https://cloud.tencent.com/developer/article/1431448" class="external-link" target="_blank">使用FastAPI框架快速构建高性能的api服务</a> by <a href="https://cloud.tencent.com/developer/user/5471722" class="external-link" target="_blank">逍遥散人</a>.
* <a href="https://wxq0309.github.io/" class="external-link" target="_blank">FastAPI框架中文文档</a> by <a href="https://wxq0309.github.io/" class="external-link" target="_blank">何大仙</a>.
### Vietnamese
* <a href="https://fullstackstation.com/fastapi-trien-khai-bang-docker/" class="external-link" target="_blank">FASTAPI: TRIỂN KHAI BẰNG DOCKER</a> by <a href="https://fullstackstation.com/author/figonking/" class="external-link" target="_blank">Nguyễn Nhân</a>.
@@ -110,11 +119,16 @@ Here's an incomplete list of some of them.
## Podcasts
* <a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" class="external-link" target="_blank">FastAPI on PythonBytes</a> by <a href="https://pythonbytes.fm/" class="external-link" target="_blank">Python Bytes FM</a>.
* <a href="https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/" class="external-link" target="_blank">Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)</a> by <a href="https://www.pythonpodcast.com/" class="external-link" target="_blank">Podcast.`__init__`</a>.
## Talks
* <a href="https://www.youtube.com/watch?v=3DLwPcrE5mA" class="external-link" target="_blank">PyCon UK 2019: FastAPI from the ground up</a> by <a href="https://twitter.com/chriswithers13" class="external-link" target="_blank">Chris Withers</a>.
* <a href="https://www.youtube.com/watch?v=z9K5pwb0rt8" class="external-link" target="_blank">PyConBY 2020: Serve ML models easily with FastAPI</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
* <a href="https://www.youtube.com/watch?v=PnpTY1f4k2U" class="external-link" target="_blank">[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI</a> by <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Sebastián Ramírez (tiangolo)</a>.
## Projects
Latest GitHub projects with the topic `fastapi`:

View File

@@ -12,28 +12,18 @@ And there are several ways to get help too.
## Star **FastAPI** in GitHub
You can "star" FastAPI in GitHub (clicking the star button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>.
You can "star" FastAPI in GitHub (clicking the star button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. ⭐️
By adding a star, other users will be able to find it more easily and see that it has been already useful for others.
## Watch the GitHub repository for releases
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>.
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
There you can select "Releases only".
Doing it, you will receive notifications (in your email) whenever there's a new release (a new version) of **FastAPI** with bug fixes and new features.
## Join the chat
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
</a>
Join the chat on Gitter: <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>.
There you can ask quick questions, help others, share ideas, etc.
## Connect with the author
You can connect with <a href="https://tiangolo.com" class="external-link" target="_blank">me (Sebastián Ramírez / `tiangolo`)</a>, the author.
@@ -45,39 +35,32 @@ You can:
* Follow me to see when I create a new Open Source project.
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">Follow me on **Twitter**</a>.
* Tell me how you use FastAPI (I love to hear that).
* Ask questions.
* Hear when I make announcements or release new tools.
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">Connect with me on **Linkedin**</a>.
* Talk to me.
* Endorse me or recommend me :)
* <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">Read what I write (or follow me) on **Medium**</a>.
* Read other ideas, articles and tools I have created.
* Follow me to see when I publish something new.
* Hear when I make announcements or release new tools (although I use Twitter more often 🤷‍♂).
* Read what I write (or follow me) on <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a> or <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>.
* Read other ideas, articles, and about tools I have created.
* Follow me to read when I publish something new.
## Tweet about **FastAPI**
<a href="https://twitter.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" class="external-link" target="_blank">Tweet about **FastAPI**</a> and let me and others know why you like it.
## Let me know how are you using **FastAPI**
<a href="https://twitter.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" class="external-link" target="_blank">Tweet about **FastAPI**</a> and let me and others know why you like it. 🎉
I love to hear about how **FastAPI** is being used, what have you liked in it, in which project/company are you using it, etc.
You can let me know:
* <a href="https://twitter.com/compose/tweet?text=Hey @tiangolo, I'm using FastAPI at..." class="external-link" target="_blank">On **Twitter**</a>.
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">On **Linkedin**</a>.
* <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">On **Medium**</a>.
## Vote for FastAPI
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Vote for **FastAPI** in Slant</a>.
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">Vote for **FastAPI** in AlternativeTo</a>.
* <a href="https://github.com/marmelab/awesome-rest/pull/93" class="external-link" target="_blank">Vote for **FastAPI** on awesome-rest</a>.
## Help others with issues in GitHub
You can see <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">existing issues</a> and try and help others.
You can see <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">existing issues</a> and try and help others, most of the times they are questions that you might already know the answer for. 🤓
## Watch the GitHub repository
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>.
You can "watch" FastAPI in GitHub (clicking the "watch" button at the top right): <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>. 👀
If you select "Watching" instead of "Releases only", you will receive notifications when someone creates a new issue.
@@ -87,9 +70,10 @@ Then you can try and help them solving those issues.
You can <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">create a new issue</a> in the GitHub repository, for example to:
* Report a bug/issue.
* Ask a question or ask about a problem.
* Suggest a new feature.
* Ask a question.
**Note**: if you create an issue then I'm going to ask you to also help others. 😉
## Create a Pull Request
@@ -100,12 +84,39 @@ You can <a href="https://github.com/tiangolo/fastapi" class="external-link" targ
* To fix an existing issue/bug.
* To add a new feature.
## Join the chat
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
</a>
Join the chat on Gitter: <a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>.
There you can have quick conversations with others, help others, share ideas, etc.
But have in mind that as it allows more "free conversation", it's easy to ask questions that are too general and more difficult to answer, so, you might not receive answers.
In GitHub issues the template will guide to to write the right question so that you can more easily get a good answer, or even solve the problem yourself even before asking. And in GitHub I can make sure I always answer everything, even if it takes some time. I can't personally do that with the Gitter chat. 😅
Conversations in Gitter are also not as easily searchable as in GitHub, so questions and answers might get lost in the conversation.
On the other side, there's more than 1000 people in the chat, so there's a high chance you'll find someone to talk to there, almost all the time. 😄
## Sponsor the author
You can also financially support the author (me) through <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>.
There you could buy me a coffee ☕️ to say thanks 😄.
## Sponsor the tools that power FastAPI
As you have seen in the documentation, FastAPI stands on the shoulders of giants, Starlette and Pydantic.
You can also sponsor:
* <a href="https://github.com/sponsors/samuelcolvin" class="external-link" target="_blank">Samuel Colvin (Pydantic)</a>
* <a href="https://github.com/sponsors/encode" class="external-link" target="_blank">Encode (Starlette, Uvicorn)</a>
---
Thanks!
Thanks! 🚀

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -45,38 +45,44 @@ The key features are:
## Opinions
"*[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products.*"
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"*Im over the moon excited about **FastAPI**. Its so fun!*"
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, the FastAPI of CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>

View File

@@ -69,3 +69,16 @@ You can read more about it in the docs for the repo.
## Full Stack FastAPI MongoDB
...might come later, depending on my time availability and other factors. 😅 🎉
## Machine Learning models with spaCy and FastAPI
GitHub: <a href="https://github.com/microsoft/cookiecutter-spacy-fastapi" class="external-link" target="_blank">https://github.com/microsoft/cookiecutter-spacy-fastapi</a>
### Machine Learning models with spaCy and FastAPI - Features
* **spaCy** NER model integration.
* **Azure Cognitive Search** request format built in.
* **Production ready** Python web server using Uvicorn and Gunicorn.
* **Azure DevOps** Kubernetes (AKS) CI/CD deployment built in.
* **Multilingual** Easily choose one of spaCy's built in languages during project setup.
* **Easily extensible** to other model frameworks (Pytorch, Tensorflow), not just spaCy.

View File

@@ -144,15 +144,15 @@ You can use, for example:
{!../../../docs_src/python_types/tutorial005.py!}
```
### Types with subtypes
### Generic types with type parameters
There are some data structures that can contain other values, like `dict`, `list`, `set` and `tuple`. And the internal values can have their own type too.
To declare those types and the subtypes, you can use the standard Python module `typing`.
To declare those types and the internal types, you can use the standard Python module `typing`.
It exists specifically to support these type hints.
#### Lists
#### `List`
For example, let's define a variable to be a `list` of `str`.
@@ -166,25 +166,30 @@ Declare the variable, with the same colon (`:`) syntax.
As the type, put the `List`.
As the list is a type that takes a "subtype", you put the subtype in square brackets:
As the list is a type that contains some internal types, you put them in square brackets:
```Python hl_lines="4"
{!../../../docs_src/python_types/tutorial006.py!}
```
!!! tip
Those internal types in the square brackets are called "type parameters".
In this case, `str` is the type parameter passed to `List`.
That means: "the variable `items` is a `list`, and each of the items in this list is a `str`".
By doing that, your editor can provide support even while processing items from the list.
Without types, that's almost impossible to achieve:
By doing that, your editor can provide support even while processing items from the list:
<img src="/img/python-types/image05.png">
Without types, that's almost impossible to achieve.
Notice that the variable `item` is one of the elements in the list `items`.
And still, the editor knows it is a `str`, and provides support for that.
#### Tuples and Sets
#### `Tuple` and `Set`
You would do the same to declare `tuple`s and `set`s:
@@ -197,13 +202,13 @@ This means:
* The variable `items_t` is a `tuple` with 3 items, an `int`, another `int`, and a `str`.
* The variable `items_s` is a `set`, and each of its items is of type `bytes`.
#### Dicts
#### `Dict`
To define a `dict`, you pass 2 subtypes, separated by commas.
To define a `dict`, you pass 2 type parameters, separated by commas.
The first subtype is for the keys of the `dict`.
The first type parameter is for the keys of the `dict`.
The second subtype is for the values of the `dict`:
The second type parameter is for the values of the `dict`:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
@@ -215,6 +220,29 @@ This means:
* The keys of this `dict` are of type `str` (let's say, the name of each item).
* The values of this `dict` are of type `float` (let's say, the price of each item).
#### `Optional`
You can also use `Optional` to declare that a variable has a type, like `str`, but that it is "optional", which means that it could also be `None`:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial009.py!}
```
Using `Optional[str]` instead of just `str` will let the editor help you detecting errors where you could be assuming that a value is always a `str`, when it could actually be `None` too.
#### Generic types
These types that take type parameters in square brackets, like:
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Optional`
* ...and others.
are called **Generic types** or **Generics**.
### Classes as types
You can also declare a class as the type of a variable.
@@ -222,13 +250,13 @@ You can also declare a class as the type of a variable.
Let's say you have a class `Person`, with a name:
```Python hl_lines="1 2 3"
{!../../../docs_src/python_types/tutorial009.py!}
{!../../../docs_src/python_types/tutorial010.py!}
```
Then you can declare a variable to be of type `Person`:
```Python hl_lines="6"
{!../../../docs_src/python_types/tutorial009.py!}
{!../../../docs_src/python_types/tutorial010.py!}
```
And then, again, you get all the editor support:
@@ -250,7 +278,7 @@ And you get all the editor support with that resulting object.
Taken from the official Pydantic docs:
```Python
{!../../../docs_src/python_types/tutorial010.py!}
{!../../../docs_src/python_types/tutorial011.py!}
```
!!! info

View File

@@ -2,6 +2,91 @@
## Latest changes
## 0.58.0
* Deep merge OpenAPI responses to preserve all the additional metadata. PR [#1577](https://github.com/tiangolo/fastapi/pull/1577).
* Mention in docs that only main app events are run (not sub-apps). PR [#1554](https://github.com/tiangolo/fastapi/pull/1554) by [@amacfie](https://github.com/amacfie).
* Fix body validation error response, do not include body variable when it is not embedded. PR [#1553](https://github.com/tiangolo/fastapi/pull/1553) by [@amacfie](https://github.com/amacfie).
* Fix testing OAuth2 security scopes when using dependency overrides. PR [#1549](https://github.com/tiangolo/fastapi/pull/1549) by [@amacfie](https://github.com/amacfie).
* Fix Model for JSON Schema keyword `not` as a JSON Schema instead of a list. PR [#1548](https://github.com/tiangolo/fastapi/pull/1548) by [@v-do](https://github.com/v-do).
* Add support for OpenAPI `servers`. PR [#1547](https://github.com/tiangolo/fastapi/pull/1547) by [@mikaello](https://github.com/mikaello).
## 0.57.0
* Remove broken link from "External Links". PR [#1565](https://github.com/tiangolo/fastapi/pull/1565) by [@victorphoenix3](https://github.com/victorphoenix3).
* Update/fix docs for [WebSockets with dependencies](https://fastapi.tiangolo.com/advanced/websockets/#using-depends-and-others). Original PR [#1540](https://github.com/tiangolo/fastapi/pull/1540) by [@ChihSeanHsu](https://github.com/ChihSeanHsu).
* Add support for Python's `http.HTTPStatus` in `status_code` parameters. PR [#1534](https://github.com/tiangolo/fastapi/pull/1534) by [@retnikt](https://github.com/retnikt).
* When using Pydantic models with `__root__`, use the internal value in `jsonable_encoder`. PR [#1524](https://github.com/tiangolo/fastapi/pull/1524) by [@patrickkwang](https://github.com/patrickkwang).
* Update docs for path parameters. PR [#1521](https://github.com/tiangolo/fastapi/pull/1521) by [@yankeexe](https://github.com/yankeexe).
* Update docs for first steps, links and rewording. PR [#1518](https://github.com/tiangolo/fastapi/pull/1518) by [@yankeexe](https://github.com/yankeexe).
* Enable `showCommonExtensions` in Swagger UI to show additional validations like `maxLength`, etc. PR [#1466](https://github.com/tiangolo/fastapi/pull/1466) by [@TiewKH](https://github.com/TiewKH).
* Make `OAuth2PasswordRequestFormStrict` importable directly from `fastapi.security`. PR [#1462](https://github.com/tiangolo/fastapi/pull/1462) by [@RichardHoekstra](https://github.com/RichardHoekstra).
* Add docs about [Default response class](https://fastapi.tiangolo.com/advanced/custom-response/#default-response-class). PR [#1455](https://github.com/tiangolo/fastapi/pull/1455) by [@TezRomacH](https://github.com/TezRomacH).
* Add note in docs about additional parameters `response_model_exclude_defaults` and `response_model_exclude_none` in [Response Model](https://fastapi.tiangolo.com/tutorial/response-model/#use-the-response_model_exclude_unset-parameter). PR [#1427](https://github.com/tiangolo/fastapi/pull/1427) by [@wshayes](https://github.com/wshayes).
* Add note about [PyCharm Pydantic plugin](https://github.com/koxudaxi/pydantic-pycharm-plugin) to docs. PR [#1420](https://github.com/tiangolo/fastapi/pull/1420) by [@koxudaxi](https://github.com/koxudaxi).
* Update and clarify testing function name. PR [#1395](https://github.com/tiangolo/fastapi/pull/1395) by [@chenl](https://github.com/chenl).
* Fix duplicated headers created by indirect dependencies that use the request directly. PR [#1386](https://github.com/tiangolo/fastapi/pull/1386) by [@obataku](https://github.com/obataku) from tests by [@scottsmith2gmail](https://github.com/scottsmith2gmail).
* Upgrade Starlette version to `0.13.4`. PR [#1361](https://github.com/tiangolo/fastapi/pull/1361) by [@rushton](https://github.com/rushton).
* Improve error handling and feedback for requests with invalid JSON. PR [#1354](https://github.com/tiangolo/fastapi/pull/1354) by [@aviramha](https://github.com/aviramha).
* Add support for declaring metadata for tags in OpenAPI. New docs at [Tutorial - Metadata and Docs URLs - Metadata for tags](https://fastapi.tiangolo.com/tutorial/metadata/#metadata-for-tags). PR [#1348](https://github.com/tiangolo/fastapi/pull/1348) by [@thomas-maschler](https://github.com/thomas-maschler).
* Add basic setup for Russian translations. PR [#1566](https://github.com/tiangolo/fastapi/pull/1566).
* Remove obsolete Chinese articles after adding official community translations. PR [#1510](https://github.com/tiangolo/fastapi/pull/1510) by [@waynerv](https://github.com/waynerv).
* Add `__repr__` for *path operation function* parameter helpers (like `Query`, `Depends`, etc) to simplify debugging. PR [#1560](https://github.com/tiangolo/fastapi/pull/1560) by [@rkbeatss](https://github.com/rkbeatss) and [@victorphoenix3](https://github.com/victorphoenix3).
## 0.56.1
* Add link to advanced docs from tutorial. PR [#1512](https://github.com/tiangolo/fastapi/pull/1512) by [@kx-chen](https://github.com/kx-chen).
* Remove internal unnecessary f-strings. PR [#1526](https://github.com/tiangolo/fastapi/pull/1526) by [@kotamatsuoka](https://github.com/kotamatsuoka).
* Add translation to Chinese for [Query Parameters and String Validations - 查询参数和字符串校验](https://fastapi.tiangolo.com/zh/tutorial/query-params-str-validations/). PR [#1500](https://github.com/tiangolo/fastapi/pull/1500) by [@waynerv](https://github.com/waynerv).
* Add translation to Chinese for [Request Body - 请求体](https://fastapi.tiangolo.com/zh/tutorial/body/). PR [#1492](https://github.com/tiangolo/fastapi/pull/1492) by [@waynerv](https://github.com/waynerv).
* Add translation to Chinese for [Help FastAPI - Get Help - 帮助 FastAPI - 获取帮助](https://fastapi.tiangolo.com/zh/help-fastapi/). PR [#1465](https://github.com/tiangolo/fastapi/pull/1465) by [@waynerv](https://github.com/waynerv).
* Add translation to Chinese for [Query Parameters - 查询参数](https://fastapi.tiangolo.com/zh/tutorial/query-params/). PR [#1454](https://github.com/tiangolo/fastapi/pull/1454) by [@waynerv](https://github.com/waynerv).
* Add translation to Chinese for [Contributing - 开发 - 贡献](https://fastapi.tiangolo.com/zh/contributing/). PR [#1460](https://github.com/tiangolo/fastapi/pull/1460) by [@waynerv](https://github.com/waynerv).
* Add translation to Chinese for [Path Parameters - 路径参数](https://fastapi.tiangolo.com/zh/tutorial/path-params/). PR [#1453](https://github.com/tiangolo/fastapi/pull/1453) by [@waynerv](https://github.com/waynerv).
* Add official Microsoft project generator for [serving spaCy with FastAPI and Azure Cognitive Skills](https://github.com/microsoft/cookiecutter-spacy-fastapi) to [Project Generators](https://fastapi.tiangolo.com/project-generation/). PR [#1390](https://github.com/tiangolo/fastapi/pull/1390) by [@kabirkhan](https://github.com/kabirkhan).
* Update docs in [Python Types Intro](https://fastapi.tiangolo.com/python-types/) to include info about `Optional`. Original PR [#1377](https://github.com/tiangolo/fastapi/pull/1377) by [@yaegassy](https://github.com/yaegassy).
* Fix support for callable class dependencies with `yield`. PR [#1365](https://github.com/tiangolo/fastapi/pull/1365) by [@mrosales](https://github.com/mrosales).
* Fix/remove incorrect error logging when a client sends invalid payloads. PR [#1351](https://github.com/tiangolo/fastapi/pull/1351) by [@dbanty](https://github.com/dbanty).
* Add translation to Chinese for [First Steps - 第一步](https://fastapi.tiangolo.com/zh/tutorial/first-steps/). PR [#1323](https://github.com/tiangolo/fastapi/pull/1323) by [@waynerv](https://github.com/waynerv).
* Fix generating OpenAPI for apps using callbacks with routers including Pydantic models. PR [#1322](https://github.com/tiangolo/fastapi/pull/1322) by [@nsidnev](https://github.com/nsidnev).
* Optimize internal regex performance in `get_path_param_names()`. PR [#1243](https://github.com/tiangolo/fastapi/pull/1243) by [@heckad](https://github.com/heckad).
* Remove `*,` from functions in docs where it's not needed. PR [#1239](https://github.com/tiangolo/fastapi/pull/1239) by [@pankaj-giri](https://github.com/pankaj-giri).
* Start translations for Italian. PR [#1557](https://github.com/tiangolo/fastapi/pull/1557) by [@csr](https://github.com/csr).
## 0.56.0
* Add support for ASGI `root_path`:
* Use `root_path` internally for mounted applications, so that OpenAPI and the docs UI works automatically without extra configurations and parameters.
* Add new `root_path` parameter for `FastAPI` applications to provide it in cases where it can be set with the command line (e.g. for Uvicorn and Hypercorn, with the parameter `--root-path`).
* Deprecate `openapi_prefix` parameter in favor of the new `root_path` parameter.
* Add new/updated docs for [Sub Applications - Mounts](https://fastapi.tiangolo.com/advanced/sub-applications/), without `openapi_prefix` (as it is now handled automatically).
* Add new/updated docs for [Behind a Proxy](https://fastapi.tiangolo.com/advanced/behind-a-proxy/), including how to setup a local testing proxy with Traefik and using `root_path`.
* Update docs for [Extending OpenAPI](https://fastapi.tiangolo.com/advanced/extending-openapi/) with the new `openapi_prefix` parameter passed (internally generated from `root_path`).
* Original PR [#1199](https://github.com/tiangolo/fastapi/pull/1199) by [@iksteen](https://github.com/iksteen).
* Update new issue templates and docs: [Help FastAPI - Get Help](https://fastapi.tiangolo.com/help-fastapi/). PR [#1531](https://github.com/tiangolo/fastapi/pull/1531).
* Update GitHub action issue-manager. PR [#1520](https://github.com/tiangolo/fastapi/pull/1520).
* Add new links:
* **English articles**:
* [Real-time Notifications with Python and Postgres](https://wuilly.com/2019/10/real-time-notifications-with-python-and-postgres/) by [Guillermo Cruz](https://wuilly.com/).
* [Microservice in Python using FastAPI](https://dev.to/paurakhsharma/microservice-in-python-using-fastapi-24cc) by [Paurakh Sharma Humagain](https://twitter.com/PaurakhSharma).
* [Build simple API service with Python FastAPI — Part 1](https://dev.to/cuongld2/build-simple-api-service-with-python-fastapi-part-1-581o) by [cuongld2](https://dev.to/cuongld2).
* [FastAPI + Zeit.co = 🚀](https://paulsec.github.io/posts/fastapi_plus_zeit_serverless_fu/) by [Paul Sec](https://twitter.com/PaulWebSec).
* [Build a web API from scratch with FastAPI - the workshop](https://dev.to/tiangolo/build-a-web-api-from-scratch-with-fastapi-the-workshop-2ehe) by [Sebastián Ramírez (tiangolo)](https://twitter.com/tiangolo).
* [Build a Secure Twilio Webhook with Python and FastAPI](https://www.twilio.com/blog/build-secure-twilio-webhook-python-fastapi) by [Twilio](https://www.twilio.com).
* [Using FastAPI with Django](https://www.stavros.io/posts/fastapi-with-django/) by [Stavros Korokithakis](https://twitter.com/Stavros).
* [Introducing Dispatch](https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072) by [Netflix](https://netflixtechblog.com/).
* **Podcasts**:
* [Build The Next Generation Of Python Web Applications With FastAPI - Episode 259 - interview to Sebastían Ramírez (tiangolo)](https://www.pythonpodcast.com/fastapi-web-application-framework-episode-259/) by [Podcast.`__init__`](https://www.pythonpodcast.com/).
* **Talks**:
* [PyConBY 2020: Serve ML models easily with FastAPI](https://www.youtube.com/watch?v=z9K5pwb0rt8) by [Sebastián Ramírez (tiangolo)](https://twitter.com/tiangolo).
* [[VIRTUAL] Py.Amsterdam's flying Software Circus: Intro to FastAPI](https://www.youtube.com/watch?v=PnpTY1f4k2U) by [Sebastián Ramírez (tiangolo)](https://twitter.com/tiangolo).
* PR [#1467](https://github.com/tiangolo/fastapi/pull/1467).
* Add translation to Chinese for [Python Types Intro - Python 类型提示简介](https://fastapi.tiangolo.com/zh/python-types/). PR [#1197](https://github.com/tiangolo/fastapi/pull/1197) by [@waynerv](https://github.com/waynerv).
## 0.55.1
* Fix handling of enums with their own schema in path parameters. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1463](https://github.com/tiangolo/fastapi/pull/1463).
## 0.55.0
* Allow enums to allow them to have their own schemas in OpenAPI. To support [samuelcolvin/pydantic#1432](https://github.com/samuelcolvin/pydantic/pull/1432) in FastAPI. PR [#1461](https://github.com/tiangolo/fastapi/pull/1461).

View File

@@ -108,6 +108,17 @@ But you would get the same editor support with <a href="https://www.jetbrains.co
<img src="/img/tutorial/body/image05.png">
!!! tip
If you use <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> as your editor, you can use the <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>.
It improves editor support for Pydantic models, with:
* auto-completion
* type checks
* refactoring
* searching
* inspections
## Use the model
Inside of the function, you can access all the attributes of the model object directly:

View File

@@ -71,13 +71,13 @@ You will see the alternative automatic documentation (provided by <a href="https
#### "Schema"
A "schema" is a definition or description of something. Not the code that implements it, but just the abstract description.
A "schema" is a definition or description of something. Not the code that implements it, but just an abstract description.
#### API "schema"
In this case, OpenAPI is a specification that dictates how to define a schema of your API.
In this case, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> is a specification that dictates how to define a schema of your API.
This OpenAPI schema would include your API paths, the possible parameters they take, etc.
This schema definition includes your API paths, the possible parameters they take, etc.
#### Data "schema"
@@ -91,7 +91,7 @@ OpenAPI defines an API schema for your API. And that schema includes definitions
#### Check the `openapi.json`
If you are curious about how the raw OpenAPI schema looks like, it is just an automatically generated JSON with the descriptions of all your API.
If you are curious about how the raw OpenAPI schema looks like, FastAPI automatically generates a JSON (schema) with the descriptions of all your API.
You can see it directly at: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
@@ -120,7 +120,7 @@ It will show a JSON starting with something like:
#### What is OpenAPI for
This OpenAPI schema is what powers the 2 interactive documentation systems included.
The OpenAPI schema is what powers the two interactive documentation systems included.
And there are dozens of alternatives, all based on OpenAPI. You could easily add any of those alternatives to your application built with **FastAPI**.
@@ -139,7 +139,7 @@ You could also use it to generate code automatically, for clients that communica
!!! note "Technical Details"
`FastAPI` is a class that inherits directly from `Starlette`.
You can use all the Starlette functionality with `FastAPI` too.
You can use all the <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> functionality with `FastAPI` too.
### Step 2: create a `FastAPI` "instance"
@@ -202,7 +202,7 @@ https://example.com/items/foo
!!! info
A "path" is also commonly called an "endpoint" or a "route".
Building an API, the "path" is the main way to separate "concerns" and "resources".
While building an API, the "path" is the main way to separate "concerns" and "resources".
#### Operation
@@ -281,7 +281,7 @@ And the more exotic ones:
The information here is presented as a guideline, not a requirement.
For example, when using GraphQL you normally perform all the actions using only `post`.
For example, when using GraphQL you normally perform all the actions using only `POST` operations.
### Step 4: define the **path operation function**
@@ -297,7 +297,7 @@ This is our "**path operation function**":
This is a Python function.
It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using `GET`.
It will be called by **FastAPI** whenever it receives a request to the URL "`/`" using a `GET` operation.
In this case, it is an `async` function.

View File

@@ -215,7 +215,6 @@ You will receive a response telling you that the data is invalid containing the
{
"loc": [
"body",
"item",
"size"
],
"msg": "value is not a valid integer",

View File

@@ -21,6 +21,58 @@ With this configuration, the automatic API docs would look like:
<img src="/img/tutorial/metadata/image01.png">
## Metadata for tags
You can also add additional metadata for the different tags used to group your path operations with the parameter `openapi_tags`.
It takes a list containing one dictionary for each tag.
Each dictionary can contain:
* `name` (**required**): a `str` with the same tag name you use in the `tags` parameter in your *path operations* and `APIRouter`s.
* `description`: a `str` with a short description for the tag. It can have Markdown and will be shown in the docs UI.
* `externalDocs`: a `dict` describing external documentation with:
* `description`: a `str` with a short description for the external docs.
* `url` (**required**): a `str` with the URL for the external documentation.
### Create metadata for tags
Let's try that in an example with tags for `users` and `items`.
Create metadata for your tags and pass it to the `openapi_tags` parameter:
```Python hl_lines="3 4 5 6 7 8 9 10 11 12 13 14 15 16 18"
{!../../../docs_src/metadata/tutorial004.py!}
```
Notice that you can use Markdown inside of the descriptions, for example "login" will be shown in bold (**login**) and "fancy" will be shown in italics (_fancy_).
!!! tip
You don't have to add metadata for all the tags that you use.
### Use your tags
Use the `tags` parameter with your *path operations* (and `APIRouter`s) to assign them to different tags:
```Python hl_lines="21 26"
{!../../../docs_src/metadata/tutorial004.py!}
```
!!! info
Read more about tags in [Path Operation Configuration](../path-operation-configuration/#tags){.internal-link target=_blank}.
### Check the docs
Now, if you check the docs, they will show all the additional metadata:
<img src="/img/tutorial/metadata/image02.png">
### Order of tags
The order of each tag metadata dictionary also defines the order shown in the docs UI.
For example, even though `users` would go after `items` in alphabetical order, it is shown before them, because we added their metadata as the first dictionary in the list.
## OpenAPI URL
By default, the OpenAPI schema is served at `/openapi.json`.

View File

@@ -85,7 +85,7 @@ And when you open your browser at <a href="http://127.0.0.1:8000/docs" class="ex
And because the generated schema is from the <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> standard, there are many compatible tools.
Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc):
Because of this, **FastAPI** itself provides an alternative API documentation (using ReDoc), which you can access at <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>:
<img src="/img/tutorial/path-params/image02.png">
@@ -125,7 +125,7 @@ Import `Enum` and create a sub-class that inherits from `str` and from `Enum`.
By inheriting from `str` the API docs will be able to know that the values must be of type `string` and will be able to render correctly.
And create class attributes with fixed values, those fixed values will be the available valid values:
Then create class attributes with fixed values, which will be the available valid values:
```Python hl_lines="1 6 7 8 9"
{!../../../docs_src/path_params/tutorial005.py!}
@@ -147,7 +147,7 @@ Then create a *path parameter* with a type annotation using the enum class you c
### Check the docs
Because the available values for the *path parameter* are specified, 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">
@@ -167,7 +167,7 @@ You can compare it with the *enumeration member* in your created enum `ModelName
You can get the actual value (a `str` in this case) using `model_name.value`, or in general, `your_enum_member.value`:
```Python hl_lines="19"
```Python hl_lines="20"
{!../../../docs_src/path_params/tutorial005.py!}
```
@@ -178,12 +178,21 @@ You can get the actual value (a `str` in this case) using `model_name.value`, or
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 before returning them to the client:
They will be converted to their corresponding values (strings in this case) before returning them to the client:
```Python hl_lines="18 20 21"
```Python hl_lines="18 21 23"
{!../../../docs_src/path_params/tutorial005.py!}
```
In your client you will get a JSON response like:
```JSON
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
```
## Path parameters containing paths
Let's say you have a *path operation* with a path `/files/{file_path}`.

View File

@@ -124,6 +124,14 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t
!!! info
FastAPI uses Pydantic model's `.dict()` with <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict" class="external-link" target="_blank">its `exclude_unset` parameter</a> to achieve this.
!!! info
You can also use:
* `response_model_exclude_defaults=True`
* `response_model_exclude_none=True`
as described in <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict" class="external-link" target="_blank">the Pydantic docs</a> for `exclude_defaults` and `exclude_none`.
#### Data with values for fields with defaults
But if your data has values for the model's fields with default values, like the item with ID `bar`:

View File

@@ -17,6 +17,9 @@ The same way you can specify a response model, you can also declare the HTTP sta
The `status_code` parameter receives a number with the HTTP status code.
!!! info
`status_code` can alternatively also receive an `IntEnum`, such as Python's <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
It will:
* Return that status code in the response.
@@ -83,4 +86,4 @@ They are just a convenience, they hold the same number, but that way you can use
## Changing the default
Later, in the **Advanced User Guide**, you will see how to return a different status code than the default you are declaring here.
Later, in the [Advanced User Guide](../advanced/response-change-status-code.md){.internal-link target=_blank}, you will see how to return a different status code than the default you are declaring here.

View File

@@ -33,7 +33,7 @@ The same way you can pass extra info to `Field`, you can do the same with `Path`
For example, you can pass an `example` for a body request to `Body`:
```Python hl_lines="20 21 22 23 24 25"
```Python hl_lines="19 20 21 22 23 24"
{!../../../docs_src/schema_extra_example/tutorial003.py!}
```

View File

@@ -22,7 +22,9 @@ nav:
- Languages:
- en: /
- es: /es/
- it: /it/
- pt: /pt/
- ru: /ru/
- zh: /zh/
- features.md
- python-types.md
@@ -92,7 +94,8 @@ nav:
- advanced/sql-databases-peewee.md
- advanced/async-sql-databases.md
- advanced/nosql-databases.md
- advanced/sub-applications-proxy.md
- advanced/sub-applications.md
- advanced/behind-a-proxy.md
- advanced/templates.md
- advanced/graphql.md
- advanced/websockets.md

View File

@@ -44,38 +44,44 @@ Sus características principales son:
## Opiniones
"*[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products.*"
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"*Im over the moon excited about **FastAPI**. Its so fun!*"
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"*Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that.*"
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"*If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]*"
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"*We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]*"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"*We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]*"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, el FastAPI de las CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>

View File

@@ -22,7 +22,9 @@ nav:
- Languages:
- en: /
- es: /es/
- it: /it/
- pt: /pt/
- ru: /ru/
- zh: /zh/
- features.md
- python-types.md

447
docs/it/docs/index.md Normal file
View File

@@ -0,0 +1,447 @@
{!../../../docs/missing-translation.md!}
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
</p>
<p align="center">
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
</a>
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
</a>
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
</a>
</p>
---
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
The key features are:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
* **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimation based on tests on an internal development team, building production applications.</small>
## Opinions
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, the FastAPI of CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
## Requirements
Python 3.6+
FastAPI stands on the shoulders of giants:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
## Installation
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install uvicorn
---> 100%
```
</div>
## Example
### Create it
* Create a file `main.py` with:
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Or use <code>async def</code>...</summary>
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
```
**Note**:
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
</details>
### Run it
Run the server with:
<div class="termy">
```console
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
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()`.
* `--reload`: make the server restart after code changes. Only do this for development.
</details>
### Check it
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
You will see the JSON response as:
```JSON
{"item_id": 5, "q": "somequery"}
```
You already created an API that:
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
### Interactive API docs
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" 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" class="external-link" 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" class="external-link" 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" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Example upgrade
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="2 7 8 9 10 23 24 25"
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
### Interactive API docs upgrade
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* The interactive API documentation will be automatically updated, including the new body:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternative API docs upgrade
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* The alternative documentation will also reflect the new query parameter and body:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**.
For example, for an `int`:
```Python
item_id: int
```
or for a more complex `Item` model:
```Python
item: Item
```
...and with that single declaration you get:
* Editor support, including:
* Completion.
* Type checks.
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
* Cookies.
* Headers.
* Forms.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> 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.
* Database models.
* ...and many more.
* Automatic interactive API documentation, including 2 alternative user interfaces:
* Swagger UI.
* ReDoc.
---
Coming back to the previous code example, **FastAPI** will:
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
* If it is not, the client will see a useful, clear error.
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
* As the `q` parameter is declared with `= None`, it is optional.
* Without the `None` it would be required (as is the body in the case with `PUT`).
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
* Check that it has a required attribute `name` that should be a `str`.
* Check that it has a required attribute `price` that has to be a `float`.
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
* All this would also work for deeply nested JSON objects.
* Convert from and to JSON automatically.
* Document everything with OpenAPI, that can be used by:
* Interactive documentation systems.
* Automatic client code generation systems, for many languages.
* Provide 2 interactive documentation web interfaces directly.
---
We just scratched the surface, but you already get the idea of how it all works.
Try changing the line with:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...from:
```Python
... "item_name": item.name ...
```
...to:
```Python
... "item_price": item.price ...
```
...and see how your editor will auto-complete the attributes and know their types:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
* Many extra features (thanks to Starlette) as:
* **WebSockets**
* **GraphQL**
* extremely easy tests based on `requests` and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
## Performance
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
Used by Pydantic:
* <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.
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 <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 Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
Used by FastAPI / Starlette:
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
You can install all of these with `pip install fastapi[all]`.
## License
This project is licensed under the terms of the MIT license.

67
docs/it/mkdocs.yml Normal file
View File

@@ -0,0 +1,67 @@
site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/it/
theme:
name: material
palette:
primary: teal
accent: amber
icon:
repo: fontawesome/brands/github-alt
logo: https://fastapi.tiangolo.com/img/icon-white.svg
favicon: https://fastapi.tiangolo.com/img/favicon.png
language: it
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- it: /it/
- pt: /pt/
- ru: /ru/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- markdown_include.include:
base_path: docs
- admonition
- codehilite
- extra
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_div_format ''
- pymdownx.tabbed
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
link: https://www.linkedin.com/in/tiangolo
- icon: fontawesome/brands/dev
link: https://dev.to/tiangolo
- icon: fontawesome/brands/medium
link: https://medium.com/@tiangolo
- icon: fontawesome/solid/globe
link: https://tiangolo.com
extra_css:
- https://fastapi.tiangolo.com/css/termynal.css
- https://fastapi.tiangolo.com/css/custom.css
extra_javascript:
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
- https://fastapi.tiangolo.com/js/termynal.js
- https://fastapi.tiangolo.com/js/custom.js
- https://fastapi.tiangolo.com/js/chat.js
- https://sidecar.gitter.im/dist/sidecar.v1.js

View File

@@ -22,7 +22,9 @@ nav:
- Languages:
- en: /
- es: /es/
- it: /it/
- pt: /pt/
- ru: /ru/
- zh: /zh/
- features.md
- Tutorial - Guia de Usuário:

447
docs/ru/docs/index.md Normal file
View File

@@ -0,0 +1,447 @@
{!../../../docs/missing-translation.md!}
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, high performance, easy to learn, fast to code, ready for production</em>
</p>
<p align="center">
<a href="https://travis-ci.com/tiangolo/fastapi" target="_blank">
<img src="https://travis-ci.com/tiangolo/fastapi.svg?branch=master" alt="Build Status">
</a>
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://badge.fury.io/py/fastapi.svg" alt="Package version">
</a>
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
</a>
</p>
---
**Documentation**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Source Code**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
---
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
The key features are:
* **Fast**: Very high performance, on par with **NodeJS** and **Go** (thanks to Starlette and Pydantic). [One of the fastest Python frameworks available](#performance).
* **Fast to code**: Increase the speed to develop features by about 200% to 300%. *
* **Fewer bugs**: Reduce about 40% of human (developer) induced errors. *
* **Intuitive**: Great editor support. <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> everywhere. Less time debugging.
* **Easy**: Designed to be easy to use and learn. Less time reading docs.
* **Short**: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
* **Robust**: Get production-ready code. With automatic interactive documentation.
* **Standards-based**: Based on (and fully compatible with) the open standards for APIs: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (previously known as Swagger) and <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* estimation based on tests on an internal development team, building production applications.</small>
## Opinions
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Im over the moon excited about **FastAPI**. Its so fun!_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, the FastAPI of CLIs
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
If you are building a <abbr title="Command Line Interface">CLI</abbr> app to be used in the terminal instead of a web API, check out <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** is FastAPI's little sibling. And it's intended to be the **FastAPI of CLIs**. ⌨️ 🚀
## Requirements
Python 3.6+
FastAPI stands on the shoulders of giants:
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> for the web parts.
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> for the data parts.
## Installation
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
You will also need an ASGI server, for production such as <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install uvicorn
---> 100%
```
</div>
## Example
### Create it
* Create a file `main.py` with:
```Python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Or use <code>async def</code>...</summary>
If your code uses `async` / `await`, use `async def`:
```Python hl_lines="7 12"
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
```
**Note**:
If you don't know, check the _"In a hurry?"_ section about <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` and `await` in the docs</a>.
</details>
### Run it
Run the server with:
<div class="termy">
```console
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
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()`.
* `--reload`: make the server restart after code changes. Only do this for development.
</details>
### Check it
Open your browser at <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
You will see the JSON response as:
```JSON
{"item_id": 5, "q": "somequery"}
```
You already created an API that:
* Receives HTTP requests in the _paths_ `/` and `/items/{item_id}`.
* Both _paths_ take `GET` <em>operations</em> (also known as HTTP _methods_).
* The _path_ `/items/{item_id}` has a _path parameter_ `item_id` that should be an `int`.
* The _path_ `/items/{item_id}` has an optional `str` _query parameter_ `q`.
### Interactive API docs
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" 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" class="external-link" 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" class="external-link" 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" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Example upgrade
Now modify the file `main.py` to receive a body from a `PUT` request.
Declare the body using standard Python types, thanks to Pydantic.
```Python hl_lines="2 7 8 9 10 23 24 25"
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
### Interactive API docs upgrade
Now go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* The interactive API documentation will be automatically updated, including the new body:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Alternative API docs upgrade
And now, go to <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* The alternative documentation will also reflect the new query parameter and body:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Recap
In summary, you declare **once** the types of parameters, body, etc. as function parameters.
You do that with standard modern Python types.
You don't have to learn a new syntax, the methods or classes of a specific library, etc.
Just standard **Python 3.6+**.
For example, for an `int`:
```Python
item_id: int
```
or for a more complex `Item` model:
```Python
item: Item
```
...and with that single declaration you get:
* Editor support, including:
* Completion.
* Type checks.
* Validation of data:
* Automatic and clear errors when the data is invalid.
* Validation even for deeply nested JSON objects.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> of input data: coming from the network to Python data and types. Reading from:
* JSON.
* Path parameters.
* Query parameters.
* Cookies.
* Headers.
* Forms.
* Files.
* <abbr title="also known as: serialization, parsing, marshalling">Conversion</abbr> 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.
* Database models.
* ...and many more.
* Automatic interactive API documentation, including 2 alternative user interfaces:
* Swagger UI.
* ReDoc.
---
Coming back to the previous code example, **FastAPI** will:
* Validate that there is an `item_id` in the path for `GET` and `PUT` requests.
* Validate that the `item_id` is of type `int` for `GET` and `PUT` requests.
* If it is not, the client will see a useful, clear error.
* Check if there is an optional query parameter named `q` (as in `http://127.0.0.1:8000/items/foo?q=somequery`) for `GET` requests.
* As the `q` parameter is declared with `= None`, it is optional.
* Without the `None` it would be required (as is the body in the case with `PUT`).
* For `PUT` requests to `/items/{item_id}`, Read the body as JSON:
* Check that it has a required attribute `name` that should be a `str`.
* Check that it has a required attribute `price` that has to be a `float`.
* Check that it has an optional attribute `is_offer`, that should be a `bool`, if present.
* All this would also work for deeply nested JSON objects.
* Convert from and to JSON automatically.
* Document everything with OpenAPI, that can be used by:
* Interactive documentation systems.
* Automatic client code generation systems, for many languages.
* Provide 2 interactive documentation web interfaces directly.
---
We just scratched the surface, but you already get the idea of how it all works.
Try changing the line with:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...from:
```Python
... "item_name": item.name ...
```
...to:
```Python
... "item_price": item.price ...
```
...and see how your editor will auto-complete the attributes and know their types:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
For a more complete example including more features, see the <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Spoiler alert**: the tutorial - user guide includes:
* Declaration of **parameters** from other different places as: **headers**, **cookies**, **form fields** and **files**.
* How to set **validation constraints** as `maximum_length` or `regex`.
* A very powerful and easy to use **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** system.
* Security and authentication, including support for **OAuth2** with **JWT tokens** and **HTTP Basic** auth.
* More advanced (but equally easy) techniques for declaring **deeply nested JSON models** (thanks to Pydantic).
* Many extra features (thanks to Starlette) as:
* **WebSockets**
* **GraphQL**
* extremely easy tests based on `requests` and `pytest`
* **CORS**
* **Cookie Sessions**
* ...and more.
## Performance
Independent TechEmpower benchmarks show **FastAPI** applications running under Uvicorn as <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">one of the fastest Python frameworks available</a>, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Optional Dependencies
Used by Pydantic:
* <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.
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 <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 Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - Required for `GraphQLApp` support.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
Used by FastAPI / Starlette:
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
You can install all of these with `pip install fastapi[all]`.
## License
This project is licensed under the terms of the MIT license.

67
docs/ru/mkdocs.yml Normal file
View File

@@ -0,0 +1,67 @@
site_name: FastAPI
site_description: FastAPI framework, high performance, easy to learn, fast to code, ready for production
site_url: https://fastapi.tiangolo.com/ru/
theme:
name: material
palette:
primary: teal
accent: amber
icon:
repo: fontawesome/brands/github-alt
logo: https://fastapi.tiangolo.com/img/icon-white.svg
favicon: https://fastapi.tiangolo.com/img/favicon.png
language: ru
repo_name: tiangolo/fastapi
repo_url: https://github.com/tiangolo/fastapi
edit_uri: ''
google_analytics:
- UA-133183413-1
- auto
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- it: /it/
- pt: /pt/
- ru: /ru/
- zh: /zh/
markdown_extensions:
- toc:
permalink: true
- markdown.extensions.codehilite:
guess_lang: false
- markdown_include.include:
base_path: docs
- admonition
- codehilite
- extra
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_div_format ''
- pymdownx.tabbed
extra:
social:
- icon: fontawesome/brands/github-alt
link: https://github.com/tiangolo/typer
- icon: fontawesome/brands/twitter
link: https://twitter.com/tiangolo
- icon: fontawesome/brands/linkedin
link: https://www.linkedin.com/in/tiangolo
- icon: fontawesome/brands/dev
link: https://dev.to/tiangolo
- icon: fontawesome/brands/medium
link: https://medium.com/@tiangolo
- icon: fontawesome/solid/globe
link: https://tiangolo.com
extra_css:
- https://fastapi.tiangolo.com/css/termynal.css
- https://fastapi.tiangolo.com/css/custom.css
extra_javascript:
- https://unpkg.com/mermaid@8.4.6/dist/mermaid.min.js
- https://fastapi.tiangolo.com/js/termynal.js
- https://fastapi.tiangolo.com/js/custom.js
- https://fastapi.tiangolo.com/js/chat.js
- https://sidecar.gitter.im/dist/sidecar.v1.js

View File

@@ -0,0 +1,510 @@
# 开发 - 贡献
首先,你最好先了解 [帮助 FastAPI 及获取帮助](help-fastapi.md){.internal-link target=_blank}的基本方式。
## 开发
如果你已经克隆了源码仓库,并且需要深入研究代码,下面是设置开发环境的指南。
### 通过 `venv` 管理虚拟环境
你可以使用 Python 的 `venv` 模块在一个目录中创建虚拟环境:
<div class="termy">
```console
$ python -m venv env
```
</div>
这将使用 Python 程序创建一个 `./env/` 目录,然后你将能够为这个隔离的环境安装软件包。
### 激活虚拟环境
使用以下方法激活新环境:
=== "Linux, macOS"
<div class="termy">
```console
$ source ./env/bin/activate
```
</div>
=== "Windows PowerShell"
<div class="termy">
```console
$ .\env\Scripts\Activate.ps1
```
</div>
=== "Windows Bash"
Or if you use Bash for Windows (e.g. <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>):
<div class="termy">
```console
$ source ./env/Scripts/activate
```
</div>
要检查操作是否成功,运行:
=== "Linux, macOS, Windows Bash"
<div class="termy">
```console
$ which pip
some/directory/fastapi/env/bin/pip
```
</div>
=== "Windows PowerShell"
<div class="termy">
```console
$ Get-Command pip
some/directory/fastapi/env/bin/pip
```
</div>
如果显示 `pip` 程序文件位于 `env/bin/pip` 则说明激活成功。 🎉
!!! tip
每一次你在该环境下使用 `pip` 安装了新软件包时,请再次激活该环境。
这样可以确保你在使用由该软件包安装的终端程序(如 `flit`)时使用的是当前虚拟环境中的程序,而不是其他的可能是全局安装的程序。
### Flit
**FastAPI** 使用 <a href="https://flit.readthedocs.io/en/latest/index.html" class="external-link" target="_blank">Flit</a> 来构建、打包和发布项目。
如上所述激活环境后,安装 `flit`
<div class="termy">
```console
$ pip install flit
---> 100%
```
</div>
现在重新激活环境,以确保你正在使用的是刚刚安装的 `flit`(而不是全局环境的)。
然后使用 `flit` 来安装开发依赖:
=== "Linux, macOS"
<div class="termy">
```console
$ flit install --deps develop --symlink
---> 100%
```
</div>
=== "Windows"
If you are on Windows, use `--pth-file` instead of `--symlink`:
<div class="termy">
```console
$ flit install --deps develop --pth-file
---> 100%
```
</div>
这将在虚拟环境中安装所有依赖和本地版本的 FastAPI。
#### 使用本地 FastAPI
如果你创建一个导入并使用 FastAPI 的 Python 文件,然后使用虚拟环境中的 Python 运行它,它将使用你本地的 FastAPI 源码。
并且如果你更改该本地 FastAPI 的源码,由于它是通过 `--symlink` (或 Windows 上的 `--pth-file`)安装的,当你再次运行那个 Python 文件,它将使用你刚刚编辑过的最新版本的 FastAPI。
这样,你不必再去重新"安装"你的本地版本即可测试所有更改。
### 格式化
你可以运行下面的脚本来格式化和清理所有代码:
<div class="termy">
```console
$ bash scripts/format.sh
```
</div>
它还会自动对所有导入代码进行整理。
为了使整理正确进行,你需要在当前环境中安装本地的 FastAPI即在运行上述段落中的命令时添加 `--symlink`(或 Windows 上的 `--pth-file`)。
### 格式化导入
还有另一个脚本可以格式化所有导入,并确保你没有未使用的导入代码:
<div class="termy">
```console
$ bash scripts/format-imports.sh
```
</div>
由于它依次运行了多个命令,并修改和还原了许多文件,所以运行时间会更长一些,因此经常地使用 `scripts/format.sh` 然后仅在提交前执行 `scripts/format-imports.sh` 会更好一些。
## 文档
首先,请确保按上述步骤设置好环境,这将安装所有需要的依赖。
文档使用 <a href="https://www.mkdocs.org/" class="external-link" target="_blank">MkDocs</a> 生成。
并且在 `./scripts/docs.py` 中还有适用的额外工具/脚本来处理翻译。
!!! tip
你不需要去了解 `./scripts/docs.py` 中的代码,只需在命令行中使用它即可。
所有文档均在 `./docs/en/` 目录中以 Markdown 文件格式保存。
许多的教程章节里包含有代码块。
在大多数情况下,这些代码块是可以直接运行的真实完整的应用程序。
实际上,这些代码块不是写在 Markdown 文件内的,它们是位于 `./docs_src/` 目录中的 Python 文件。
生成站点时,这些 Python 文件会被包含/注入到文档中。
### 用于测试的文档
大多数的测试实际上都是针对文档中的示例源文件运行的。
这有助于确保:
* 文档始终是最新的。
* 文档示例可以直接运行。
* 绝大多数特性既在文档中得以阐述,又通过测试覆盖进行保障。
在本地开发期间,有一个脚本可以实时重载地构建站点并用来检查所做的任何更改:
<div class="termy">
```console
$ python ./scripts/docs.py live
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
<span style="color: green;">[INFO]</span> Start watching changes
<span style="color: green;">[INFO]</span> Start detecting changes
```
</div>
它将在 `http://127.0.0.1:8008` 提供对文档的访问。
这样,你可以编辑文档/源文件并实时查看更改。
#### Typer CLI (可选)
本指引向你展示了如何直接用 `python` 程序运行 `./scripts/docs.py` 中的脚本。
但你也可以使用 <a href="https://typer.tiangolo.com/typer-cli/" class="external-link" target="_blank">Typer CLI</a>,而且在安装了补全功能后,你将可以在终端中对命令进行自动补全。
如果你打算安装 Typer CLI ,可以使用以下命令安装自动补全功能:
<div class="termy">
```console
$ typer --install-completion
zsh completion installed in /home/user/.bashrc.
Completion will take effect once you restart the terminal.
```
</div>
### 应用和文档同时运行
如果你使用以下方式运行示例程序:
<div class="termy">
```console
$ uvicorn tutorial001:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
由于 Uvicorn 默认使用 `8000` 端口 ,因此运行在 `8008` 端口上的文档不会与之冲突。
### 翻译
非常感谢你能够参与文档的翻译!这项工作需要社区的帮助才能完成。 🌎 🚀
以下是参与帮助翻译的步骤。
#### 建议和指南
* 在当前 <a href="https://github.com/tiangolo/fastapi/pulls" class="external-link" target="_blank">已有的 pull requests</a> 中查找你使用的语言,添加要求修改或同意合并的评审意见。
!!! tip
你可以为已有的 pull requests <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request" class="external-link" target="_blank">添加包含修改建议的评论</a>。
详情可查看关于 <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-reviews" class="external-link" target="_blank">添加 pull request 评审意见</a> 以同意合并或要求修改的文档。
* 在 <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">issues</a> 中查找是否有对你所用语言所进行的协作翻译。
* 每翻译一个页面新增一个 pull request。这将使其他人更容易对其进行评审。
对于我(译注:作者使用西班牙语和英语)不懂的语言,我将在等待其他人评审翻译之后将其合并。
* 你还可以查看是否有你所用语言的翻译,并对其进行评审,这将帮助我了解翻译是否正确以及能否将其合并。
* 使用相同的 Python 示例并且仅翻译文档中的文本。无需进行任何其他更改示例也能正常工作。
* 使用相同的图片、文件名以及链接地址。无需进行任何其他调整来让它们兼容。
* 你可以从 <a href="https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes" class="external-link" target="_blank">ISO 639-1 代码列表</a> 表中查找你想要翻译语言的两位字母代码。
#### 已有的语言
假设你想将某个页面翻译成已经翻译了一些页面的语言,例如西班牙语。
对于西班牙语来说,它的两位字母代码是 `es`。所以西班牙语翻译的目录位于 `docs/es/`。
!!! tip
主要("官方")语言是英语,位于 `docs/en/`目录。
现在为西班牙语文档运行实时服务器:
<div class="termy">
```console
// Use the command "live" and pass the language code as a CLI argument
$ python ./scripts/docs.py live es
<span style="color: green;">[INFO]</span> Serving on http://127.0.0.1:8008
<span style="color: green;">[INFO]</span> Start watching changes
<span style="color: green;">[INFO]</span> Start detecting changes
```
</div>
现在你可以访问 <a href="http://127.0.0.1:8008" class="external-link" target="_blank">http://127.0.0.1:8008</a> 实时查看你所做的更改。
如果你查看 FastAPI 的线上文档网站,会看到每种语言都有所有页面。但是某些页面并未被翻译并且会有一处关于缺少翻译的提示。
但是当你像上面这样在本地运行文档时,你只会看到已经翻译的页面。
现在假设你要为 [Features](features.md){.internal-link target=_blank} 章节添加翻译。
* 复制下面的文件:
```
docs/en/docs/features.md
```
* 粘贴到你想要翻译语言目录的相同位置,比如:
```
docs/es/docs/features.md
```
!!! tip
注意路径和文件名的唯一变化是语言代码,从 `en` 更改为 `es`。
* 现在打开位于英语文档目录下的 MkDocs 配置文件:
```
docs/en/docs/mkdocs.yml
```
* 在配置文件中找到 `docs/features.md` 所在的位置。结果像这样:
```YAML hl_lines="8"
site_name: FastAPI
# More stuff
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- features.md
```
* 打开你正在编辑的语言目录中的 MkDocs 配置文件,例如:
```
docs/es/docs/mkdocs.yml
```
* 将其添加到与英语文档完全相同的位置,例如:
```YAML hl_lines="8"
site_name: FastAPI
# More stuff
nav:
- FastAPI: index.md
- Languages:
- en: /
- es: /es/
- features.md
```
如果配置文件中还有其他条目,请确保你所翻译的新条目和它们之间的顺序与英文版本完全相同。
打开浏览器,现在你将看到文档展示了你所加入的新章节。 🎉
现在,你可以将它全部翻译完并在保存文件后进行预览。
#### 新语言
假设你想要为尚未有任何页面被翻译的语言添加翻译。
假设你想要添加克里奥尔语翻译,而且文档中还没有该语言的翻译。
点击上面提到的链接,可以查到"克里奥尔语"的代码为 `ht`。
下一步是运行脚本以生成新的翻译目录:
<div class="termy">
```console
// Use the command new-lang, pass the language code as a CLI argument
$ python ./scripts/docs.py new-lang ht
Successfully initialized: docs/ht
Updating ht
Updating en
```
</div>
现在,你可以在编辑器中查看新创建的目录 `docs/ht/`。
!!! tip
在添加实际的翻译之前,仅以此创建首个 pull request 来设定新语言的配置。
这样当你在翻译第一个页面时,其他人可以帮助翻译其他页面。🚀
首先翻译文档主页 `docs/ht/index.md`。
然后,你可以根据上面的"已有语言"的指引继续进行翻译。
##### 不支持的新语言
如果在运行实时服务器脚本时收到关于不支持该语言的错误,类似于:
```
raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: partials/language/xx.html
```
这意味着文档的主题不支持该语言(在这种例子中,编造的语言代码是 `xx`)。
但是别担心,你可以将主题语言设置为英语,然后翻译文档的内容。
如果你需要这么做,编辑新语言目录下的 `mkdocs.yml`,它将有类似下面的内容:
```YAML hl_lines="5"
site_name: FastAPI
# More stuff
theme:
# More stuff
language: xx
```
将其中的 language 项从 `xx`(你的语言代码)更改为 `en`。
然后,你就可以再次启动实时服务器了。
#### 预览结果
当你通过 `live` 命令使用 `./scripts/docs.py` 中的脚本时,该脚本仅展示当前语言已有的文件和翻译。
但是当你完成翻译后,你可以像在线上展示一样测试所有内容。
为此,首先构建所有文档:
<div class="termy">
```console
// Use the command "build-all", this will take a bit
$ python ./scripts/docs.py build-all
Updating es
Updating en
Building docs for: en
Building docs for: es
Successfully built docs for: es
Copying en index.md to README.md
```
</div>
这将在 `./docs_build/` 目录中为每一种语言生成全部的文档。还包括添加所有缺少翻译的文件,并带有一条"此文件还没有翻译"的提醒。但是你不需要对该目录执行任何操作。
然后,它针对每种语言构建独立的 MkDocs 站点,将它们组合在一起,并在 `./site/` 目录中生成最终的输出。
然后你可以使用命令 `serve` 来运行生成的站点:
<div class="termy">
```console
// Use the command "serve" after running "build-all"
$ python ./scripts/docs.py serve
Warning: this is a very simple server. For development, use mkdocs serve instead.
This is here only to preview a site with translations already built.
Make sure you run the build-all command first.
Serving at: http://127.0.0.1:8008
```
</div>
## 测试
你可以在本地运行下面的脚本来测试所有代码并生成 HTML 格式的覆盖率报告:
<div class="termy">
```console
$ bash scripts/test-cov-html.sh
```
</div>
该命令生成了一个 `./htmlcov/` 目录,如果你在浏览器中打开 `./htmlcov/index.html` 文件,你可以交互式地浏览被测试所覆盖的代码区块,并注意是否缺少了任何区块。
### 在编辑器中测试
如果你想要在编辑器中运行集成测试,请将 `./docs_src` 加入到你的 `PYTHONPATH` 变量中。
例如,在 VS Code 中你可以创建一个包含以下内容的 `.env` 文件:
```env
PYTHONPATH=./docs_src
```

View File

@@ -0,0 +1,111 @@
# 帮助 FastAPI - 获取帮助
你喜欢 **FastAPI** 吗?
您愿意去帮助 FastAPI帮助其他用户以及作者吗
或者你想要获得有关 **FastAPI** 的帮助?
下面是一些非常简单的方式去提供帮助(有些只需单击一两次链接)。
以及几种获取帮助的途径。
## 在 GitHub 上 Star **FastAPI**
你可以在 GitHub 上 "star" FastAPI点击右上角的 star 按钮):<a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>。
通过添加 star其他用户将会更容易发现 FastAPI并了解已经有许多人认为它有用。
## Watch GitHub 仓库的版本发布
你可以在 GitHub 上 "watch" FastAPI点击右上角的 watch 按钮):<a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>。
这时你可以选择 "Releases only" 选项。
之后,只要有 **FastAPI** 的新版本(包含缺陷修复和新功能)发布,你都会(通过电子邮件)收到通知。
## 加入聊天室
<a href="https://gitter.im/tiangolo/fastapi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge" target="_blank">
<img src="https://badges.gitter.im/tiangolo/fastapi.svg" alt="Join the chat at https://gitter.im/tiangolo/fastapi">
</a>
加入 Gitter 上的聊天室:<a href="https://gitter.im/tiangolo/fastapi" class="external-link" target="_blank">https://gitter.im/tiangolo/fastapi</a>。
在这里你可以快速提问、帮助他人、分享想法等。
## 与作者联系
你可以联系 <a href="https://tiangolo.com" class="external-link" target="_blank">我 (Sebastián Ramírez / `tiangolo`)</a> - FastAPI 的作者。
你可以:
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">在 **GitHub** 上关注我</a>。
* 查看我创建的其他的可能对你有帮助的开源项目。
* 关注我以了解我创建的新开源项目。
* <a href="https://twitter.com/tiangolo" class="external-link" target="_blank">在 **Twitter** 上关注我</a>。
* 告诉我你是如何使用 FastAPI 的(我很乐意听到)。
* 提出问题。
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">在 **Linkedin** 上联系我</a>。
* 与我交流。
* 认可我的技能或推荐我 :)
* <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">在 **Medium** 上阅读我写的文章(或关注我)</a>。
* 阅读我创建的其他想法,文章和工具。
* 关注我以了解我发布的新内容。
## 发布和 **FastAPI** 有关的推特
<a href="https://twitter.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" class="external-link" target="_blank"> 发布和 **FastAPI** 有关的推特</a> 让我和其他人知道你为什么喜欢它。
## 告诉我你正在如何使用 **FastAPI**
我很乐意听到有关 **FastAPI** 被如何使用、你喜欢它的哪一点、被投入使用的项目/公司等等信息。
你可以通过以下平台让我知道:
* <a href="https://twitter.com/compose/tweet?text=Hey @tiangolo, I'm using FastAPI at..." class="external-link" target="_blank">**Twitter**</a>。
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">**Linkedin**</a>。
* <a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a>。
## 为 FastAPI 投票
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">在 Slant 上为 **FastAPI** 投票</a>。
## 帮助他人解决 GitHub 的 issues
你可以查看 <a href="https://github.com/tiangolo/fastapi/issues" class="external-link" target="_blank">已有的 issues</a> 并尝试帮助其他人。
## Watch GitHub 仓库
你可以在 GitHub 上 "watch" FastAPI点击右上角的 "watch" 按钮):<a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">https://github.com/tiangolo/fastapi</a>。
如果你选择的是 "Watching" 而不是 "Releases only" 选项,你会在其他人创建了新的 issue 时收到通知。
然后你可以尝试帮助他们解决这些 issue。
## 创建 issue
你可以在 GitHub 仓库中 <a href="https://github.com/tiangolo/fastapi/issues/new/choose" class="external-link" target="_blank">创建一个新 issue</a> 用来:
* 报告 bug 或问题。
* 提议新的特性。
* 提问。
## 创建 Pull Request
你可以 <a href="https://github.com/tiangolo/fastapi" class="external-link" target="_blank">创建一个 Pull Request</a> 用来:
* 纠正你在文档中发现的错别字。
* 添加新的文档内容。
* 修复已有的 bug 或问题。
* 添加新的特性。
## 赞助作者
你还可以通过 <a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a> 在经济上支持作者(我)。
这样你可以给我买杯咖啡☕️以示谢意😄。
---
感谢!

View File

@@ -0,0 +1,286 @@
# Python 类型提示简介
**Python 3.6+ 版本**加入了对"类型提示"的支持。
这些**"类型提示"**是一种新的语法(在 Python 3.6 版本加入)用来声明一个变量的<abbr title="例如str、int、float、bool">类型</abbr>。
通过声明变量的类型,编辑器和一些工具能给你提供更好的支持。
这只是一个关于 Python 类型提示的**快速入门 / 复习**。它仅涵盖与 **FastAPI** 一起使用所需的最少部分...实际上只有很少一点。
整个 **FastAPI** 都基于这些类型提示构建,它们带来了许多优点和好处。
但即使你不会用到 **FastAPI**,了解一下类型提示也会让你从中受益。
!!! note
如果你已经精通 Python并且了解关于类型提示的一切知识直接跳到下一章节吧。
## 动机
让我们从一个简单的例子开始:
```Python
{!../../../docs_src/python_types/tutorial001.py!}
```
运行这段程序将输出:
```
John Doe
```
这个函数做了下面这些事情:
* 接收 `first_name``last_name` 参数。
* 通过 `title()` 将每个参数的第一个字母转换为大写形式。
* 中间用一个空格来<abbr title="将它们按顺序放置组合成一个整体。">拼接</abbr>它们。
```Python hl_lines="2"
{!../../../docs_src/python_types/tutorial001.py!}
```
### 修改示例
这是一个非常简单的程序。
现在假设你将从头开始编写这段程序。
在某一时刻,你开始定义函数,并且准备好了参数...。
现在你需要调用一个"将第一个字母转换为大写形式的方法"。
等等,那个方法是什么来着?`upper`?还是 `uppercase``first_uppercase``capitalize`
然后你尝试向程序员老手的朋友——编辑器自动补全寻求帮助。
输入函数的第一个参数 `first_name`,输入点号(`.`)然后敲下 `Ctrl+Space` 来触发代码补全。
但遗憾的是并没有起什么作用:
<img src="https://fastapi.tiangolo.com/img/python-types/image01.png">
### 添加类型
让我们来修改上面例子的一行代码。
我们将把下面这段代码中的函数参数从:
```Python
first_name, last_name
```
改成:
```Python
first_name: str, last_name: str
```
就是这样。
这些就是"类型提示"
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial002.py!}
```
这和声明默认值是不同的,例如:
```Python
first_name="john", last_name="doe"
```
这两者不一样。
我们用的是冒号(`:`),不是等号(`=`)。
而且添加类型提示一般不会改变原来的运行结果。
现在假设我们又一次正在创建这个函数,这次添加了类型提示。
在同样的地方,通过 `Ctrl+Space` 触发自动补全,你会发现:
<img src="https://fastapi.tiangolo.com/img/python-types/image02.png">
这样,你可以滚动查看选项,直到你找到看起来眼熟的那个:
<img src="https://fastapi.tiangolo.com/img/python-types/image03.png">
## 更多动机
下面是一个已经有类型提示的函数:
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial003.py!}
```
因为编辑器已经知道了这些变量的类型,所以不仅能对代码进行补全,还能检查其中的错误:
<img src="https://fastapi.tiangolo.com/img/python-types/image04.png">
现在你知道了必须先修复这个问题,通过 `str(age)` 把 `age` 转换成字符串:
```Python hl_lines="2"
{!../../../docs_src/python_types/tutorial004.py!}
```
## 声明类型
你刚刚看到的就是声明类型提示的主要场景。用于函数的参数。
这也是你将在 **FastAPI** 中使用它们的主要场景。
### 简单类型
不只是 `str`,你能够声明所有的标准 Python 类型。
比如以下类型:
* `int`
* `float`
* `bool`
* `bytes`
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial005.py!}
```
### 嵌套类型
有些容器数据结构可以包含其他的值,比如 `dict`、`list`、`set` 和 `tuple`。它们内部的值也会拥有自己的类型。
你可以使用 Python 的 `typing` 标准库来声明这些类型以及子类型。
它专门用来支持这些类型提示。
#### 列表
例如,让我们来定义一个由 `str` 组成的 `list` 变量。
从 `typing` 模块导入 `List`(注意是大写的 `L`
```Python hl_lines="1"
{!../../../docs_src/python_types/tutorial006.py!}
```
同样以冒号(`:`)来声明这个变量。
输入 `List` 作为类型。
由于列表是带有"子类型"的类型,所以我们把子类型放在方括号中:
```Python hl_lines="4"
{!../../../docs_src/python_types/tutorial006.py!}
```
这表示:"变量 `items` 是一个 `list`,并且这个列表里的每一个元素都是 `str`"。
这样,即使在处理列表中的元素时,你的编辑器也可以提供支持。
没有类型,几乎是不可能实现下面这样:
<img src="https://fastapi.tiangolo.com/img/python-types/image05.png">
注意,变量 `item` 是列表 `items` 中的元素之一。
而且,编辑器仍然知道它是一个 `str`,并为此提供了支持。
#### 元组和集合
声明 `tuple` 和 `set` 的方法也是一样的:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial007.py!}
```
这表示:
* 变量 `items_t` 是一个 `tuple`,其中的每个元素都是 `int` 类型。
* 变量 `items_s` 是一个 `set`,其中的每个元素都是 `bytes` 类型。
#### 字典
定义 `dict` 时,需要传入两个子类型,用逗号进行分隔。
第一个子类型声明 `dict` 的所有键。
第二个子类型声明 `dict` 的所有值:
```Python hl_lines="1 4"
{!../../../docs_src/python_types/tutorial008.py!}
```
这表示:
* 变量 `prices` 是一个 `dict`
* 这个 `dict` 的所有键为 `str` 类型(可以看作是字典内每个元素的名称)。
* 这个 `dict` 的所有值为 `float` 类型(可以看作是字典内每个元素的价格)。
### 类作为类型
你也可以将类声明为变量的类型。
假设你有一个名为 `Person` 的类,拥有 name 属性:
```Python hl_lines="1 2 3"
{!../../../docs_src/python_types/tutorial009.py!}
```
接下来,你可以将一个变量声明为 `Person` 类型:
```Python hl_lines="6"
{!../../../docs_src/python_types/tutorial009.py!}
```
然后,你将再次获得所有的编辑器支持:
<img src="https://fastapi.tiangolo.com/img/python-types/image06.png">
## Pydantic 模型
<a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> 是一个用来用来执行数据校验的 Python 库。
你可以将数据的"结构"声明为具有属性的类。
每个属性都拥有类型。
接着你用一些值来创建这个类的实例,这些值会被校验,并被转换为适当的类型(在需要的情况下),返回一个包含所有数据的对象。
然后,你将获得这个对象的所有编辑器支持。
下面的例子来自 Pydantic 官方文档:
```Python
{!../../../docs_src/python_types/tutorial010.py!}
```
!!! info
想进一步了解 <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic请阅读其文档</a>.
整个 **FastAPI** 建立在 Pydantic 的基础之上。
实际上你将在 [教程 - 用户指南](tutorial/index.md){.internal-link target=_blank} 看到很多这种情况。
## **FastAPI** 中的类型提示
**FastAPI** 利用这些类型提示来做下面几件事。
使用 **FastAPI** 时用类型提示声明参数可以获得:
* **编辑器支持**。
* **类型检查**。
...并且 **FastAPI** 还会用这些类型声明来:
* **定义参数要求**:声明对请求路径参数、查询参数、请求头、请求体、依赖等的要求。
* **转换数据**:将来自请求的数据转换为需要的类型。
* **校验数据** 对于每一个请求:
* 当数据校验失败时自动生成**错误信息**返回给客户端。
* 使用 OpenAPI **记录** API
* 然后用于自动生成交互式文档的用户界面。
听上去有点抽象。不过不用担心。你将在 [教程 - 用户指南](tutorial/index.md){.internal-link target=_blank} 中看到所有的实战。
最重要的是,通过使用标准的 Python 类型,只需要在一个地方声明(而不是添加更多的类、装饰器等),**FastAPI** 会为你完成很多的工作。
!!! info
如果你已经阅读了所有教程,回过头来想了解有关类型的更多信息,<a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">来自 `mypy` 的"速查表"</a>是不错的资源。

View File

@@ -0,0 +1,147 @@
# 请求体
当你需要将数据从客户端(例如浏览器)发送给 API 时,你将其作为「请求体」发送。
**请求**体是客户端发送给 API 的数据。**响应**体是 API 发送给客户端的数据。
你的 API 几乎总是要发送**响应**体。但是客户端并不总是需要发送**请求**体。
我们使用 <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> 模型来声明**请求**体,并能够获得它们所具有的所有能力和优点。
!!! info
你不能使用 `GET` 操作HTTP 方法)发送请求体。
要发送数据,你必须使用下列方法之一:`POST`(较常见)、`PUT``DELETE``PATCH`
## 导入 Pydantic 的 `BaseModel`
首先,你需要从 `pydantic` 中导入 `BaseModel`
```Python hl_lines="2"
{!../../../docs_src/body/tutorial001.py!}
```
## 创建数据模型
然后,将你的数据模型声明为继承自 `BaseModel` 的类。
使用标准的 Python 类型来声明所有属性:
```Python hl_lines="5 6 7 8 9"
{!../../../docs_src/body/tutorial001.py!}
```
和声明查询参数时一样,当一个模型属性具有默认值时,它不是必需的。否则它是一个必需属性。将默认值设为 `None` 可使其成为可选属性。
例如,上面的模型声明了一个这样的 JSON「`object`」(或 Python `dict`
```JSON
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
```
...由于 `description` 和 `tax` 是可选的(它们的默认值为 `None`),下面的 JSON「`object`」也将是有效的:
```JSON
{
"name": "Foo",
"price": 45.2
}
```
## 声明为参数
使用与声明路径和查询参数的相同方式声明请求体,即可将其添加到「路径操作」中:
```Python hl_lines="16"
{!../../../docs_src/body/tutorial001.py!}
```
...并且将它的类型声明为你创建的 `Item` 模型。
## 结果
仅仅使用了 Python 类型声明,**FastAPI** 将会:
* 将请求体作为 JSON 读取。
* 转换为相应的类型(在需要时)。
* 校验数据。
* 如果数据无效,将返回一条清晰易读的错误信息,指出不正确数据的确切位置和内容。
* 将接收的数据赋值到参数 `item` 中。
* 由于你已经在函数中将它声明为 `Item` 类型,你还将获得对于所有属性及其类型的一切编辑器支持(代码补全等)。
* 为你的模型生成 <a href="http://json-schema.org" class="external-link" target="_blank">JSON 模式</a> 定义,你还可以在其他任何对你的项目有意义的地方使用它们。
* 这些模式将成为生成的 OpenAPI 模式的一部分,并且被自动化文档 <abbr title="用户界面">UI</abbr> 所使用。
## 自动化文档
你所定义模型的 JSON 模式将成为生成的 OpenAPI 模式的一部分,并且在交互式 API 文档中展示:
<img src="https://fastapi.tiangolo.com/img/tutorial/body/image01.png">
而且还将在每一个需要它们的*路径操作*的 API 文档中使用:
<img src="https://fastapi.tiangolo.com/img/tutorial/body/image02.png">
## 编辑器支持
在你的编辑器中,你会在函数内部的任意地方得到类型提示和代码补全(如果你接收的是一个 `dict` 而不是 Pydantic 模型,则不会发生这种情况):
<img src="https://fastapi.tiangolo.com/img/tutorial/body/image03.png">
你还会获得对不正确的类型操作的错误检查:
<img src="https://fastapi.tiangolo.com/img/tutorial/body/image04.png">
这并非偶然,整个框架都是围绕该设计而构建。
并且在进行任何实现之前,已经在设计阶段经过了全面测试,以确保它可以在所有的编辑器中生效。
Pydantic 本身甚至也进行了一些更改以支持此功能。
上面的截图取自 <a href="https://code.visualstudio.com" class="external-link" target="_blank">Visual Studio Code</a>。
但是在 <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> 和绝大多数其他 Python 编辑器中你也会获得同样的编辑器支持:
<img src="https://fastapi.tiangolo.com/img/tutorial/body/image05.png">
## 使用模型
在函数内部,你可以直接访问模型对象的所有属性:
```Python hl_lines="19"
{!../../../docs_src/body/tutorial002.py!}
```
## 请求体 + 路径参数
你可以同时声明路径参数和请求体。
**FastAPI** 将识别出与路径参数匹配的函数参数应**从路径中获取**,而声明为 Pydantic 模型的函数参数应**从请求体中获取**。
```Python hl_lines="15 16"
{!../../../docs_src/body/tutorial003.py!}
```
## 请求体 + 路径参数 + 查询参数
你还可以同时声明**请求体**、**路径参数**和**查询参数**。
**FastAPI** 会识别它们中的每一个,并从正确的位置获取数据。
```Python hl_lines="16"
{!../../../docs_src/body/tutorial004.py!}
```
函数参数将依次按如下规则进行识别:
* 如果在**路径**中也声明了该参数,它将被用作路径参数。
* 如果参数属于**单一类型**(比如 `int`、`float`、`str`、`bool` 等)它将被解释为**查询**参数。
* 如果参数的类型被声明为一个 **Pydantic 模型**,它将被解释为**请求体**。
## 不使用 Pydantic
如果你不想使用 Pydantic 模型,你还可以使用 **Body** 参数。请参阅文档 [请求体 - 多个参数:请求体中的单一值](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank}。

View File

@@ -0,0 +1,335 @@
# 第一步
最简单的 FastAPI 文件可能像下面这样:
```Python
{!../../../docs_src/first_steps/tutorial001.py!}
```
将其复制到 `main.py` 文件中。
运行实时服务器:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
!!! note
`uvicorn main:app` 命令含义如下:
* `main``main.py` 文件(一个 Python「模块」
* `app`:在 `main.py` 文件中通过 `app = FastAPI()` 创建的对象。
* `--reload`:让服务器在更新代码后重新启动。仅在开发时使用该选项。
在输出中,会有一行信息像下面这样:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
该行显示了你的应用在本机所提供服务的 URL 地址。
### 查看
打开浏览器访问 <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>。
你将看到如下的 JSON 响应:
```JSON
{"message": "Hello World"}
```
### 交互式 API 文档
跳转到 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
你将会看到自动生成的交互式 API 文档(由 <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> 提供):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### 可选的 API 文档
前往 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>。
你将会看到可选的自动生成文档 (由 <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> 提供)
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI** 使用定义 API 的 **OpenAPI** 标准将你的所有 API 转换成「模式」。
#### 「模式」
「模式」是对事物的一种定义或描述。它并非具体的实现代码,而只是抽象的描述。
#### API「模式」
在这种场景下OpenAPI 是一种规定如何定义 API 模式的规范。
定义的 OpenAPI 模式将包括你的 API 路径,以及它们可能使用的参数等等。
#### 数据「模式」
「模式」这个术语也可能指的是某些数据比如 JSON 的结构。
在这种情况下,它可以表示 JSON 的属性及其具有的数据类型,等等。
#### OpenAPI 和 JSON Schema
OpenAPI 为你的 API 定义 API 模式。该模式中包含了你的 API 发送和接收的数据的定义(或称为「模式」),这些定义通过 JSON 数据模式标准 **JSON Schema** 所生成。
#### 查看 `openapi.json`
如果你对原始的 OpenAPI 模式长什么样子感到好奇,其实它只是一个自动生成的包含了所有 API 描述的 JSON。
你可以直接在:<a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a> 看到它。
它将显示以如下内容开头的 JSON
```JSON
{
"openapi": "3.0.2",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### OpenAPI 的用途
驱动 FastAPI 内置的 2 个交互式文档系统的正是 OpenAPI 模式。
并且还有数十种替代方案,它们全部都基于 OpenAPI。你可以轻松地将这些替代方案中的任何一种添加到使用 **FastAPI** 构建的应用程序中。
你还可以使用它自动生成与你的 API 进行通信的客户端代码。例如 web 前端,移动端或物联网嵌入程序。
## 分步概括
### 步骤 1导入 `FastAPI`
```Python hl_lines="1"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`FastAPI` 是一个为你的 API 提供了所有功能的 Python 类。
!!! note "技术细节"
`FastAPI` 是直接从 `Starlette` 继承的类。
你可以通过 `FastAPI` 使用所有的 Starlette 的功能。
### 步骤 2创建一个 `FastAPI`「实例」
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial001.py!}
```
这里的变量 `app` 会是 `FastAPI` 类的一个「实例」。
这个实例将是创建你所有 API 的主要交互对象。
这个 `app` 同样在如下命令中被 `uvicorn` 所引用:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
如果你像下面这样创建应用:
```Python hl_lines="3"
{!../../../docs_src/first_steps/tutorial002.py!}
```
将代码放入 `main.py` 文件中,然后你可以像下面这样运行 `uvicorn`
<div class="termy">
```console
$ uvicorn main:my_awesome_api --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### 步骤 3创建一个*路径操作*
#### 路径
这里的「路径」指的是 URL 中从第一个 `/` 起的后半部分。
所以,在一个这样的 URL 中:
```
https://example.com/items/foo
```
...路径会是:
```
/items/foo
```
!!! info
「路径」也通常被称为「端点」或「路由」。
开发 API 时,「路径」是用来分离「关注点」和「资源」的主要手段。
#### 操作
这里的「操作」指的是一种 HTTP「方法」。
下列之一:
* `POST`
* `GET`
* `PUT`
* `DELETE`
...以及更少见的几种:
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
在 HTTP 协议中,你可以使用以上的其中一种(或多种)「方法」与每个路径进行通信。
---
在开发 API 时,你通常使用特定的 HTTP 方法去执行特定的行为。
通常使用:
* `POST`:创建数据。
* `GET`:读取数据。
* `PUT`:更新数据。
* `DELETE`:删除数据。
因此,在 OpenAPI 中,每一个 HTTP 方法都被称为「操作」。
我们也打算称呼它们为「操作」。
#### 定义一个*路径操作装饰器*
```Python hl_lines="6"
{!../../../docs_src/first_steps/tutorial001.py!}
```
`@app.get("/")` 告诉 **FastAPI** 在它下方的函数负责处理如下访问请求:
* 请求路径为 `/`
* 使用 <abbr title="HTTP GET 方法"><code>get</code> 操作</abbr>
!!! info "`@decorator` Info"
`@something` 语法在 Python 中被称为「装饰器」。
像一顶漂亮的装饰帽一样,将它放在一个函数的上方(我猜测这个术语的命名就是这么来的)。
装饰器接收位于其下方的函数并且用它完成一些工作。
在我们的例子中,这个装饰器告诉 **FastAPI** 位于其下方的函数对应着**路径** `/` 加上 `get` **操作**。
它是一个「**路径操作装饰器**」。
你也可以使用其他的操作:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
以及更少见的:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
!!! tip
您可以随意使用任何一个操作HTTP方法
**FastAPI** 没有强制要求操作有任何特定的含义。
此处提供的信息仅作为指导,而不是要求。
比如,当使用 GraphQL 时通常你所有的动作都通过 `post` 一种方法执行。
### 步骤 4定义**路径操作函数**
这是我们的「**路径操作函数**」:
* **路径**:是 `/`。
* **操作**:是 `get`。
* **函数**:是位于「装饰器」下方的函数(位于 `@app.get("/")` 下方)。
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial001.py!}
```
这是一个 Python 函数。
每当 **FastAPI** 接收一个使用 `GET` 方法访问 URL「`/`」的请求时这个函数会被调用。
在这个例子中,它是一个 `async` 函数。
---
你也可以将其定义为常规函数而不使用 `async def`:
```Python hl_lines="7"
{!../../../docs_src/first_steps/tutorial003.py!}
```
!!! note
如果你不知道两者的区别,请查阅 [Async: *"In a hurry?"*](https://fastapi.tiangolo.com/async/#in-a-hurry){.internal-link target=_blank}。
### 步骤 5返回内容
```Python hl_lines="8"
{!../../../docs_src/first_steps/tutorial001.py!}
```
你可以返回一个 `dict`、`list`,像 `str`、`int` 一样的单个值,等等。
你还可以返回 Pydantic 模型(稍后你将了解更多)。
还有许多其他将会自动转换为 JSON 的对象和模型(包括 ORM 对象等)。尝试下使用你最喜欢的一种,它很有可能已经被支持。
## 总结
* 导入 `FastAPI`。
* 创建一个 `app` 实例。
* 编写一个**路径操作装饰器**(如 `@app.get("/")`)。
* 编写一个**路径操作函数**(如上面的 `def root(): ...`)。
* 运行开发服务器(如 `uvicorn main:app --reload`)。

View File

@@ -0,0 +1,234 @@
# 路径参数
你可以使用与 Python 格式化字符串相同的语法来声明路径"参数"或"变量"
```Python hl_lines="6 7"
{!../../../docs_src/path_params/tutorial001.py!}
```
路径参数 `item_id` 的值将作为参数 `item_id` 传递给你的函数。
所以,如果你运行示例并访问 <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>,将会看到如下响应:
```JSON
{"item_id":"foo"}
```
## 有类型的路径参数
你可以使用标准的 Python 类型标注为函数中的路径参数声明类型。
```Python hl_lines="7"
{!../../../docs_src/path_params/tutorial002.py!}
```
在这个例子中,`item_id` 被声明为 `int` 类型。
!!! check
这将为你的函数提供编辑器支持,包括错误检查、代码补全等等。
## 数据<abbr title="也被称为:序列化、解析">转换</abbr>
如果你运行示例并打开浏览器访问 <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a>,将得到如下响应:
```JSON
{"item_id":3}
```
!!! check
注意函数接收(并返回)的值为 3是一个 Python `int` 值,而不是字符串 `"3"`。
所以,**FastAPI** 通过上面的类型声明提供了对请求的自动<abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">"解析"</abbr>。
## 数据校验
但如果你通过浏览器访问 <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a>,你会看到一个清晰可读的 HTTP 错误:
```JSON
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
```
因为路径参数 `item_id` 传入的值为 `"foo"`,它不是一个 `int`。
如果你提供的是 `float` 而非整数也会出现同样的错误,比如: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
!!! check
所以,通过同样的 Python 类型声明,**FastAPI** 提供了数据校验功能。
注意上面的错误同样清楚地指出了校验未通过的具体原因。
在开发和调试与你的 API 进行交互的代码时,这非常有用。
## 文档
当你打开浏览器访问 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>,你将看到自动生成的交互式 API 文档:
<img src="https://fastapi.tiangolo.com/img/tutorial/path-params/image01.png">
!!! check
再一次,还是通过相同的 Python 类型声明,**FastAPI** 为你提供了自动生成的交互式文档(集成 Swagger UI
注意这里的路径参数被声明为一个整数。
## 基于标准的好处:可选文档
由于生成的 API 模式来自于 <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> 标准,所以有很多工具与其兼容。
正因如此,**FastAPI** 内置了一个可选的 API 文档(使用 Redoc
<img src="https://fastapi.tiangolo.com/img/tutorial/path-params/image02.png">
同样的,还有很多其他兼容的工具,包括适用于多种语言的代码生成工具。
## Pydantic
所有的数据校验都由 <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> 在幕后完成,所以你可以从它所有的优点中受益。并且你知道它在这方面非常胜任。
你可以使用同样的类型声明来声明 `str`、`float`、`bool` 以及许多其他的复合数据类型。
本教程的下一章节将探讨其中的一些内容。
## 顺序很重要
在创建*路径操作*时,你会发现有些情况下路径是固定的。
比如 `/users/me`,我们假设它用来获取关于当前用户的数据.
然后,你还可以使用路径 `/users/{user_id}` 来通过用户 ID 获取关于特定用户的数据。
由于*路径操作*是按顺序依次运行的,你需要确保路径 `/users/me` 声明在路径 `/users/{user_id}`之前:
```Python hl_lines="6 11"
{!../../../docs_src/path_params/tutorial003.py!}
```
否则,`/users/{user_id}` 的路径还将与 `/users/me` 相匹配,"认为"自己正在接收一个值为 `"me"` 的 `user_id` 参数。
## 预设值
如果你有一个接收路径参数的路径操作,但你希望预先设定可能的有效参数值,则可以使用标准的 Python <abbr title="Enumeration">`Enum`</abbr> 类型。
### 创建一个 `Enum` 类
导入 `Enum` 并创建一个继承自 `str` 和 `Enum` 的子类。
通过从 `str` 继承API 文档将能够知道这些值必须为 `string` 类型并且能够正确地展示出来。
然后创建具有固定值的类属性,这些固定值将是可用的有效值:
```Python hl_lines="1 6 7 8 9"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! info
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">枚举(或 enums</a>从 3.4 版本起在 Python 中可用。
!!! tip
如果你想知道,"AlexNet"、"ResNet" 和 "LeNet" 只是机器学习中的<abbr title="技术上来说是深度学习模型架构">模型</abbr>名称。
### 声明*路径参数*
然后使用你定义的枚举类(`ModelName`)创建一个带有类型标注的*路径参数*
```Python hl_lines="16"
{!../../../docs_src/path_params/tutorial005.py!}
```
### 查看文档
因为已经指定了*路径参数*的可用值,所以交互式文档可以恰当地展示它们:
<img src="https://fastapi.tiangolo.com/img/tutorial/path-params/image03.png">
### 使用 Python *枚举类型*
*路径参数*的值将是一个*枚举成员*。
#### 比较*枚举成员*
你可以将它与你创建的枚举类 `ModelName` 中的*枚举成员*进行比较:
```Python hl_lines="17"
{!../../../docs_src/path_params/tutorial005.py!}
```
#### 获取*枚举值*
你可以使用 `model_name.value` 或通常来说 `your_enum_member.value` 来获取实际的值(在这个例子中为 `str`
```Python hl_lines="19"
{!../../../docs_src/path_params/tutorial005.py!}
```
!!! tip
你也可以通过 `ModelName.lenet.value` 来获取值 `"lenet"`。
#### 返回*枚举成员*
你可以从*路径操作*中返回*枚举成员*,即使嵌套在 JSON 结构中(例如一个 `dict` 中)。
在返回给客户端之前,它们将被转换为对应的值:
```Python hl_lines="18 20 21"
{!../../../docs_src/path_params/tutorial005.py!}
```
## 包含路径的路径参数
假设你有一个*路径操作*,它的路径为 `/files/{file_path}`。
但是你需要 `file_path` 自身也包含*路径*,比如 `home/johndoe/myfile.txt`。
因此该文件的URL将类似于这样`/files/home/johndoe/myfile.txt`。
### OpenAPI 支持
OpenAPI 不支持任何方式去声明*路径参数*以在其内部包含*路径*,因为这可能会导致难以测试和定义的情况出现。
不过,你仍然可以通过 Starlette 的一个内部工具在 **FastAPI** 中实现它。
而且文档依旧可以使用,但是不会添加任何该参数应包含路径的说明。
### 路径转换器
你可以使用直接来自 Starlette 的选项来声明一个包含*路径*的*路径参数*
```
/files/{file_path:path}
```
在这种情况下,参数的名称为 `file_path`,结尾部分的 `:path` 说明该参数应匹配任意的*路径*。
因此,你可以这样使用它:
```Python hl_lines="6"
{!../../../docs_src/path_params/tutorial004.py!}
```
!!! tip
你可能会需要参数包含 `/home/johndoe/myfile.txt`,以斜杠(`/`)开头。
在这种情况下URL 将会是 `/files//home/johndoe/myfile.txt`,在`files` 和 `home` 之间有一个双斜杠(`//`)。
## 总结
使用 **FastAPI**,通过简短、直观和标准的 Python 类型声明,你将获得:
* 编辑器支持:错误检查,代码补全等
* 数据 "<abbr title="将来自 HTTP 请求中的字符串转换为 Python 数据类型">解析</abbr>"
* 数据校验
* API 标注和自动生成的文档
而且你只需要声明一次即可。
这可能是 **FastAPI** 与其他框架相比主要的明显优势(除了原始性能以外)。

View File

@@ -0,0 +1,281 @@
# 查询参数和字符串校验
**FastAPI** 允许你为参数声明额外的信息和校验。
让我们以下面的应用程序为例:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial001.py!}
```
查询参数 `q` 的类型为 `str`,默认值为 `None`,因此它是可选的。
## 额外的校验
我们打算添加约束条件:即使 `q` 是可选的,但只要提供了该参数,则该参数值**不能超过50个字符的长度**。
### 导入 `Query`
为此,首先从 `fastapi` 导入 `Query`
```Python hl_lines="1"
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
## 使用 `Query` 作为默认值
现在,将 `Query` 用作查询参数的默认值,并将它的 `max_length` 参数设置为 50
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial002.py!}
```
由于我们必须用 `Query(None)` 替换默认值 `None``Query` 的第一个参数同样也是用于定义默认值。
所以:
```Python
q: str = Query(None)
```
...使得参数可选,等同于:
```Python
q: str = None
```
但是 `Query` 显式地将其声明为查询参数。
然后,我们可以将更多的参数传递给 `Query`。在本例中,适用于字符串的 `max_length` 参数:
```Python
q: str = Query(None, max_length=50)
```
将会校验数据,在数据无效时展示清晰的错误信息,并在 OpenAPI 模式的*路径操作*中记录该参​​数。
## 添加更多校验
你还可以添加 `min_length` 参数:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial003.py!}
```
## 添加正则表达式
你可以定义一个参数值必须匹配的<abbr title="正则表达式或正则是定义字符串搜索模式的字符序列。">正则表达式</abbr>
```Python hl_lines="8"
{!../../../docs_src/query_params_str_validations/tutorial004.py!}
```
这个指定的正则表达式通过以下规则检查接收到的参数值:
* `^`:以该符号之后的字符开头,符号之前没有字符。
* `fixedquery`: 值精确地等于 `fixedquery`。
* `$`: 到此结束,在 `fixedquery` 之后没有更多字符。
如果你对所有的这些**「正则表达式」**概念感到迷茫,请不要担心。对于许多人来说这都是一个困难的主题。你仍然可以在无需正则表达式的情况下做很多事情。
但是,一旦你需要用到并去学习它们时,请了解你已经可以在 **FastAPI** 中直接使用它们。
## 默认值
你可以向 `Query` 的第一个参数传入 `None` 用作查询参数的默认值,以同样的方式你也可以传递其他默认值。
假设你想要声明查询参数 `q`,使其 `min_length` 为 `3`,并且默认值为 `fixedquery`
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial005.py!}
```
!!! note
具有默认值还会使该参数成为可选参数。
## 声明为必需参数
当我们不需要声明额外的校验或元数据时,只需不声明默认值就可以使 `q` 参数成为必需参数,例如:
```Python
q: str
```
代替:
```Python
q: str = None
```
但是现在我们正在用 `Query` 声明它,例如:
```Python
q: str = Query(None, min_length=3)
```
因此,当你在使用 `Query` 且需要声明一个值是必需的时,可以将 `...` 用作第一个参数值:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial006.py!}
```
!!! info
如果你之前没见过 `...` 这种用法:它是一个特殊的单独值,它是 <a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">Python 的一部分并且被称为「省略号」</a>。
这将使 **FastAPI** 知道此查询参数是必需的。
## 查询参数列表 / 多个值
当你使用 `Query` 显式地定义查询参数时,你还可以声明它去接收一组值,或换句话来说,接收多个值。
例如,要声明一个可在 URL 中出现多次的查询参数 `q`,你可以这样写:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial011.py!}
```
然后,输入如下网址:
```
http://localhost:8000/items/?q=foo&q=bar
```
你会在*路径操作函数*的*函数参数* `q` 中以一个 Python `list` 的形式接收到*查询参数* `q` 的多个值(`foo` 和 `bar`)。
因此,该 URL 的响应将会是:
```JSON
{
"q": [
"foo",
"bar"
]
}
```
!!! tip
要声明类型为 `list` 的查询参数,如上例所示,你需要显式地使用 `Query`,否则该参数将被解释为请求体。
交互式 API 文档将会相应地进行更新,以允许使用多个值:
<img src="https://fastapi.tiangolo.com/img/tutorial/query-params-str-validations/image02.png">
### 具有默认值的查询参数列表 / 多个值
你还可以定义在没有任何给定值时的默认 `list` 值:
```Python hl_lines="9"
{!../../../docs_src/query_params_str_validations/tutorial012.py!}
```
如果你访问:
```
http://localhost:8000/items/
```
`q` 的默认值将为:`["foo", "bar"]`,你的响应会是:
```JSON
{
"q": [
"foo",
"bar"
]
}
```
#### 使用 `list`
你也可以直接使用 `list` 代替 `List [str]`
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial013.py!}
```
!!! note
请记住,在这种情况下 FastAPI 将不会检查列表的内容。
例如,`List[int]` 将检查(并记录到文档)列表的内容必须是整数。但是单独的 `list` 不会。
## 声明更多元数据
你可以添加更多有关该参数的信息。
这些信息将包含在生成的 OpenAPI 模式中,并由文档用户界面和外部工具所使用。
!!! note
请记住,不同的工具对 OpenAPI 的支持程度可能不同。
其中一些可能不会展示所有已声明的额外信息,尽管在大多数情况下,缺少的这部分功能已经计划进行开发。
你可以添加 `title`
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial007.py!}
```
以及 `description`
```Python hl_lines="11"
{!../../../docs_src/query_params_str_validations/tutorial008.py!}
```
## 别名参数
假设你想要查询参数为 `item-query`。
像下面这样:
```
http://127.0.0.1:8000/items/?item-query=foobaritems
```
但是 `item-query` 不是一个有效的 Python 变量名称。
最接近的有效名称是 `item_query`。
但是你仍然要求它在 URL 中必须是 `item-query`...
这时你可以用 `alias` 参数声明一个别名,该别名将用于在 URL 中查找查询参数值:
```Python hl_lines="7"
{!../../../docs_src/query_params_str_validations/tutorial009.py!}
```
## 弃用参数
现在假设你不再喜欢此参数。
你不得不将其保留一段时间,因为有些客户端正在使用它,但你希望文档清楚地将其展示为<abbr title ="已过时,建议不要使用它">已弃用</abbr>。
那么将参数 `deprecated=True` 传入 `Query`
```Python hl_lines="16"
{!../../../docs_src/query_params_str_validations/tutorial010.py!}
```
文档将会像下面这样展示它:
<img src="https://fastapi.tiangolo.com/img/tutorial/query-params-str-validations/image01.png">
## 总结
你可以为查询参数声明额外的校验和元数据。
通用的校验和元数据:
* `alias`
* `title`
* `description`
* `deprecated`
特定于字符串的校验:
* `min_length`
* `max_length`
* `regex`
在这些示例中,你了解了如何声明对 `str` 值的校验。
请参阅下一章节,以了解如何声明对其他类型例如数值的校验。

View File

@@ -0,0 +1,226 @@
# 查询参数
声明不属于路径参数的其他函数参数时,它们将被自动解释为"查询字符串"参数
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
查询字符串是键值对的集合,这些键值对位于 URL 的 `` 之后,并以 `&` 符号分隔。
例如,在以下 url 中:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...查询参数为:
* `skip`:对应的值为 `0`
* `limit`:对应的值为 `10`
由于它们是 URL 的一部分,因此它们的"原始值"是字符串。
但是,当你为它们声明了 Python 类型(在上面的示例中为 `int`)时,它们将转换为该类型并针对该类型进行校验。
应用于路径参数的所有相同过程也适用于查询参数:
* (很明显的)编辑器支持
* 数据<abbr title="将来自 HTTP 请求的字符串转换为 Python 数据类型">"解析"</abbr>
* 数据校验
* 自动生成文档
## 默认值
由于查询参数不是路径的固定部分,因此它们可以是可选的,并且可以有默认值。
在上面的示例中,它们具有 `skip=0` 和 `limit=10` 的默认值。
因此,访问 URL
```
http://127.0.0.1:8000/items/
```
将与访问以下地址相同:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
但是,如果你访问的是:
```
http://127.0.0.1:8000/items/?skip=20
```
函数中的参数值将会是:
* `skip=20`:在 URL 中设定的值
* `limit=10`:使用默认值
## 可选参数
通过同样的方式,你可以将它们的默认值设置为 `None` 来声明可选查询参数:
```Python hl_lines="7"
{!../../../docs_src/query_params/tutorial002.py!}
```
在这个例子中,函数参数 `q` 将是可选的,并且默认值为 `None`。
!!! check
还要注意的是,**FastAPI** 足够聪明,能够分辨出参数 `item_id` 是路径参数而 `q` 不是,因此 `q` 是一个查询参数。
## 查询参数类型转换
你还可以声明 `bool` 类型,它们将被自动转换:
```Python hl_lines="7"
{!../../../docs_src/query_params/tutorial003.py!}
```
这个例子中,如果你访问:
```
http://127.0.0.1:8000/items/foo?short=1
```
```
http://127.0.0.1:8000/items/foo?short=True
```
```
http://127.0.0.1:8000/items/foo?short=true
```
```
http://127.0.0.1:8000/items/foo?short=on
```
```
http://127.0.0.1:8000/items/foo?short=yes
```
或任何其他的变体形式(大写,首字母大写等等),你的函数接收的 `short` 参数都会是布尔值 `True`。对于值为 `False` 的情况也是一样的。
## 多个路径和查询参数
你可以同时声明多个路径参数和查询参数,**FastAPI** 能够识别它们。
而且你不需要以任何特定的顺序来声明。
它们将通过名称被检测到:
```Python hl_lines="6 8"
{!../../../docs_src/query_params/tutorial004.py!}
```
## 必需查询参数
当你为非路径参数声明了默认值时(目前而言,我们所知道的仅有查询参数),则该参数不是必需的。
如果你不想添加一个特定的值,而只是想使该参数成为可选的,则将默认值设置为 `None`。
但当你想让一个查询参数成为必需的,不声明任何默认值就可以:
```Python hl_lines="6 7"
{!../../../docs_src/query_params/tutorial005.py!}
```
这里的查询参数 `needy` 是类型为 `str` 的必需查询参数。
如果你在浏览器中打开一个像下面的 URL
```
http://127.0.0.1:8000/items/foo-item
```
...因为没有添加必需的参数 `needy`,你将看到类似以下的错误:
```JSON
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}
```
由于 `needy` 是必需参数,因此你需要在 URL 中设置它的值:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...这样就正常了:
```JSON
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
```
当然,你也可以定义一些参数为必需的,一些具有默认值,而某些则完全是可选的:
```Python hl_lines="7"
{!../../../docs_src/query_params/tutorial006.py!}
```
在这个例子中有3个查询参数
* `needy`,一个必需的 `str` 类型参数。
* `skip`,一个默认值为 `0` 的 `int` 类型参数。
* `limit`,一个可选的 `int` 类型参数。
!!! tip
你还可以像在 [路径参数](path-params.md#predefined-values){.internal-link target=_blank} 中那样使用 `Enum`。
## Optional 类型声明
!!! warning
这可能是一个比较高级的使用场景。
您也可以跳过它。
如果你正在使用 `mypy`,它可能会对如下的类型声明进行警告:
```Python
limit: int = None
```
提示类似以下错误:
```
Incompatible types in assignment (expression has type "None", variable has type "int")
```
在这种情况下,你可以使用 `Optional` 来告诉 `mypy` 该值可以为 `None`,例如:
```Python
from typing import Optional
limit: Optional[int] = None
```
在一个*路径操作*中,看起来会是:
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial007.py!}
```

View File

@@ -22,12 +22,22 @@ nav:
- Languages:
- en: /
- es: /es/
- it: /it/
- pt: /pt/
- ru: /ru/
- zh: /zh/
- features.md
- python-types.md
- 教程 - 用户指南:
- tutorial/index.md
- tutorial/first-steps.md
- tutorial/path-params.md
- tutorial/query-params.md
- tutorial/body.md
- tutorial/query-params-str-validations.md
- deployment.md
- contributing.md
- help-fastapi.md
markdown_extensions:
- toc:
permalink: true

View File

@@ -51,7 +51,7 @@ def test_create_item_bad_token():
assert response.json() == {"detail": "Invalid X-Token header"}
def test_create_existing_token():
def test_create_existing_item():
response = client.post(
"/items/",
headers={"X-Token": "coneofsilence"},

View File

@@ -0,0 +1,8 @@
from fastapi import FastAPI, Request
app = FastAPI()
@app.get("/app")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}

View File

@@ -0,0 +1,8 @@
from fastapi import FastAPI, Request
app = FastAPI(root_path="/api/v1")
@app.get("/app")
def read_main(request: Request):
return {"message": "Hello World", "root_path": request.scope.get("root_path")}

View File

@@ -12,6 +12,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item = Body(..., embed=True)):
async def update_item(item_id: int, item: Item = Body(..., embed=True)):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -17,6 +17,6 @@ class User(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item, user: User):
async def update_item(item_id: int, item: Item, user: User):
results = {"item_id": item_id, "item": item, "user": user}
return results

View File

@@ -18,7 +18,7 @@ class User(BaseModel):
@app.put("/items/{item_id}")
async def update_item(
*, item_id: int, item: Item, user: User, importance: int = Body(...)
item_id: int, item: Item, user: User, importance: int = Body(...)
):
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
return results

View File

@@ -12,6 +12,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item = Body(..., embed=True)):
async def update_item(item_id: int, item: Item = Body(..., embed=True)):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -13,6 +13,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -15,6 +15,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -15,6 +15,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -21,6 +21,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -21,6 +21,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -21,6 +21,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -28,5 +28,5 @@ class Offer(BaseModel):
@app.post("/offers/")
async def create_offer(*, offer: Offer):
async def create_offer(offer: Offer):
return offer

View File

@@ -12,5 +12,5 @@ class Image(BaseModel):
@app.post("/images/multiple/")
async def create_multiple_images(*, images: List[Image]):
async def create_multiple_images(images: List[Image]):
return images

View File

@@ -4,5 +4,5 @@ app = FastAPI()
@app.get("/items/")
async def read_items(*, ads_id: str = Cookie(None)):
async def read_items(ads_id: str = Cookie(None)):
return {"ads_id": ads_id}

View File

@@ -0,0 +1,9 @@
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI(default_response_class=ORJSONResponse)
@app.get("/items/")
async def read_items():
return [{"item_id": "Foo"}]

View File

@@ -9,7 +9,7 @@ async def read_items():
return [{"name": "Foo"}]
def custom_openapi():
def custom_openapi(openapi_prefix: str):
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
@@ -17,6 +17,7 @@ def custom_openapi():
version="2.5.0",
description="This is a very custom OpenAPI schema",
routes=app.routes,
openapi_prefix=openapi_prefix,
)
openapi_schema["info"]["x-logo"] = {
"url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png"

View File

@@ -36,6 +36,6 @@ def fake_save_user(user_in: UserIn):
@app.post("/user/", response_model=UserOut)
async def create_user(*, user_in: UserIn):
async def create_user(user_in: UserIn):
user_saved = fake_save_user(user_in)
return user_saved

View File

@@ -34,6 +34,6 @@ def fake_save_user(user_in: UserIn):
@app.post("/user/", response_model=UserOut)
async def create_user(*, user_in: UserIn):
async def create_user(user_in: UserIn):
user_saved = fake_save_user(user_in)
return user_saved

View File

@@ -4,5 +4,5 @@ app = FastAPI()
@app.get("/items/")
async def read_items(*, user_agent: str = Header(None)):
async def read_items(user_agent: str = Header(None)):
return {"User-Agent": user_agent}

View File

@@ -4,5 +4,5 @@ app = FastAPI()
@app.get("/items/")
async def read_items(*, strange_header: str = Header(None, convert_underscores=False)):
async def read_items(strange_header: str = Header(None, convert_underscores=False)):
return {"strange_header": strange_header}

View File

@@ -0,0 +1,28 @@
from fastapi import FastAPI
tags_metadata = [
{
"name": "users",
"description": "Operations with users. The **login** logic is also here.",
},
{
"name": "items",
"description": "Manage items. So _fancy_ they have their own docs.",
"externalDocs": {
"description": "Items external docs",
"url": "https://fastapi.tiangolo.com/",
},
},
]
app = FastAPI(openapi_tags=tags_metadata)
@app.get("/users/", tags=["users"])
async def get_users():
return [{"name": "Harry"}, {"name": "Ron"}]
@app.get("/items/", tags=["items"])
async def get_items():
return [{"name": "wand"}, {"name": "flying broom"}]

View File

@@ -15,7 +15,7 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_item(*, item: Item):
async def create_item(item: Item):
"""
Create an item with all the information:

View File

@@ -15,5 +15,5 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, status_code=status.HTTP_201_CREATED)
async def create_item(*, item: Item):
async def create_item(item: Item):
return item

View File

@@ -15,7 +15,7 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, tags=["items"])
async def create_item(*, item: Item):
async def create_item(item: Item):
return item

View File

@@ -20,5 +20,5 @@ class Item(BaseModel):
summary="Create an item",
description="Create an item with all the information, name, description, price, tax and a set of unique tags",
)
async def create_item(*, item: Item):
async def create_item(item: Item):
return item

View File

@@ -15,7 +15,7 @@ class Item(BaseModel):
@app.post("/items/", response_model=Item, summary="Create an item")
async def create_item(*, item: Item):
async def create_item(item: Item):
"""
Create an item with all the information:

View File

@@ -20,7 +20,7 @@ class Item(BaseModel):
summary="Create an item",
response_description="The created item",
)
async def create_item(*, item: Item):
async def create_item(item: Item):
"""
Create an item with all the information:

View File

@@ -16,6 +16,8 @@ app = FastAPI()
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}

View File

@@ -1,7 +1,8 @@
class Person:
def __init__(self, name: str):
self.name = name
from typing import Optional
def get_person_name(one_person: Person):
return one_person.name
def say_hi(name: Optional[str] = None):
if name is not None:
print(f"Hey {name}!")
else:
print("Hello World")

View File

@@ -1,23 +1,7 @@
from datetime import datetime
from typing import List
from pydantic import BaseModel
class Person:
def __init__(self, name: str):
self.name = name
class User(BaseModel):
id: int
name = "John Doe"
signup_ts: datetime = None
friends: List[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
def get_person_name(one_person: Person):
return one_person.name

View File

@@ -0,0 +1,23 @@
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel
class User(BaseModel):
id: int
name = "John Doe"
signup_ts: Optional[datetime] = None
friends: List[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123

View File

@@ -4,5 +4,5 @@ app = FastAPI()
@app.post("/login/")
async def login(*, username: str = Form(...), password: str = Form(...)):
async def login(username: str = Form(...), password: str = Form(...)):
return {"username": username}

View File

@@ -13,5 +13,5 @@ class UserIn(BaseModel):
# Don't do this in production!
@app.post("/user/", response_model=UserIn)
async def create_user(*, user: UserIn):
async def create_user(user: UserIn):
return user

View File

@@ -18,5 +18,5 @@ class UserOut(BaseModel):
@app.post("/user/", response_model=UserOut)
async def create_user(*, user: UserIn):
async def create_user(user: UserIn):
return user

View File

@@ -22,6 +22,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -12,6 +12,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(*, item_id: int, item: Item):
async def update_item(item_id: int, item: Item):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -13,7 +13,6 @@ class Item(BaseModel):
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Item = Body(
...,
@@ -23,7 +22,7 @@ async def update_item(
"price": 35.4,
"tax": 3.2,
},
)
),
):
results = {"item_id": item_id, "item": item}
return results

View File

@@ -75,7 +75,7 @@ def authenticate_user(fake_db, username: str, password: str):
return user
def create_access_token(*, data: dict, expires_delta: timedelta = None):
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta

View File

@@ -91,7 +91,7 @@ def authenticate_user(fake_db, username: str, password: str):
return user
def create_access_token(*, data: dict, expires_delta: timedelta = None):
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta

View File

@@ -8,7 +8,7 @@ def read_main():
return {"message": "Hello World from main app"}
subapi = FastAPI(openapi_prefix="/subapi")
subapi = FastAPI()
@subapi.get("/sub")

View File

@@ -1,4 +1,4 @@
from fastapi import Cookie, Depends, FastAPI, Header, WebSocket, status
from fastapi import Cookie, Depends, FastAPI, Query, WebSocket, status
from fastapi.responses import HTMLResponse
app = FastAPI()
@@ -13,8 +13,9 @@ html = """
<h1>WebSocket Chat</h1>
<form action="" onsubmit="sendMessage(event)">
<label>Item ID: <input type="text" id="itemId" autocomplete="off" value="foo"/></label>
<label>Token: <input type="text" id="token" autocomplete="off" value="some-key-token"/></label>
<button onclick="connect(event)">Connect</button>
<br>
<hr>
<label>Message: <input type="text" id="messageText" autocomplete="off"/></label>
<button>Send</button>
</form>
@@ -23,8 +24,9 @@ html = """
<script>
var ws = null;
function connect(event) {
var input = document.getElementById("itemId")
ws = new WebSocket("ws://localhost:8000/items/" + input.value + "/ws");
var itemId = document.getElementById("itemId")
var token = document.getElementById("token")
ws = new WebSocket("ws://localhost:8000/items/" + itemId.value + "/ws?token=" + token.value);
ws.onmessage = function(event) {
var messages = document.getElementById('messages')
var message = document.createElement('li')
@@ -32,6 +34,7 @@ html = """
message.appendChild(content)
messages.appendChild(message)
};
event.preventDefault()
}
function sendMessage(event) {
var input = document.getElementById("messageText")
@@ -50,26 +53,26 @@ async def get():
return HTMLResponse(html)
async def get_cookie_or_client(
websocket: WebSocket, session: str = Cookie(None), x_client: str = Header(None)
async def get_cookie_or_token(
websocket: WebSocket, session: str = Cookie(None), token: str = Query(None)
):
if session is None and x_client is None:
if session is None and token is None:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return session or x_client
return session or token
@app.websocket("/items/{item_id}/ws")
async def websocket_endpoint(
websocket: WebSocket,
item_id: int,
q: str = None,
cookie_or_client: str = Depends(get_cookie_or_client),
item_id: str,
q: int = None,
cookie_or_token: str = Depends(get_cookie_or_token),
):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(
f"Session Cookie or X-Client Header value is: {cookie_or_client}"
f"Session cookie or query token value is: {cookie_or_token}"
)
if q is not None:
await websocket.send_text(f"Query parameter q is: {q}")

View File

@@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.55.0"
__version__ = "0.58.0"
from starlette import status

View File

@@ -8,6 +8,7 @@ from fastapi.exception_handlers import (
request_validation_exception_handler,
)
from fastapi.exceptions import RequestValidationError
from fastapi.logger import logger
from fastapi.openapi.docs import (
get_redoc_html,
get_swagger_ui_html,
@@ -36,7 +37,8 @@ class FastAPI(Starlette):
description: str = "",
version: str = "0.1.0",
openapi_url: Optional[str] = "/openapi.json",
openapi_prefix: str = "",
openapi_tags: Optional[List[Dict[str, Any]]] = None,
servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
default_response_class: Type[Response] = JSONResponse,
docs_url: Optional[str] = "/docs",
redoc_url: Optional[str] = "/redoc",
@@ -46,6 +48,8 @@ class FastAPI(Starlette):
exception_handlers: Dict[Union[int, Type[Exception]], Callable] = None,
on_startup: Sequence[Callable] = None,
on_shutdown: Sequence[Callable] = None,
openapi_prefix: str = "",
root_path: str = "",
**extra: Dict[str, Any],
) -> None:
self.default_response_class = default_response_class
@@ -67,8 +71,18 @@ class FastAPI(Starlette):
self.title = title
self.description = description
self.version = version
self.servers = servers
self.openapi_url = openapi_url
self.openapi_prefix = openapi_prefix.rstrip("/")
self.openapi_tags = openapi_tags
# TODO: remove when discarding the openapi_prefix parameter
if openapi_prefix:
logger.warning(
'"openapi_prefix" has been deprecated in favor of "root_path", which '
"follows more closely the ASGI standard, is simpler, and more "
"automatic. Check the docs at "
"https://fastapi.tiangolo.com/advanced/sub-applications-proxy/"
)
self.root_path = root_path or openapi_prefix
self.docs_url = docs_url
self.redoc_url = redoc_url
self.swagger_ui_oauth2_redirect_url = swagger_ui_oauth2_redirect_url
@@ -84,7 +98,7 @@ class FastAPI(Starlette):
self.openapi_schema: Optional[Dict[str, Any]] = None
self.setup()
def openapi(self) -> Dict:
def openapi(self, openapi_prefix: str = "") -> Dict:
if not self.openapi_schema:
self.openapi_schema = get_openapi(
title=self.title,
@@ -92,7 +106,9 @@ class FastAPI(Starlette):
openapi_version=self.openapi_version,
description=self.description,
routes=self.routes,
openapi_prefix=self.openapi_prefix,
openapi_prefix=openapi_prefix,
tags=self.openapi_tags,
servers=self.servers,
)
return self.openapi_schema
@@ -100,17 +116,22 @@ class FastAPI(Starlette):
if self.openapi_url:
async def openapi(req: Request) -> JSONResponse:
return JSONResponse(self.openapi())
root_path = req.scope.get("root_path", "").rstrip("/")
return JSONResponse(self.openapi(root_path))
self.add_route(self.openapi_url, openapi, include_in_schema=False)
openapi_url = self.openapi_prefix + self.openapi_url
if self.openapi_url and self.docs_url:
async def swagger_ui_html(req: Request) -> HTMLResponse:
root_path = req.scope.get("root_path", "").rstrip("/")
openapi_url = root_path + self.openapi_url
oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url
if oauth2_redirect_url:
oauth2_redirect_url = root_path + oauth2_redirect_url
return get_swagger_ui_html(
openapi_url=openapi_url,
title=self.title + " - Swagger UI",
oauth2_redirect_url=self.swagger_ui_oauth2_redirect_url,
oauth2_redirect_url=oauth2_redirect_url,
init_oauth=self.swagger_ui_init_oauth,
)
@@ -129,6 +150,8 @@ class FastAPI(Starlette):
if self.openapi_url and self.redoc_url:
async def redoc_html(req: Request) -> HTMLResponse:
root_path = req.scope.get("root_path", "").rstrip("/")
openapi_url = root_path + self.openapi_url
return get_redoc_html(
openapi_url=openapi_url, title=self.title + " - ReDoc"
)
@@ -140,6 +163,8 @@ class FastAPI(Starlette):
)
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
if self.root_path:
scope["root_path"] = self.root_path
if AsyncExitStack:
async with AsyncExitStack() as stack:
scope["fastapi_astack"] = stack

View File

@@ -188,6 +188,16 @@ def get_flat_dependant(
return flat_dependant
def get_flat_params(dependant: Dependant) -> List[ModelField]:
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
return (
flat_dependant.path_params
+ flat_dependant.query_params
+ flat_dependant.header_params
+ flat_dependant.cookie_params
)
def is_scalar_field(field: ModelField) -> bool:
field_info = get_field_info(field)
if not (
@@ -264,7 +274,7 @@ def get_dependant(
path_param_names = get_path_param_names(path)
endpoint_signature = get_typed_signature(call)
signature_params = endpoint_signature.parameters
if inspect.isgeneratorfunction(call) or inspect.isasyncgenfunction(call):
if is_gen_callable(call) or is_async_gen_callable(call):
check_dependency_contextmanagers()
dependant = Dependant(call=call, name=name, path=path, use_cache=use_cache)
for param_name, param in signature_params.items():
@@ -284,7 +294,7 @@ def get_dependant(
if param_name in path_param_names:
assert is_scalar_field(
field=param_field
), f"Path params must be of one of the supported types"
), "Path params must be of one of the supported types"
if isinstance(param.default, params.Path):
ignore_default = False
else:
@@ -402,19 +412,41 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
def is_coroutine_callable(call: Callable) -> bool:
if inspect.isroutine(call):
return asyncio.iscoroutinefunction(call)
return inspect.iscoroutinefunction(call)
if inspect.isclass(call):
return False
call = getattr(call, "__call__", None)
return asyncio.iscoroutinefunction(call)
return inspect.iscoroutinefunction(call)
def is_async_gen_callable(call: Callable) -> bool:
if inspect.isasyncgenfunction(call):
return True
call = getattr(call, "__call__", None)
return inspect.isasyncgenfunction(call)
def is_gen_callable(call: Callable) -> bool:
if inspect.isgeneratorfunction(call):
return True
call = getattr(call, "__call__", None)
return inspect.isgeneratorfunction(call)
async def solve_generator(
*, call: Callable, stack: AsyncExitStack, sub_values: Dict[str, Any]
) -> Any:
if inspect.isgeneratorfunction(call):
if is_gen_callable(call):
cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values))
elif inspect.isasyncgenfunction(call):
elif is_async_gen_callable(call):
if not inspect.isasyncgenfunction(call):
# asynccontextmanager from the async_generator backfill pre python3.7
# does not support callables that are not functions or methods.
# See https://github.com/python-trio/async_generator/issues/32
#
# Expand the callable class into its __call__ method before decorating it.
# This approach will work on newer python versions as well.
call = getattr(call, "__call__", None)
cm = asynccontextmanager(call)(**sub_values)
return await stack.enter_async_context(cm)
@@ -468,6 +500,7 @@ async def solve_dependencies(
name=sub_dependant.name,
security_scopes=sub_dependant.security_scopes,
)
use_sub_dependant.security_scopes = sub_dependant.security_scopes
solved_result = await solve_dependencies(
request=request,
@@ -482,20 +515,16 @@ async def solve_dependencies(
sub_values,
sub_errors,
background_tasks,
sub_response,
_, # the subdependency returns the same response we have
sub_dependency_cache,
) = solved_result
sub_response = cast(Response, sub_response)
response.headers.raw.extend(sub_response.headers.raw)
if sub_response.status_code:
response.status_code = sub_response.status_code
dependency_cache.update(sub_dependency_cache)
if sub_errors:
errors.extend(sub_errors)
continue
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
solved = dependency_cache[sub_dependant.cache_key]
elif inspect.isgeneratorfunction(call) or inspect.isasyncgenfunction(call):
elif is_gen_callable(call) or is_async_gen_callable(call):
stack = request.scope.get("fastapi_astack")
if stack is None:
raise RuntimeError(
@@ -613,9 +642,17 @@ async def request_body_to_args(
field = required_params[0]
field_info = get_field_info(field)
embed = getattr(field_info, "embed", None)
if len(required_params) == 1 and not embed:
field_alias_omitted = len(required_params) == 1 and not embed
if field_alias_omitted:
received_body = {field.alias: received_body}
for field in required_params:
loc: Tuple[str, ...]
if field_alias_omitted:
loc = ("body",)
else:
loc = ("body", field.alias)
value: Any = None
if received_body is not None:
if (
@@ -626,7 +663,7 @@ async def request_body_to_args(
try:
value = received_body.get(field.alias)
except AttributeError:
errors.append(get_missing_field_error(field.alias))
errors.append(get_missing_field_error(loc))
continue
if (
value is None
@@ -638,7 +675,7 @@ async def request_body_to_args(
)
):
if field.required:
errors.append(get_missing_field_error(field.alias))
errors.append(get_missing_field_error(loc))
else:
values[field.name] = deepcopy(field.default)
continue
@@ -657,7 +694,9 @@ async def request_body_to_args(
awaitables = [sub_value.read() for sub_value in value]
contents = await asyncio.gather(*awaitables)
value = sequence_shape_to_type[field.shape](contents)
v_, errors_ = field.validate(value, values, loc=("body", field.alias))
v_, errors_ = field.validate(value, values, loc=loc)
if isinstance(errors_, ErrorWrapper):
errors.append(errors_)
elif isinstance(errors_, list):
@@ -667,12 +706,12 @@ async def request_body_to_args(
return values, errors
def get_missing_field_error(field_alias: str) -> ErrorWrapper:
def get_missing_field_error(loc: Tuple[str, ...]) -> ErrorWrapper:
if PYDANTIC_1:
missing_field_error = ErrorWrapper(MissingError(), loc=("body", field_alias))
missing_field_error = ErrorWrapper(MissingError(), loc=loc)
else: # pragma: no cover
missing_field_error = ErrorWrapper( # type: ignore
MissingError(), loc=("body", field_alias), config=BaseConfig,
MissingError(), loc=loc, config=BaseConfig,
)
return missing_field_error

View File

@@ -71,6 +71,8 @@ def jsonable_encoder(
by_alias=by_alias,
skip_defaults=bool(exclude_unset or skip_defaults),
)
if "__root__" in obj_dict:
obj_dict = obj_dict["__root__"]
return jsonable_encoder(
obj_dict,
exclude_none=exclude_none,

View File

@@ -44,7 +44,9 @@ def get_swagger_ui_html(
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout",
deepLinking: true
deepLinking: true,
showExtensions: true,
showCommonExtensions: true
})"""
if init_oauth:

View File

@@ -63,7 +63,7 @@ class ServerVariable(BaseModel):
class Server(BaseModel):
url: AnyUrl
url: Union[AnyUrl, str]
description: Optional[str] = None
variables: Optional[Dict[str, ServerVariable]] = None
@@ -112,7 +112,7 @@ class SchemaBase(BaseModel):
allOf: Optional[List[Any]] = None
oneOf: Optional[List[Any]] = None
anyOf: Optional[List[Any]] = None
not_: Optional[List[Any]] = Field(None, alias="not")
not_: Optional[Any] = Field(None, alias="not")
items: Optional[Any] = None
properties: Optional[Dict[str, Any]] = None
additionalProperties: Optional[Union[Dict[str, Any], bool]] = None
@@ -133,7 +133,7 @@ class Schema(SchemaBase):
allOf: Optional[List[SchemaBase]] = None
oneOf: Optional[List[SchemaBase]] = None
anyOf: Optional[List[SchemaBase]] = None
not_: Optional[List[SchemaBase]] = Field(None, alias="not")
not_: Optional[SchemaBase] = Field(None, alias="not")
items: Optional[SchemaBase] = None
properties: Optional[Dict[str, SchemaBase]] = None
additionalProperties: Optional[Union[Dict[str, Any], bool]] = None

View File

@@ -1,9 +1,10 @@
import http.client
from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, cast
from enum import Enum
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
from fastapi import routing
from fastapi.dependencies.models import Dependant
from fastapi.dependencies.utils import get_flat_dependant
from fastapi.dependencies.utils import get_flat_dependant, get_flat_params
from fastapi.encoders import jsonable_encoder
from fastapi.openapi.constants import (
METHODS_WITH_BODY,
@@ -13,13 +14,17 @@ from fastapi.openapi.constants import (
from fastapi.openapi.models import OpenAPI
from fastapi.params import Body, Param
from fastapi.utils import (
deep_dict_update,
generate_operation_id_for_path,
get_field_info,
get_flat_models_from_routes,
get_model_definitions,
)
from pydantic import BaseModel
from pydantic.schema import field_schema, get_model_name_map
from pydantic.schema import (
field_schema,
get_flat_models_from_fields,
get_model_name_map,
)
from pydantic.utils import lenient_issubclass
from starlette.responses import JSONResponse
from starlette.routing import BaseRoute
@@ -64,16 +69,6 @@ status_code_ranges: Dict[str, str] = {
}
def get_openapi_params(dependant: Dependant) -> List[ModelField]:
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
return (
flat_dependant.path_params
+ flat_dependant.query_params
+ flat_dependant.header_params
+ flat_dependant.cookie_params
)
def get_openapi_security_definitions(flat_dependant: Dependant) -> Tuple[Dict, List]:
security_definitions = {}
operation_security = []
@@ -90,17 +85,22 @@ def get_openapi_security_definitions(flat_dependant: Dependant) -> Tuple[Dict, L
def get_openapi_operation_parameters(
*,
all_route_params: Sequence[ModelField],
model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str],
) -> List[Dict[str, Any]]:
parameters = []
for param in all_route_params:
field_info = get_field_info(param)
field_info = cast(Param, field_info)
# ignore mypy error until enum schemas are released
parameter = {
"name": param.alias,
"in": field_info.in_.value,
"required": param.required,
"schema": field_schema(param, model_name_map={})[0],
"schema": field_schema(
param, model_name_map=model_name_map, ref_prefix=REF_PREFIX # type: ignore
)[0],
}
if field_info.description:
parameter["description"] = field_info.description
@@ -111,13 +111,16 @@ def get_openapi_operation_parameters(
def get_openapi_operation_request_body(
*, body_field: Optional[ModelField], model_name_map: Dict[Type[BaseModel], str]
*,
body_field: Optional[ModelField],
model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str],
) -> Optional[Dict]:
if not body_field:
return None
assert isinstance(body_field, ModelField)
# ignore mypy error until enum schemas are released
body_schema, _, _ = field_schema(
body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
body_field, model_name_map=model_name_map, ref_prefix=REF_PREFIX # type: ignore
)
field_info = cast(Body, get_field_info(body_field))
request_media_type = field_info.media_type
@@ -176,8 +179,10 @@ def get_openapi_path(
operation.setdefault("security", []).extend(operation_security)
if security_definitions:
security_schemes.update(security_definitions)
all_route_params = get_openapi_params(route.dependant)
operation_parameters = get_openapi_operation_parameters(all_route_params)
all_route_params = get_flat_params(route.dependant)
operation_parameters = get_openapi_operation_parameters(
all_route_params=all_route_params, model_name_map=model_name_map
)
parameters.extend(operation_parameters)
if parameters:
operation["parameters"] = list(
@@ -197,29 +202,6 @@ def get_openapi_path(
)
callbacks[callback.name] = {callback.path: cb_path}
operation["callbacks"] = callbacks
if route.responses:
for (additional_status_code, response) in route.responses.items():
assert isinstance(
response, dict
), "An additional response must be a dict"
field = route.response_fields.get(additional_status_code)
if field:
response_schema, _, _ = field_schema(
field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
)
response.setdefault("content", {}).setdefault(
route_response_media_type or "application/json", {}
)["schema"] = response_schema
status_text: Optional[str] = status_code_ranges.get(
str(additional_status_code).upper()
) or http.client.responses.get(int(additional_status_code))
response.setdefault(
"description", status_text or "Additional Response"
)
status_code_key = str(additional_status_code).upper()
if status_code_key == "DEFAULT":
status_code_key = "default"
operation.setdefault("responses", {})[status_code_key] = response
status_code = str(route.status_code)
operation.setdefault("responses", {}).setdefault(status_code, {})[
"description"
@@ -243,7 +225,47 @@ def get_openapi_path(
).setdefault("content", {}).setdefault(route_response_media_type, {})[
"schema"
] = response_schema
if route.responses:
operation_responses = operation.setdefault("responses", {})
for (
additional_status_code,
additional_response,
) in route.responses.items():
process_response = additional_response.copy()
process_response.pop("model", None)
status_code_key = str(additional_status_code).upper()
if status_code_key == "DEFAULT":
status_code_key = "default"
openapi_response = operation_responses.setdefault(
status_code_key, {}
)
assert isinstance(
process_response, dict
), "An additional response must be a dict"
field = route.response_fields.get(additional_status_code)
additional_field_schema: Optional[Dict[str, Any]] = None
if field:
additional_field_schema, _, _ = field_schema(
field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
)
media_type = route_response_media_type or "application/json"
additional_schema = (
process_response.setdefault("content", {})
.setdefault(media_type, {})
.setdefault("schema", {})
)
deep_dict_update(additional_schema, additional_field_schema)
status_text: Optional[str] = status_code_ranges.get(
str(additional_status_code).upper()
) or http.client.responses.get(int(additional_status_code))
description = (
process_response.get("description")
or openapi_response.get("description")
or status_text
or "Additional Response"
)
deep_dict_update(openapi_response, process_response)
openapi_response["description"] = description
http422 = str(HTTP_422_UNPROCESSABLE_ENTITY)
if (all_route_params or route.body_field) and not any(
[
@@ -270,6 +292,38 @@ def get_openapi_path(
return path, security_schemes, definitions
def get_flat_models_from_routes(
routes: Sequence[BaseRoute],
) -> Set[Union[Type[BaseModel], Type[Enum]]]:
body_fields_from_routes: List[ModelField] = []
responses_from_routes: List[ModelField] = []
request_fields_from_routes: List[ModelField] = []
callback_flat_models: Set[Union[Type[BaseModel], Type[Enum]]] = set()
for route in routes:
if getattr(route, "include_in_schema", None) and isinstance(
route, routing.APIRoute
):
if route.body_field:
assert isinstance(
route.body_field, ModelField
), "A request body must be a Pydantic Field"
body_fields_from_routes.append(route.body_field)
if route.response_field:
responses_from_routes.append(route.response_field)
if route.response_fields:
responses_from_routes.extend(route.response_fields.values())
if route.callbacks:
callback_flat_models |= get_flat_models_from_routes(route.callbacks)
params = get_flat_params(route.dependant)
request_fields_from_routes.extend(params)
flat_models = callback_flat_models | get_flat_models_from_fields(
body_fields_from_routes + responses_from_routes + request_fields_from_routes,
known_models=set(),
)
return flat_models
def get_openapi(
*,
title: str,
@@ -277,18 +331,24 @@ def get_openapi(
openapi_version: str = "3.0.2",
description: str = None,
routes: Sequence[BaseRoute],
openapi_prefix: str = ""
openapi_prefix: str = "",
tags: Optional[List[Dict[str, Any]]] = None,
servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
) -> Dict:
info = {"title": title, "version": version}
if description:
info["description"] = description
output = {"openapi": openapi_version, "info": info}
output: Dict[str, Any] = {"openapi": openapi_version, "info": info}
if servers:
output["servers"] = servers
components: Dict[str, Dict] = {}
paths: Dict[str, Dict] = {}
flat_models = get_flat_models_from_routes(routes)
model_name_map = get_model_name_map(flat_models)
# ignore mypy error until enum schemas are released
model_name_map = get_model_name_map(flat_models) # type: ignore
# ignore mypy error until enum schemas are released
definitions = get_model_definitions(
flat_models=flat_models, model_name_map=model_name_map
flat_models=flat_models, model_name_map=model_name_map # type: ignore
)
for route in routes:
if isinstance(route, routing.APIRoute):
@@ -310,4 +370,6 @@ def get_openapi(
if components:
output["components"] = components
output["paths"] = paths
if tags:
output["tags"] = tags
return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True)

View File

@@ -51,6 +51,9 @@ class Param(FieldInfo):
**extra,
)
def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.default})"
class Path(Param):
in_ = ParamTypes.path
@@ -239,6 +242,9 @@ class Body(FieldInfo):
**extra,
)
def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.default})"
class Form(Body):
def __init__(
@@ -316,6 +322,11 @@ class Depends:
self.dependency = dependency
self.use_cache = use_cache
def __repr__(self) -> str:
attr = getattr(self.dependency, "__name__", type(self.dependency).__name__)
cache = "" if self.use_cache else ", use_cache=False"
return f"{self.__class__.__name__}({attr}{cache})"
class Security(Depends):
def __init__(

Some files were not shown because too many files have changed in this diff Show More