mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-25 07:08:11 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf53518141 | ||
|
|
0ed55eb7d3 | ||
|
|
12e087f0b5 | ||
|
|
ba10838c30 | ||
|
|
656e1c7ce9 | ||
|
|
88b31e6a4d | ||
|
|
2c3b826810 | ||
|
|
aa64eecda6 | ||
|
|
712b18a58a | ||
|
|
a809da5567 | ||
|
|
80b68cd97d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@ site
|
||||
.coverage
|
||||
coverage.xml
|
||||
.netlify
|
||||
test.db
|
||||
|
||||
2
Pipfile
2
Pipfile
@@ -24,7 +24,7 @@ python-multipart = "*"
|
||||
sqlalchemy = "*"
|
||||
|
||||
[packages]
|
||||
starlette = "==0.10.1"
|
||||
starlette = "==0.11.1"
|
||||
pydantic = "==0.18.2"
|
||||
|
||||
[requires]
|
||||
|
||||
79
Pipfile.lock
generated
79
Pipfile.lock
generated
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "37b34bb892b6b4dc0f7c941434d0e08199aa7a7ca83efb6294b89ace44168bba"
|
||||
"sha256": "6b55a2dcce8b6bd5a1be8f170acb18478149218a01d1b026981a6297800cd3fa"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@@ -34,10 +34,10 @@
|
||||
},
|
||||
"starlette": {
|
||||
"hashes": [
|
||||
"sha256:7cc05c33d00db3b2ddfd7516a737544ed0a34c9dd0ced94076f29b581ce4f532"
|
||||
"sha256:9d48b35d1fc7521d59ae53c421297ab3878d3c7cd4b75266d77f6c73cccb78bb"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.10.1"
|
||||
"version": "==0.11.1"
|
||||
}
|
||||
},
|
||||
"develop": {
|
||||
@@ -199,11 +199,11 @@
|
||||
},
|
||||
"flake8": {
|
||||
"hashes": [
|
||||
"sha256:c3ba1e130c813191db95c431a18cb4d20a468e98af7a77e2181b68574481ad36",
|
||||
"sha256:fd9ddf503110bf3d8b1d270e8c673aab29ccb3dd6abf29bae1f54e5116ab4a91"
|
||||
"sha256:6d8c66a65635d46d54de59b027a1dda40abbe2275b3164b634835ac9c13fd048",
|
||||
"sha256:6eab21c6e34df2c05416faa40d0c59963008fff29b6f0ccfe8fa28152ab3e383"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.7.5"
|
||||
"version": "==3.7.6"
|
||||
},
|
||||
"flit": {
|
||||
"hashes": [
|
||||
@@ -229,11 +229,11 @@
|
||||
},
|
||||
"ipython": {
|
||||
"hashes": [
|
||||
"sha256:6a9496209b76463f1dec126ab928919aaf1f55b38beb9219af3fe202f6bbdd12",
|
||||
"sha256:f69932b1e806b38a7818d9a1e918e5821b685715040b48e59c657b3c7961b742"
|
||||
"sha256:06de667a9e406924f97781bda22d5d76bfb39762b678762d86a466e63f65dc39",
|
||||
"sha256:5d3e020a6b5f29df037555e5c45ab1088d6a7cf3bd84f47e0ba501eeb0c3ec82"
|
||||
],
|
||||
"markers": "python_version >= '3.3'",
|
||||
"version": "==7.2.0"
|
||||
"version": "==7.3.0"
|
||||
},
|
||||
"ipython-genutils": {
|
||||
"hashes": [
|
||||
@@ -387,17 +387,18 @@
|
||||
},
|
||||
"mkdocs-material": {
|
||||
"hashes": [
|
||||
"sha256:4b4af83c704d2bab41be3a5228e800a5e1157003368fbf548d95073ce19e0f61",
|
||||
"sha256:86c0042c803586985bf79c99962ebd4644c3f0ff095d5df541f09fa48f5b62cc"
|
||||
"sha256:63c49a7020e5d187d5adcd441b259e0b81ad418599b22e2c2574b419ed833851",
|
||||
"sha256:90a240f268f182a96098490d35bb75d5efc86b2f67d63a82b8750da20a72ef60"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.3.0"
|
||||
"version": "==4.0.1"
|
||||
},
|
||||
"more-itertools": {
|
||||
"hashes": [
|
||||
"sha256:0125e8f60e9e031347105eb1682cef932f5e97d7b9a1a28d9bf00c22a5daef40",
|
||||
"sha256:590044e3942351a1bdb1de960b739ff4ce277960f2425ad4509446dbace8d9d1"
|
||||
],
|
||||
"markers": "python_version > '2.7'",
|
||||
"version": "==6.0.0"
|
||||
},
|
||||
"mypy": {
|
||||
@@ -444,10 +445,10 @@
|
||||
},
|
||||
"parso": {
|
||||
"hashes": [
|
||||
"sha256:6ecf7244be8e7283ec9009c72d074830e7e0e611c974f813d76db0390a4e0dd6",
|
||||
"sha256:8162be7570ffb34ec0b8d215d7f3b6c5fab24f51eb3886d6dee362de96b6db94"
|
||||
"sha256:4580328ae3f548b358f4901e38c0578229186835f0fa0846e47369796dd5bcc9",
|
||||
"sha256:68406ebd7eafe17f8e40e15a84b56848eccbf27d7c1feb89e93d8fca395706db"
|
||||
],
|
||||
"version": "==0.3.3"
|
||||
"version": "==0.3.4"
|
||||
},
|
||||
"pexpect": {
|
||||
"hashes": [
|
||||
@@ -536,11 +537,11 @@
|
||||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:65aeaa77ae87c7fc95de56285282546cfa9c886dc8e5dc78313db1c25e21bc07",
|
||||
"sha256:6ac6d467d9f053e95aaacd79f831dbecfe730f419c6c7022cb316b365cd9199d"
|
||||
"sha256:067a1d4bf827ffdd56ad21bd46674703fce77c5957f6c1eef731f6146bfcef1c",
|
||||
"sha256:9687049d53695ad45cf5fdc7bbd51f0c49f1ea3ecfc4b7f3fde7501b541f17f4"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.2.0"
|
||||
"version": "==4.3.0"
|
||||
},
|
||||
"pytest-cov": {
|
||||
"hashes": [
|
||||
@@ -582,33 +583,23 @@
|
||||
},
|
||||
"pyzmq": {
|
||||
"hashes": [
|
||||
"sha256:25a0715c8f69cf72f67cfe5a68a3f3ed391c67c063d2257bec0fe7fc2c7f08f8",
|
||||
"sha256:2bab63759632c6b9e0d5bf19cc63c3b01df267d660e0abcf230cf0afaa966349",
|
||||
"sha256:30ab49d99b24bf0908ebe1cdfa421720bfab6f93174e4883075b7ff38cc555ba",
|
||||
"sha256:32c7ca9fc547a91e3c26fc6080b6982e46e79819e706eb414dd78f635a65d946",
|
||||
"sha256:41219ae72b3cc86d97557fe5b1ef5d1adc1057292ec597b50050874a970a39cf",
|
||||
"sha256:4b8c48a9a13cea8f1f16622f9bd46127108af14cd26150461e3eab71e0de3e46",
|
||||
"sha256:55724997b4a929c0d01b43c95051318e26ddbae23565018e138ae2dc60187e59",
|
||||
"sha256:65f0a4afae59d4fc0aad54a917ab599162613a761b760ba167d66cc646ac3786",
|
||||
"sha256:6f88591a8b246f5c285ee6ce5c1bf4f6bd8464b7f090b1333a446b6240a68d40",
|
||||
"sha256:75022a4c60dcd8765bb9ca32f6de75a0ec83b0d96e0309dc479f4c7b21f26cb7",
|
||||
"sha256:76ea493bfab18dcb090d825f3662b5612e2def73dffc196d51a5194b0294a81d",
|
||||
"sha256:7b60c045b80709e4e3c085bab9b691e71761b44c2b42dbb047b8b498e7bc16b3",
|
||||
"sha256:8e6af2f736734aef8ed6f278f9f552ec7f37b1a6b98e59b887484a840757f67d",
|
||||
"sha256:9ac2298e486524331e26390eac14e4627effd3f8e001d4266ed9d8f1d2d31cce",
|
||||
"sha256:9ba650f493a9bc1f24feca1d90fce0e5dd41088a252ac9840131dfbdbf3815ca",
|
||||
"sha256:a02a4a385e394e46012dc83d2e8fd6523f039bb52997c1c34a2e0dd49ed839c1",
|
||||
"sha256:a3ceee84114d9f5711fa0f4db9c652af0e4636c89eabc9b7f03a3882569dd1ed",
|
||||
"sha256:a72b82ac1910f2cf61a49139f4974f994984475f771b0faa730839607eeedddf",
|
||||
"sha256:ab136ac51027e7c484c53138a0fab4a8a51e80d05162eb7b1585583bcfdbad27",
|
||||
"sha256:c095b224300bcac61e6c445e27f9046981b1ac20d891b2f1714da89d34c637c8",
|
||||
"sha256:c5cc52d16c06dc2521340d69adda78a8e1031705924e103c0eb8fc8af861d810",
|
||||
"sha256:d612e9833a89e8177f8c1dc68d7b4ff98d3186cd331acd616b01bbdab67d3a7b",
|
||||
"sha256:e828376a23c66c6fe90dcea24b4b72cd774f555a6ee94081670872918df87a19",
|
||||
"sha256:e9767c7ab2eb552796440168d5c6e23a99ecaade08dda16266d43ad461730192",
|
||||
"sha256:ebf8b800d42d217e4710d1582b0c8bff20cdcb4faad7c7213e52644034300924"
|
||||
"sha256:15f0bf7cd80020f165635595e197603aedb37fddf4164ad5ae226afc43242f7b",
|
||||
"sha256:1756dc72e192c670490e38c788c3a35f901adc74ee436e5131d5a3e85fdd7dc6",
|
||||
"sha256:1d1eb490da54679d724b08ef3ee04530849023670c4ba7e400ed2cdf906720c4",
|
||||
"sha256:228402625796821f08706f58cc42a3c51c9897d723550babaefe4feec2b6dacc",
|
||||
"sha256:3928534fa00a2aabfcfdb439c08ba37fbe99ab0cf57776c8db8d2b73a51693ba",
|
||||
"sha256:3d2a295b1086d450981f73d3561ac204a0cc9c8ded386a4a34327d918f3b1d0a",
|
||||
"sha256:4fd8621a309db6ec23ef1369f43cdf7a9b0dc217d8ff9ca4095a6e932b379bda",
|
||||
"sha256:54fe55a1694ffe608c8e4c5183e83cab7a91f3e5c84bd6f188868d6676c12aba",
|
||||
"sha256:618887be4ad754228c0cbba7631f6574608b4430fe93974e6322324f1304fdac",
|
||||
"sha256:69130efb6efa936de601cb135a8a4eec1caccd4ea2b784237145ff4075c2d3ae",
|
||||
"sha256:6e7f78eeac82140bde7e60e975c6e6b1b678a4dd377782ab63319c1c78bf3aa1",
|
||||
"sha256:6ee760cdb84e43574da6b3f2f1fc1251e8acf87253900d28a06451c5f5de39e9",
|
||||
"sha256:97cb1b7cd2c46e87b0a26651eccd2bbb8c758035efd1635ebb81ac36aa76a88c",
|
||||
"sha256:abfa774dbadacc849121ed92eae05189d226daab583388b499472e1bbb17ef69",
|
||||
"sha256:b30c339eb58355f51f4f54dd61d785f1ff58c86bca1c3a5916977631d121867b"
|
||||
],
|
||||
"version": "==17.1.2"
|
||||
"version": "==18.0.0"
|
||||
},
|
||||
"qtconsole": {
|
||||
"hashes": [
|
||||
|
||||
123
docs/contributing.md
Normal file
123
docs/contributing.md
Normal file
@@ -0,0 +1,123 @@
|
||||
First, you might want to see the basic ways to <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">help FastAPI and get help</a>.
|
||||
|
||||
## Developing
|
||||
|
||||
If you already cloned the repository and you know that you need to deep dive in the code, here are some guidelines to set up your environment.
|
||||
|
||||
|
||||
### Pipenv
|
||||
|
||||
If you are using <a href="https://pipenv.readthedocs.io/en/latest/" target="_blank">Pipenv</a>, you can create a virtual environment and install the packages with:
|
||||
|
||||
```bash
|
||||
pipenv install --dev
|
||||
```
|
||||
|
||||
Then you can activate that virtual environment with:
|
||||
|
||||
```bash
|
||||
pipenv shell
|
||||
```
|
||||
|
||||
|
||||
### No Pipenv
|
||||
|
||||
If you are not using Pipenv, you can create a virtual environment with your preferred tool, and install the packages listed in the file `Pipfile`.
|
||||
|
||||
|
||||
### Flit
|
||||
|
||||
**FastAPI** uses <a href="https://flit.readthedocs.io/en/latest/index.html" target="_blank">Flit</a> to build, package and publish the project.
|
||||
|
||||
If you installed the development dependencies with one of the methods above, you already have the `flit` command.
|
||||
|
||||
To install your local version of FastAPI as a package in your local environment, run:
|
||||
|
||||
```bash
|
||||
flit install --symlink
|
||||
```
|
||||
|
||||
It will install your local FastAPI in your local environment.
|
||||
|
||||
|
||||
#### Using your local FastAPI
|
||||
|
||||
If you create a Python file that imports and uses FastAPI, and run it with the Python from your local environment, it will use your local FastAPI source code.
|
||||
|
||||
And if you update that local FastAPI source code, as it is installed with `--symlink`, when you run that Python file again, it will use the fresh version of FastAPI you just edited.
|
||||
|
||||
That way, you don't have to "install" your local version to be able to test every change.
|
||||
|
||||
|
||||
### Format
|
||||
|
||||
There is a script that you can run that will format and clean all your code:
|
||||
|
||||
```bash
|
||||
bash scripts/lint.sh
|
||||
```
|
||||
|
||||
It will also auto-sort all your imports.
|
||||
|
||||
For it to sort them correctly, you need to have FastAPI installed locally in your environment, with the command in the section above:
|
||||
|
||||
```bash
|
||||
flit install --symlink
|
||||
```
|
||||
|
||||
|
||||
### Docs
|
||||
|
||||
The documentation uses <a href="https://www.mkdocs.org/" target="_blank">MkDocs</a>.
|
||||
|
||||
All the documentation is in Markdown format in the directory `./docs`.
|
||||
|
||||
Many of the tutorials have blocks of code.
|
||||
|
||||
In most of the cases, these blocks of code are actual complete applicactions that can be run as is.
|
||||
|
||||
In fact, those blocks of code are not written inside the Markdown, they are Python files in the `./docs/src/` directory.
|
||||
|
||||
And those Python files are included/injected in the documentation when generating the site.
|
||||
|
||||
|
||||
#### Docs for tests
|
||||
|
||||
Most of the tests actually run against the example source files in the documentation.
|
||||
|
||||
This helps making sure that:
|
||||
|
||||
* The documentation is up to date.
|
||||
* The documentation examples can be run as is.
|
||||
* Most of the features are covered by the documentation, ensured by the coverage tests.
|
||||
|
||||
During local development, there is a script that builds the site and checks for any changes, live-reloading:
|
||||
|
||||
```bash
|
||||
bash scripts/docs-live.sh
|
||||
```
|
||||
|
||||
It will serve the documentation on `http://0.0.0.0:8008`.
|
||||
|
||||
That way, you can edit the documentation/source files and see the changes live.
|
||||
|
||||
#### Apps and docs at the same time
|
||||
|
||||
And if you run the examples with, e.g.:
|
||||
|
||||
```bash
|
||||
uvicorn tutorial001:app --debug
|
||||
```
|
||||
|
||||
as Uvicorn by default will use the port `8000`, the documentation on port `8008` won't clash.
|
||||
|
||||
|
||||
### Tests
|
||||
|
||||
There is a script that you can run locally to test all the code and generate coverage reports in HTML:
|
||||
|
||||
```bash
|
||||
bash scripts/test-cov-html.sh
|
||||
```
|
||||
|
||||
This command generates a directory `./htmlcov/`, if you open the file `./htmlcov/index.html` in your browser, you can explore interactively the regions of code that are covered by the tests, and notice if there is any region missing.
|
||||
100
docs/help-fastapi.md
Normal file
100
docs/help-fastapi.md
Normal file
@@ -0,0 +1,100 @@
|
||||
Are you liking **FastAPI**?
|
||||
|
||||
Would you like to help FastAPI, other users, and the author?
|
||||
|
||||
Or would you like to get help with **FastAPI**?
|
||||
|
||||
There are very simple ways to help (several involve just one or two clicks).
|
||||
|
||||
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" 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" 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.
|
||||
|
||||
|
||||
## Connect with the author
|
||||
|
||||
You can connect with me (Sebastián Ramírez / `tiangolo`), the author.
|
||||
|
||||
You can:
|
||||
|
||||
* <a href="https://github.com/tiangolo" target="_blank">Follow me on **GitHub**</a>.
|
||||
* See other Open Source projects I have created that could help you.
|
||||
* Follow me to see when I create a new Open Source project.
|
||||
* <a href="https://twitter.com/tiangolo" target="_blank">Follow me on **Twitter**</a>.
|
||||
* Tell me how you use FastAPI (I love to hear that).
|
||||
* Ask questions.
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" target="_blank">Connect with me on **Linkedin**</a>.
|
||||
* Talk to me.
|
||||
* Endorse me or recommend me :)
|
||||
* <a href="https://medium.com/@tiangolo" 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.
|
||||
|
||||
|
||||
## Tweet about **FastAPI**
|
||||
|
||||
<a href="http://twitter.com/home/?status=I'm loving FastAPI because... https://github.com/tiangolo/fastapi cc @tiangolo" target="_blank">Tweet about **FastAPI**</a> and let me and others why you like it.
|
||||
|
||||
## Let me know how are you using **FastAPI**
|
||||
|
||||
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="http://twitter.com/home/?status=Hey @tiangolo, I'm using FastAPI at..." target="_blank">On **Twitter**</a>.
|
||||
* <a href="https://www.linkedin.com/in/tiangolo/" target="_blank">On **Linkedin**</a>.
|
||||
* <a href="https://medium.com/@tiangolo" target="_blank">On **Medium**</a>.
|
||||
|
||||
## Vote for FastAPI
|
||||
|
||||
You can vote to include FastAPI in several "awesome lists":
|
||||
|
||||
* <a href="https://github.com/vinta/awesome-python/pull/1209" target="_blank">Vote to include **FastAPI** in `awesome-python`</a>.
|
||||
* <a href="https://github.com/timofurrer/awesome-asyncio/pull/43" target="_blank">Vote to include **FastAPI** in `awesome-asyncio`</a>.
|
||||
|
||||
## Help others with issues in GitHub
|
||||
|
||||
You can see <a href="https://github.com/tiangolo/fastapi/issues" target="_blank">existing issues</a> and try and help others.
|
||||
|
||||
## 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" 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.
|
||||
|
||||
Then you can try and help them solving those issues.
|
||||
|
||||
## Create issues
|
||||
|
||||
You can <a href="https://github.com/tiangolo/fastapi/issues/new/choose" target="_blank">create a new issue</a> in the GitHub repository, for example to:
|
||||
|
||||
* Report a bug/issue.
|
||||
* Suggest a new feature.
|
||||
* Ask a question.
|
||||
|
||||
## Create a Pull Request
|
||||
|
||||
You can <a href="https://github.com/tiangolo/fastapi" target="_blank">create a Pull Request</a>, for example:
|
||||
|
||||
* To fix a typo you found on the documentation.
|
||||
* To propose new documentation sections.
|
||||
* To fix an existing issue/bug.
|
||||
* To add a new feature.
|
||||
|
||||
---
|
||||
|
||||
Thanks!
|
||||
@@ -1,5 +1,21 @@
|
||||
## Next
|
||||
|
||||
## 0.6.0
|
||||
|
||||
* Update SQL with SQLAlchemy tutorial at <a href="https://fastapi.tiangolo.com/tutorial/sql-databases/" target="_blank">https://fastapi.tiangolo.com/tutorial/sql-databases/</a> using the new official `request.state`. PR <a href="https://github.com/tiangolo/fastapi/pull/45" target="_blank">#45</a>.
|
||||
|
||||
* Upgrade Starlette to version `0.11.1` and add required compatibility changes. PR <a href="https://github.com/tiangolo/fastapi/pull/44" target="_blank">#44</a>.
|
||||
|
||||
## 0.5.1
|
||||
|
||||
* Add section about <a href="https://fastapi.tiangolo.com/help-fastapi/" target="_blank">helping and getting help with **FastAPI**</a>.
|
||||
|
||||
* Add note about <a href="https://fastapi.tiangolo.com/tutorial/path-params/#order-matters" target="_blank">path operations order in docs</a>.
|
||||
|
||||
* Update <a href="https://fastapi.tiangolo.com/tutorial/handling-errors/" target="_blank">section about error handling</a> with more information and make relation with Starlette error handling utilities more explicit. PR <a href="https://github.com/tiangolo/fastapi/pull/41" target="_blank">#41</a>.
|
||||
|
||||
* Add <a href="" target="_blank">Development - Contributing section to the docs</a>. PR <a href="https://github.com/tiangolo/fastapi/pull/42" target="_blank">#42</a>.
|
||||
|
||||
## 0.5.0
|
||||
|
||||
* Add new `HTTPException` with support for custom headers. With new documentation for handling errors at: <a href="https://fastapi.tiangolo.com/tutorial/handling-errors/" target="_blank">https://fastapi.tiangolo.com/tutorial/handling-errors/</a>. PR <a href="https://github.com/tiangolo/fastapi/pull/35" target="_blank">#35</a>.
|
||||
|
||||
15
docs/src/handling_errors/tutorial003.py
Normal file
15
docs/src/handling_errors/tutorial003.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.responses import PlainTextResponse
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.exception_handler(HTTPException)
|
||||
async def http_exception(request, exc):
|
||||
return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return {"message": "Hello World"}
|
||||
@@ -1,10 +1,13 @@
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: UUID):
|
||||
return {"item_id": item_id}
|
||||
@app.get("/users/me")
|
||||
async def read_user_me():
|
||||
return {"user_id": "the current user"}
|
||||
|
||||
|
||||
@app.get("/users/{user_id}")
|
||||
async def read_user(user_id: str):
|
||||
return {"user_id": user_id}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, FastAPI, Security, HTTPException
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
from jwt import PyJWTError
|
||||
from passlib.context import CryptContext
|
||||
|
||||
@@ -55,13 +55,13 @@ app = FastAPI()
|
||||
|
||||
@app.get("/users/{user_id}")
|
||||
def read_user(request: Request, user_id: int):
|
||||
user = get_user(request._scope["db"], user_id=user_id)
|
||||
user = get_user(request.state.db, user_id=user_id)
|
||||
return user
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def close_db(request, call_next):
|
||||
request._scope["db"] = Session()
|
||||
async def close_db(request: Request, call_next):
|
||||
request.state.db = Session()
|
||||
response = await call_next(request)
|
||||
request._scope["db"].close()
|
||||
request.state.db.close()
|
||||
return response
|
||||
|
||||
@@ -43,6 +43,31 @@ In this example, when the client request an item by an ID that doesn't exist, ra
|
||||
{!./src/handling_errors/tutorial001.py!}
|
||||
```
|
||||
|
||||
### The resulting response
|
||||
|
||||
If the client requests `http://example.com/items/foo` (an `item_id` `"foo"`), he will receive an HTTP status code of 200, and a JSON response of:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item": "The Foo Wrestlers"
|
||||
}
|
||||
```
|
||||
|
||||
But if the client requests `http://example.com/items/bar` (a non-existent `item_id` `"bar"`), he will receive an HTTP status code of 404 (the "not found" error), and a JSON response of:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"detail": "Item not found"
|
||||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
When raising an `HTTPException`, you can pass any value that can be converted to JSON as the parameter `detail`, not only `str`.
|
||||
|
||||
You could pass a `dict`, a `list`, etc.
|
||||
|
||||
They are handled automatically by **FastAPI** and converted to JSON.
|
||||
|
||||
### Adding custom headers
|
||||
|
||||
There are some situations in where it's useful to be able to add custom headers to the HTTP error. For example, for some types of security.
|
||||
@@ -55,3 +80,20 @@ But in case you needed it for an advanced scenario, you can add custom headers:
|
||||
```Python hl_lines="14"
|
||||
{!./src/handling_errors/tutorial002.py!}
|
||||
```
|
||||
|
||||
### Installing custom handlers
|
||||
|
||||
If you need to add other custom exception handlers, or override the default one (that sends the errors as JSON), you can use <a href="https://www.starlette.io/exceptions/" target="_blank">the same exception utilities from Starlette</a>.
|
||||
|
||||
For example, you could override the default exception handler with:
|
||||
|
||||
```Python hl_lines="2 3 8 9 10"
|
||||
{!./src/handling_errors/tutorial003.py!}
|
||||
```
|
||||
|
||||
...this would make it return "plain text" responses with the errors, instead of JSON responses.
|
||||
|
||||
!!! info
|
||||
Note that in this example we set the exception handler with Starlette's `HTTPException` instead of FastAPI's `HTTPException`.
|
||||
|
||||
This would ensure that if you use a plug-in or any other third-party tool that raises Starlette's `HTTPException` directly, it will be catched by your exception handler.
|
||||
|
||||
@@ -98,6 +98,24 @@ You can use the same type declarations with `str`, `float`, `bool` and many othe
|
||||
|
||||
These are explored in the next chapters of the tutorial.
|
||||
|
||||
|
||||
## Order matters
|
||||
|
||||
When creating *path operations*, you can find situations where you have a fixed path.
|
||||
|
||||
Like `/users/me`, let's say that it's to get data about the current user.
|
||||
|
||||
And then you can also have a path `/users/{user_id}` to get data about a specific user by some user ID.
|
||||
|
||||
Because path operations are evaluated in order, you need to make sure that the path for `/users/me` is declared before the one for `/users/{user_id}`:
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!./src/path_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
Otherwise, the path for `/users/{user_id}` would match also for `/users/me`, "thinking" that it's receiving a parameter `user_id` with a value of `"me"`.
|
||||
|
||||
|
||||
## Recap
|
||||
|
||||
With **FastAPI**, by using short, intuitive and standard Python type declarations, you get:
|
||||
|
||||
@@ -102,15 +102,12 @@ The middleware we will create (just a function) will create a new SQLAlchemy `Se
|
||||
{!./src/sql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
### About `request._scope`
|
||||
### About `request.state`
|
||||
|
||||
`request._scope` is a "private property" of each request. We normally shouldn't need to use a "private property" from a Python object.
|
||||
<a href="https://www.starlette.io/requests/#other-state" target="_blank">`request.state` is a property of each Starlette `Request` object</a>, it is there to store arbitrary objects attached to the request itself, like the database session in this case.
|
||||
|
||||
But we need to attach the session to the request to be able to ensure a single session/database-connection is used through all the request, and then closed afterwards.
|
||||
For us in this case, it helps us ensuring a single session/database-connection is used through all the request, and then closed afterwards (in the middleware).
|
||||
|
||||
In the near future, Starlette <a href="https://github.com/encode/starlette/issues/379" target="_blank">will have a way to attach custom objects to each request</a>.
|
||||
|
||||
When that happens, this tutorial will be updated to use the new official way of doing it.
|
||||
|
||||
## Create a `CustomBase` model
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.5.0"
|
||||
__version__ = "0.6.0"
|
||||
|
||||
from .applications import FastAPI
|
||||
from .routing import APIRouter
|
||||
|
||||
@@ -7,9 +7,9 @@ from pydantic import BaseModel
|
||||
from starlette.applications import Starlette
|
||||
from starlette.exceptions import ExceptionMiddleware, HTTPException
|
||||
from starlette.middleware.errors import ServerErrorMiddleware
|
||||
from starlette.middleware.lifespan import LifespanMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
|
||||
|
||||
async def http_exception(request: Request, exc: HTTPException) -> JSONResponse:
|
||||
@@ -26,6 +26,7 @@ class FastAPI(Starlette):
|
||||
def __init__(
|
||||
self,
|
||||
debug: bool = False,
|
||||
routes: List[BaseRoute] = None,
|
||||
template_directory: str = None,
|
||||
title: str = "Fast API",
|
||||
description: str = "",
|
||||
@@ -37,14 +38,11 @@ class FastAPI(Starlette):
|
||||
**extra: Dict[str, Any],
|
||||
) -> None:
|
||||
self._debug = debug
|
||||
self.router: routing.APIRouter = routing.APIRouter()
|
||||
self.router: routing.APIRouter = routing.APIRouter(routes)
|
||||
self.exception_middleware = ExceptionMiddleware(self.router, debug=debug)
|
||||
self.error_middleware = ServerErrorMiddleware(
|
||||
self.exception_middleware, debug=debug
|
||||
)
|
||||
self.lifespan_middleware = LifespanMiddleware(self.error_middleware)
|
||||
self.schema_generator = None
|
||||
self.template_env = self.load_template_env(template_directory)
|
||||
|
||||
self.title = title
|
||||
self.description = description
|
||||
|
||||
@@ -66,6 +66,8 @@ nav:
|
||||
- Project Generation - Template: 'project-generation.md'
|
||||
- Alternatives, Inspiration and Comparisons: 'alternatives.md'
|
||||
- Benchmarks: 'benchmarks.md'
|
||||
- Help FastAPI - Get Help: 'help-fastapi.md'
|
||||
- Development - Contributing: 'contributing.md'
|
||||
- Release Notes: release-notes.md
|
||||
|
||||
markdown_extensions:
|
||||
|
||||
@@ -19,7 +19,7 @@ classifiers = [
|
||||
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
||||
]
|
||||
requires = [
|
||||
"starlette >=0.9.11,<=0.10.1",
|
||||
"starlette ==0.11.1",
|
||||
"pydantic >=0.17,<=0.18.2"
|
||||
]
|
||||
description-file = "README.md"
|
||||
|
||||
Reference in New Issue
Block a user