mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-26 15:51:02 -05:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e40747f10a | ||
|
|
32b56a8d08 | ||
|
|
b6b0f2a7e6 | ||
|
|
bf771bd781 | ||
|
|
6336604906 | ||
|
|
cb93874014 | ||
|
|
9210e6a330 | ||
|
|
dec45c534f | ||
|
|
5da35ff980 | ||
|
|
626b066e56 | ||
|
|
a6bc32a61a | ||
|
|
e52bf9628f | ||
|
|
e76977bb35 | ||
|
|
073a05ebdd | ||
|
|
d0b143916c | ||
|
|
ce1a358cbf | ||
|
|
646e7eb3c7 | ||
|
|
6062ec86f3 | ||
|
|
3808d618fd | ||
|
|
f1ff930e68 | ||
|
|
7ca6f1cd1a | ||
|
|
73ca60c273 | ||
|
|
122713b168 | ||
|
|
ec464f0938 | ||
|
|
be87690255 | ||
|
|
33f6026c6c | ||
|
|
8ad6acfe6a | ||
|
|
b8941c31ea | ||
|
|
a315048357 | ||
|
|
b1fa0f262e | ||
|
|
44c4cdd73b | ||
|
|
c0df023557 | ||
|
|
9f4db6d6d3 | ||
|
|
383870a275 | ||
|
|
76e14214bd | ||
|
|
564d5591ad | ||
|
|
a5edc3f85b | ||
|
|
75e3aac8d3 | ||
|
|
d048b485cd | ||
|
|
b7e1551286 | ||
|
|
d2f69cf311 | ||
|
|
378623294e | ||
|
|
1f6a33ce72 | ||
|
|
0c13911af8 | ||
|
|
572a47cd1e | ||
|
|
2db35873ec | ||
|
|
fe4bed62ff | ||
|
|
d442afa175 | ||
|
|
1926ade7a8 | ||
|
|
712eee66ca | ||
|
|
957e6600a7 | ||
|
|
2a60a055f0 | ||
|
|
f48912633a | ||
|
|
e79bd168a4 | ||
|
|
b9766d7ee9 | ||
|
|
d9cacacf7f | ||
|
|
0880a5c6a0 |
36
docs/de/docs/external-links.md
Normal file
36
docs/de/docs/external-links.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Externe Links und Artikel
|
||||
|
||||
**FastAPI** hat eine großartige Community, die ständig wächst.
|
||||
|
||||
Es gibt viele Beiträge, Artikel, Tools und Projekte zum Thema **FastAPI**.
|
||||
|
||||
Hier ist eine unvollständige Liste einiger davon.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie einen Artikel, ein Projekt, ein Tool oder irgendetwas im Zusammenhang mit **FastAPI** haben, was hier noch nicht aufgeführt ist, erstellen Sie einen <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request und fügen Sie es hinzu</a>.
|
||||
|
||||
!!! note "Hinweis Deutsche Übersetzung"
|
||||
Die folgenden Überschriften und Links werden aus einer <a href="https://github.com/tiangolo/fastapi/blob/master/docs/en/data/external_links.yml" class="external-link" target="_blank">anderen Datei</a> gelesen und sind daher nicht ins Deutsche übersetzt.
|
||||
|
||||
{% for section_name, section_content in external_links.items() %}
|
||||
|
||||
## {{ section_name }}
|
||||
|
||||
{% for lang_name, lang_content in section_content.items() %}
|
||||
|
||||
### {{ lang_name }}
|
||||
|
||||
{% for item in lang_content %}
|
||||
|
||||
* <a href="{{ item.link }}" class="external-link" target="_blank">{{ item.title }}</a> by <a href="{{ item.author_link }}" class="external-link" target="_blank">{{ item.author }}</a>.
|
||||
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
## Projekte
|
||||
|
||||
Die neuesten GitHub-Projekte zum Thema `fastapi`:
|
||||
|
||||
<div class="github-topic-projects">
|
||||
</div>
|
||||
5
docs/de/docs/newsletter.md
Normal file
5
docs/de/docs/newsletter.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# FastAPI und Freunde Newsletter
|
||||
|
||||
<iframe data-w-type="embedded" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://xr4n4.mjt.lu/wgt/xr4n4/hj5/form?c=40a44fa4" width="100%" style="height: 0;"></iframe>
|
||||
|
||||
<script type="text/javascript" src="https://app.mailjet.com/pas-nc-embedded-v1.js"></script>
|
||||
11
docs/de/docs/reference/background.md
Normal file
11
docs/de/docs/reference/background.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Hintergrundtasks – `BackgroundTasks`
|
||||
|
||||
Sie können einen Parameter in einer *Pfadoperation-Funktion* oder einer Abhängigkeitsfunktion mit dem Typ `BackgroundTasks` deklarieren und diesen danach verwenden, um die Ausführung von Hintergrundtasks nach dem Senden der Response zu definieren.
|
||||
|
||||
Sie können `BackgroundTasks` direkt von `fastapi` importieren:
|
||||
|
||||
```python
|
||||
from fastapi import BackgroundTasks
|
||||
```
|
||||
|
||||
::: fastapi.BackgroundTasks
|
||||
3
docs/de/docs/reference/encoders.md
Normal file
3
docs/de/docs/reference/encoders.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Encoder – `jsonable_encoder`
|
||||
|
||||
::: fastapi.encoders.jsonable_encoder
|
||||
31
docs/de/docs/reference/fastapi.md
Normal file
31
docs/de/docs/reference/fastapi.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# `FastAPI`-Klasse
|
||||
|
||||
Hier sind die Referenzinformationen für die Klasse `FastAPI` mit all ihren Parametern, Attributen und Methoden.
|
||||
|
||||
Sie können die `FastAPI`-Klasse direkt von `fastapi` importieren:
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
```
|
||||
|
||||
::: fastapi.FastAPI
|
||||
options:
|
||||
members:
|
||||
- openapi_version
|
||||
- webhooks
|
||||
- state
|
||||
- dependency_overrides
|
||||
- openapi
|
||||
- websocket
|
||||
- include_router
|
||||
- get
|
||||
- put
|
||||
- post
|
||||
- delete
|
||||
- options
|
||||
- head
|
||||
- patch
|
||||
- trace
|
||||
- on_event
|
||||
- middleware
|
||||
- exception_handler
|
||||
14
docs/de/docs/reference/request.md
Normal file
14
docs/de/docs/reference/request.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# `Request`-Klasse
|
||||
|
||||
Sie können einen Parameter in einer *Pfadoperation-Funktion* oder einer Abhängigkeit als vom Typ `Request` deklarieren und dann direkt auf das Requestobjekt zugreifen, ohne jegliche Validierung, usw.
|
||||
|
||||
Sie können es direkt von `fastapi` importieren:
|
||||
|
||||
```python
|
||||
from fastapi import Request
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie Abhängigkeiten definieren möchten, die sowohl mit HTTP als auch mit WebSockets kompatibel sein sollen, können Sie einen Parameter definieren, der eine `HTTPConnection` anstelle eines `Request` oder eines `WebSocket` akzeptiert.
|
||||
|
||||
::: fastapi.Request
|
||||
164
docs/de/docs/reference/responses.md
Normal file
164
docs/de/docs/reference/responses.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Benutzerdefinierte Responseklassen – File, HTML, Redirect, Streaming, usw.
|
||||
|
||||
Es gibt mehrere benutzerdefinierte Responseklassen, von denen Sie eine Instanz erstellen und diese direkt von Ihren *Pfadoperationen* zurückgeben können.
|
||||
|
||||
Lesen Sie mehr darüber in der [FastAPI-Dokumentation zu benutzerdefinierten Responses – HTML, Stream, Datei, andere](../advanced/custom-response.md).
|
||||
|
||||
Sie können diese direkt von `fastapi.responses` importieren:
|
||||
|
||||
```python
|
||||
from fastapi.responses import (
|
||||
FileResponse,
|
||||
HTMLResponse,
|
||||
JSONResponse,
|
||||
ORJSONResponse,
|
||||
PlainTextResponse,
|
||||
RedirectResponse,
|
||||
Response,
|
||||
StreamingResponse,
|
||||
UJSONResponse,
|
||||
)
|
||||
```
|
||||
|
||||
## FastAPI-Responses
|
||||
|
||||
Es gibt einige benutzerdefinierte FastAPI-Responseklassen, welche Sie verwenden können, um die JSON-Performanz zu optimieren.
|
||||
|
||||
::: fastapi.responses.UJSONResponse
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.ORJSONResponse
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
## Starlette-Responses
|
||||
|
||||
::: fastapi.responses.FileResponse
|
||||
options:
|
||||
members:
|
||||
- chunk_size
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.HTMLResponse
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.JSONResponse
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.PlainTextResponse
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.RedirectResponse
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.Response
|
||||
options:
|
||||
members:
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
|
||||
::: fastapi.responses.StreamingResponse
|
||||
options:
|
||||
members:
|
||||
- body_iterator
|
||||
- charset
|
||||
- status_code
|
||||
- media_type
|
||||
- body
|
||||
- background
|
||||
- raw_headers
|
||||
- render
|
||||
- init_headers
|
||||
- headers
|
||||
- set_cookie
|
||||
- delete_cookie
|
||||
13
docs/de/docs/reference/templating.md
Normal file
13
docs/de/docs/reference/templating.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Templating – `Jinja2Templates`
|
||||
|
||||
Sie können die `Jinja2Templates`-Klasse verwenden, um Jinja-Templates zu rendern.
|
||||
|
||||
Lesen Sie mehr darüber in der [FastAPI-Dokumentation zu Templates](../advanced/templates.md).
|
||||
|
||||
Sie können die Klasse direkt von `fastapi.templating` importieren:
|
||||
|
||||
```python
|
||||
from fastapi.templating import Jinja2Templates
|
||||
```
|
||||
|
||||
::: fastapi.templating.Jinja2Templates
|
||||
@@ -7,6 +7,67 @@ hide:
|
||||
|
||||
## Latest Changes
|
||||
|
||||
## 0.110.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* 🐛 Fix unhandled growing memory for internal server errors, refactor dependencies with `yield` and `except` to require raising again as in regular Python. PR [#11191](https://github.com/tiangolo/fastapi/pull/11191) by [@tiangolo](https://github.com/tiangolo).
|
||||
* This is a breaking change (and only slightly) if you used dependencies with `yield`, used `except` in those dependencies, and didn't raise again.
|
||||
* This was reported internally by [@rushilsrivastava](https://github.com/rushilsrivastava) as a memory leak when the server had unhandled exceptions that would produce internal server errors, the memory allocated before that point would not be released.
|
||||
* Read the new docs: [Dependencies with `yield` and `except`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except).
|
||||
|
||||
In short, if you had dependencies that looked like:
|
||||
|
||||
```Python
|
||||
def my_dep():
|
||||
try:
|
||||
yield
|
||||
except SomeException:
|
||||
pass
|
||||
```
|
||||
|
||||
Now you need to make sure you raise again after `except`, just as you would in regular Python:
|
||||
|
||||
```Python
|
||||
def my_dep():
|
||||
try:
|
||||
yield
|
||||
except SomeException:
|
||||
raise
|
||||
```
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏️ Fix minor typos in `docs/ko/docs/`. PR [#11126](https://github.com/tiangolo/fastapi/pull/11126) by [@KaniKim](https://github.com/KaniKim).
|
||||
* ✏️ Fix minor typo in `fastapi/applications.py`. PR [#11099](https://github.com/tiangolo/fastapi/pull/11099) by [@JacobHayes](https://github.com/JacobHayes).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add German translation for `docs/de/docs/reference/background.md`. PR [#10820](https://github.com/tiangolo/fastapi/pull/10820) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add German translation for `docs/de/docs/reference/templating.md`. PR [#10842](https://github.com/tiangolo/fastapi/pull/10842) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add German translation for `docs/de/docs/external-links.md`. PR [#10852](https://github.com/tiangolo/fastapi/pull/10852) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Update Turkish translation for `docs/tr/docs/tutorial/query-params.md`. PR [#11162](https://github.com/tiangolo/fastapi/pull/11162) by [@hasansezertasan](https://github.com/hasansezertasan).
|
||||
* 🌐 Add German translation for `docs/de/docs/reference/encoders.md`. PR [#10840](https://github.com/tiangolo/fastapi/pull/10840) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add German translation for `docs/de/docs/reference/responses.md`. PR [#10825](https://github.com/tiangolo/fastapi/pull/10825) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add German translation for `docs/de/docs/reference/request.md`. PR [#10821](https://github.com/tiangolo/fastapi/pull/10821) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/query-params.md`. PR [#11078](https://github.com/tiangolo/fastapi/pull/11078) by [@emrhnsyts](https://github.com/emrhnsyts).
|
||||
* 🌐 Add German translation for `docs/de/docs/reference/fastapi.md`. PR [#10813](https://github.com/tiangolo/fastapi/pull/10813) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add German translation for `docs/de/docs/newsletter.md`. PR [#10853](https://github.com/tiangolo/fastapi/pull/10853) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/learn/index.md`. PR [#11142](https://github.com/tiangolo/fastapi/pull/11142) by [@hsuanchi](https://github.com/hsuanchi).
|
||||
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/dependencies/global-dependencies.md`. PR [#11123](https://github.com/tiangolo/fastapi/pull/11123) by [@riroan](https://github.com/riroan).
|
||||
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#11124](https://github.com/tiangolo/fastapi/pull/11124) by [@riroan](https://github.com/riroan).
|
||||
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/schema-extra-example.md`. PR [#11121](https://github.com/tiangolo/fastapi/pull/11121) by [@KaniKim](https://github.com/KaniKim).
|
||||
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/body-fields.md`. PR [#11112](https://github.com/tiangolo/fastapi/pull/11112) by [@KaniKim](https://github.com/KaniKim).
|
||||
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/cookie-params.md`. PR [#11118](https://github.com/tiangolo/fastapi/pull/11118) by [@riroan](https://github.com/riroan).
|
||||
* 🌐 Update Korean translation for `/docs/ko/docs/dependencies/index.md`. PR [#11114](https://github.com/tiangolo/fastapi/pull/11114) by [@KaniKim](https://github.com/KaniKim).
|
||||
* 🌐 Update Korean translation for `/docs/ko/docs/deployment/docker.md`. PR [#11113](https://github.com/tiangolo/fastapi/pull/11113) by [@KaniKim](https://github.com/KaniKim).
|
||||
* 🌐 Update Turkish translation for `docs/tr/docs/tutorial/first-steps.md`. PR [#11094](https://github.com/tiangolo/fastapi/pull/11094) by [@hasansezertasan](https://github.com/hasansezertasan).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/advanced/security/index.md`. PR [#2278](https://github.com/tiangolo/fastapi/pull/2278) by [@Xaraxx](https://github.com/Xaraxx).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/advanced/response-headers.md`. PR [#2276](https://github.com/tiangolo/fastapi/pull/2276) by [@Xaraxx](https://github.com/Xaraxx).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/deployment/index.md` and `~/deployment/versions.md`. PR [#9669](https://github.com/tiangolo/fastapi/pull/9669) by [@pabloperezmoya](https://github.com/pabloperezmoya).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/benchmarks.md`. PR [#10928](https://github.com/tiangolo/fastapi/pull/10928) by [@pablocm83](https://github.com/pablocm83).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/advanced/response-change-status-code.md`. PR [#11100](https://github.com/tiangolo/fastapi/pull/11100) by [@alejsdev](https://github.com/alejsdev).
|
||||
|
||||
## 0.109.2
|
||||
|
||||
### Upgrades
|
||||
|
||||
@@ -162,6 +162,63 @@ The same way, you could raise an `HTTPException` or similar in the exit code, af
|
||||
|
||||
An alternative you could use to catch exceptions (and possibly also raise another `HTTPException`) is to create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
|
||||
|
||||
## Dependencies with `yield` and `except`
|
||||
|
||||
If you catch an exception using `except` in a dependency with `yield` and you don't raise it again (or raise a new exception), FastAPI won't be able to notice there was an exception, the same way that would happen with regular Python:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="15-16"
|
||||
{!> ../../../docs_src/dependencies/tutorial008c_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="14-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial008c_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
```Python hl_lines="13-14"
|
||||
{!> ../../../docs_src/dependencies/tutorial008c.py!}
|
||||
```
|
||||
|
||||
In this case, the client will see an *HTTP 500 Internal Server Error* response as it should, given that we are not raising an `HTTPException` or similar, but the server will **not have any logs** or any other indication of what was the error. 😱
|
||||
|
||||
### Always `raise` in Dependencies with `yield` and `except`
|
||||
|
||||
If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, you should re-raise the original exception.
|
||||
|
||||
You can re-raise the same exception using `raise`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial008d_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial008d_an.py!}
|
||||
```
|
||||
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/dependencies/tutorial008d.py!}
|
||||
```
|
||||
|
||||
Now the client will get the same *HTTP 500 Internal Server Error* response, but the server will have our custom `InternalError` in the logs. 😎
|
||||
|
||||
## Execution of dependencies with `yield`
|
||||
|
||||
The sequence of execution is more or less like this diagram. Time flows from top to bottom. And each column is one of the parts interacting or executing code.
|
||||
@@ -187,7 +244,6 @@ participant tasks as Background tasks
|
||||
operation -->> dep: Raise Exception (e.g. HTTPException)
|
||||
opt handle
|
||||
dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception
|
||||
dep -->> handler: Auto forward exception
|
||||
end
|
||||
handler -->> client: HTTP error response
|
||||
end
|
||||
@@ -210,15 +266,23 @@ participant tasks as Background tasks
|
||||
!!! tip
|
||||
This diagram shows `HTTPException`, but you could also raise any other exception that you catch in a dependency with `yield` or with a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
|
||||
|
||||
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`, and then **again** to the exception handlers. If there's no exception handler for that exception, it will then be handled by the default internal `ServerErrorMiddleware`, returning a 500 HTTP status code, to let the client know that there was an error in the server.
|
||||
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`. In most cases you will want to re-raise that same exception or a new one from the dependency with `yield` to make sure it's properly handled.
|
||||
|
||||
## Dependencies with `yield`, `HTTPException` and Background Tasks
|
||||
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks
|
||||
|
||||
!!! warning
|
||||
You most probably don't need these technical details, you can skip this section and continue below.
|
||||
|
||||
These details are useful mainly if you were using a version of FastAPI prior to 0.106.0 and used resources from dependencies with `yield` in background tasks.
|
||||
|
||||
### Dependencies with `yield` and `except`, Technical Details
|
||||
|
||||
Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
|
||||
|
||||
This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
|
||||
|
||||
### Background Tasks and Dependencies with `yield`, Technical Details
|
||||
|
||||
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
|
||||
|
||||
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
|
||||
|
||||
33
docs/es/docs/advanced/response-change-status-code.md
Normal file
33
docs/es/docs/advanced/response-change-status-code.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Response - Cambiar el Status Code
|
||||
|
||||
Probablemente ya has leído con anterioridad que puedes establecer un [Response Status Code](../tutorial/response-status-code.md){.internal-link target=_blank} por defecto.
|
||||
|
||||
Pero en algunos casos necesitas retornar un status code diferente al predeterminado.
|
||||
|
||||
## Casos de uso
|
||||
|
||||
Por ejemplo, imagina que quieres retornar un HTTP status code de "OK" `200` por defecto.
|
||||
|
||||
Pero si los datos no existen, quieres crearlos y retornar un HTTP status code de "CREATED" `201`.
|
||||
|
||||
Pero aún quieres poder filtrar y convertir los datos que retornas con un `response_model`.
|
||||
|
||||
Para esos casos, puedes usar un parámetro `Response`.
|
||||
|
||||
## Usar un parámetro `Response`
|
||||
|
||||
Puedes declarar un parámetro de tipo `Response` en tu *función de la operación de path* (como puedes hacer para cookies y headers).
|
||||
|
||||
Y luego puedes establecer el `status_code` en ese objeto de respuesta *temporal*.
|
||||
|
||||
```Python hl_lines="1 9 12"
|
||||
{!../../../docs_src/response_change_status_code/tutorial001.py!}
|
||||
```
|
||||
|
||||
Y luego puedes retornar cualquier objeto que necesites, como normalmente lo harías (un `dict`, un modelo de base de datos, etc).
|
||||
|
||||
Y si declaraste un `response_model`, aún se usará para filtrar y convertir el objeto que retornaste.
|
||||
|
||||
**FastAPI** usará esa respuesta *temporal* para extraer el código de estado (también cookies y headers), y los pondrá en la respuesta final que contiene el valor que retornaste, filtrado por cualquier `response_model`.
|
||||
|
||||
También puedes declarar la dependencia del parámetro `Response`, y establecer el código de estado en ellos. Pero ten en cuenta que el último en establecerse será el que gane.
|
||||
44
docs/es/docs/advanced/response-headers.md
Normal file
44
docs/es/docs/advanced/response-headers.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Headers de Respuesta
|
||||
|
||||
## Usar un parámetro `Response`
|
||||
|
||||
Puedes declarar un parámetro de tipo `Response` en tu *función de operación de path* (de manera similar como se hace con las cookies).
|
||||
|
||||
Y entonces, podrás configurar las cookies en ese objeto de response *temporal*.
|
||||
|
||||
```Python hl_lines="1 7-8"
|
||||
{!../../../docs_src/response_headers/tutorial002.py!}
|
||||
```
|
||||
|
||||
Posteriormente, puedes devolver cualquier objeto que necesites, como normalmente harías (un `dict`, un modelo de base de datos, etc).
|
||||
|
||||
Si declaraste un `response_model`, este se continuará usando para filtrar y convertir el objeto que devolviste.
|
||||
|
||||
**FastAPI** usará ese response *temporal* para extraer los headers (al igual que las cookies y el status code), además las pondrá en el response final que contendrá el valor retornado y filtrado por algún `response_model`.
|
||||
|
||||
También puedes declarar el parámetro `Response` en dependencias, así como configurar los headers (y las cookies) en ellas.
|
||||
|
||||
|
||||
## Retornar una `Response` directamente
|
||||
|
||||
Adicionalmente, puedes añadir headers cuando se retorne una `Response` directamente.
|
||||
|
||||
Crea un response tal como se describe en [Retornar una respuesta directamente](response-directly.md){.internal-link target=_blank} y pasa los headers como un parámetro adicional:
|
||||
|
||||
```Python hl_lines="10-12"
|
||||
{!../../../docs_src/response_headers/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Detalles Técnicos"
|
||||
También podrías utilizar `from starlette.responses import Response` o `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** proporciona las mismas `starlette.responses` en `fastapi.responses` sólo que de una manera más conveniente para ti, el desarrollador. En otras palabras, muchas de las responses disponibles provienen directamente de Starlette.
|
||||
|
||||
|
||||
Y como la `Response` puede ser usada frecuentemente para configurar headers y cookies, **FastAPI** también la provee en `fastapi.Response`.
|
||||
|
||||
## Headers Personalizados
|
||||
|
||||
Ten en cuenta que se pueden añadir headers propietarios personalizados <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">usando el prefijo 'X-'</a>.
|
||||
|
||||
Si tienes headers personalizados y deseas que un cliente pueda verlos en el navegador, es necesario que los añadas a tus configuraciones de CORS (puedes leer más en [CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank}), usando el parámetro `expose_headers` documentado en <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette's CORS docs</a>.
|
||||
16
docs/es/docs/advanced/security/index.md
Normal file
16
docs/es/docs/advanced/security/index.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Seguridad Avanzada
|
||||
|
||||
## Características Adicionales
|
||||
|
||||
Hay algunas características adicionales para manejar la seguridad además de las que se tratan en el [Tutorial - Guía de Usuario: Seguridad](../../tutorial/security/){.internal-link target=_blank}.
|
||||
|
||||
!!! tip
|
||||
Las siguientes secciones **no necesariamente son "avanzadas"**.
|
||||
|
||||
Y es posible que para tu caso de uso, la solución esté en alguna de ellas.
|
||||
|
||||
## Leer primero el Tutorial
|
||||
|
||||
En las siguientes secciones asumimos que ya has leído el principal [Tutorial - Guía de Usuario: Seguridad](../../tutorial/security/){.internal-link target=_blank}.
|
||||
|
||||
Están basadas en los mismos conceptos, pero permiten algunas funcionalidades adicionales.
|
||||
33
docs/es/docs/benchmarks.md
Normal file
33
docs/es/docs/benchmarks.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Benchmarks
|
||||
|
||||
Los benchmarks independientes de TechEmpower muestran aplicaciones de **FastAPI** que se ejecutan en Uvicorn como <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">uno de los frameworks de Python más rápidos disponibles</a>, solo por debajo de Starlette y Uvicorn (utilizados internamente por FastAPI). (*)
|
||||
|
||||
Pero al comprobar benchmarks y comparaciones debes tener en cuenta lo siguiente.
|
||||
|
||||
## Benchmarks y velocidad
|
||||
|
||||
Cuando revisas los benchmarks, es común ver varias herramientas de diferentes tipos comparadas como equivalentes.
|
||||
|
||||
Específicamente, para ver Uvicorn, Starlette y FastAPI comparadas entre sí (entre muchas otras herramientas).
|
||||
|
||||
Cuanto más sencillo sea el problema resuelto por la herramienta, mejor rendimiento obtendrá. Y la mayoría de los benchmarks no prueban las funciones adicionales proporcionadas por la herramienta.
|
||||
|
||||
La jerarquía sería:
|
||||
|
||||
* **Uvicorn**: como servidor ASGI
|
||||
* **Starlette**: (usa Uvicorn) un microframework web
|
||||
* **FastAPI**: (usa Starlette) un microframework API con varias características adicionales para construir APIs, con validación de datos, etc.
|
||||
* **Uvicorn**:
|
||||
* Tendrá el mejor rendimiento, ya que no tiene mucho código extra aparte del propio servidor.
|
||||
* No escribirías una aplicación directamente en Uvicorn. Eso significaría que tu código tendría que incluir más o menos, al menos, todo el código proporcionado por Starlette (o **FastAPI**). Y si hicieras eso, tu aplicación final tendría la misma sobrecarga que si hubieras usado un framework y minimizado el código de tu aplicación y los errores.
|
||||
* Si estás comparando Uvicorn, compáralo con los servidores de aplicaciones Daphne, Hypercorn, uWSGI, etc.
|
||||
* **Starlette**:
|
||||
* Tendrá el siguiente mejor desempeño, después de Uvicorn. De hecho, Starlette usa Uvicorn para correr. Por lo tanto, probablemente sólo pueda volverse "más lento" que Uvicorn al tener que ejecutar más código.
|
||||
* Pero te proporciona las herramientas para crear aplicaciones web simples, con <abbr title="también conocido en español como: enrutamiento">routing</abbr> basado en <abbr title="tambien conocido en español como: rutas">paths</abbr>, etc.
|
||||
* Si estás comparando Starlette, compáralo con Sanic, Flask, Django, etc. Frameworks web (o microframeworks).
|
||||
* **FastAPI**:
|
||||
* De la misma manera que Starlette usa Uvicorn y no puede ser más rápido que él, **FastAPI** usa Starlette, por lo que no puede ser más rápido que él.
|
||||
* * FastAPI ofrece más características además de las de Starlette. Funciones que casi siempre necesitas al crear una API, como validación y serialización de datos. Y al usarlo, obtienes documentación automática de forma gratuita (la documentación automática ni siquiera agrega gastos generales a las aplicaciones en ejecución, se genera al iniciar).
|
||||
* Si no usaras FastAPI y usaras Starlette directamente (u otra herramienta, como Sanic, Flask, Responder, etc.), tendrías que implementar toda la validación y serialización de datos tu mismo. Por lo tanto, tu aplicación final seguirá teniendo la misma sobrecarga que si se hubiera creado con FastAPI. Y en muchos casos, esta validación y serialización de datos constituye la mayor cantidad de código escrito en las aplicaciones.
|
||||
* Entonces, al usar FastAPI estás ahorrando tiempo de desarrollo, errores, líneas de código y probablemente obtendrías el mismo rendimiento (o mejor) que obtendrías si no lo usaras (ya que tendrías que implementarlo todo en tu código).
|
||||
* Si estás comparando FastAPI, compáralo con un framework de aplicaciones web (o conjunto de herramientas) que proporciona validación, serialización y documentación de datos, como Flask-apispec, NestJS, Molten, etc. Frameworks con validación, serialización y documentación automáticas integradas.
|
||||
21
docs/es/docs/deployment/index.md
Normal file
21
docs/es/docs/deployment/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Despliegue - Introducción
|
||||
|
||||
Desplegar una aplicación hecha con **FastAPI** es relativamente fácil.
|
||||
|
||||
## ¿Qué significa desplegar una aplicación?
|
||||
|
||||
**Desplegar** una aplicación significa realizar una serie de pasos para hacerla **disponible para los usuarios**.
|
||||
|
||||
Para una **API web**, normalmente implica ponerla en una **máquina remota**, con un **programa de servidor** que proporcione un buen rendimiento, estabilidad, etc, para que sus **usuarios** puedan **acceder** a la aplicación de manera eficiente y sin interrupciones o problemas.
|
||||
|
||||
Esto difiere en las fases de **desarrollo**, donde estás constantemente cambiando el código, rompiéndolo y arreglándolo, deteniendo y reiniciando el servidor de desarrollo, etc.
|
||||
|
||||
## Estrategias de despliegue
|
||||
|
||||
Existen varias formas de hacerlo dependiendo de tu caso de uso específico y las herramientas que uses.
|
||||
|
||||
Puedes **desplegar un servidor** tú mismo usando un conjunto de herramientas, puedes usar **servicios en la nube** que haga parte del trabajo por ti, o usar otras posibles opciones.
|
||||
|
||||
Te enseñaré algunos de los conceptos principales que debes tener en cuenta al desplegar aplicaciones hechas con **FastAPI** (aunque la mayoría de estos conceptos aplican para cualquier otro tipo de aplicación web).
|
||||
|
||||
Podrás ver más detalles para tener en cuenta y algunas de las técnicas para hacerlo en las próximas secciones.✨
|
||||
87
docs/es/docs/deployment/versions.md
Normal file
87
docs/es/docs/deployment/versions.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Acerca de las versiones de FastAPI
|
||||
|
||||
**FastAPI** está siendo utilizado en producción en muchas aplicaciones y sistemas. La cobertura de los tests se mantiene al 100%. Sin embargo, su desarrollo sigue siendo rápido.
|
||||
|
||||
Se agregan nuevas características frecuentemente, se corrigen errores continuamente y el código está constantemente mejorando.
|
||||
|
||||
Por eso las versiones actuales siguen siendo `0.x.x`, esto significa que cada versión puede potencialmente tener <abbr title="cambios que rompen funcionalidades o compatibilidad">*breaking changes*</abbr>. Las versiones siguen las convenciones de <a href="https://semver.org/" class="external-link" target="_blank"><abbr title="versionado semántico">*Semantic Versioning*</abbr></a>.
|
||||
|
||||
Puedes crear aplicaciones listas para producción con **FastAPI** ahora mismo (y probablemente lo has estado haciendo por algún tiempo), solo tienes que asegurarte de usar la versión que funciona correctamente con el resto de tu código.
|
||||
|
||||
## Fijar la versión de `fastapi`
|
||||
|
||||
Lo primero que debes hacer en tu proyecto es "fijar" la última versión específica de **FastAPI** que sabes que funciona bien con tu aplicación.
|
||||
|
||||
Por ejemplo, digamos que estás usando la versión `0.45.0` en tu aplicación.
|
||||
|
||||
Si usas el archivo `requirements.txt` puedes especificar la versión con:
|
||||
|
||||
```txt
|
||||
fastapi==0.45.0
|
||||
```
|
||||
|
||||
esto significa que usarás específicamente la versión `0.45.0`.
|
||||
|
||||
También puedes fijar las versiones de esta forma:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
esto significa que usarás la versión `0.45.0` o superiores, pero menores a la versión `0.46.0`, por ejemplo, la versión `0.45.2` sería aceptada.
|
||||
|
||||
Si usas cualquier otra herramienta para manejar tus instalaciones, como Poetry, Pipenv, u otras, todas tienen una forma que puedes usar para definir versiones específicas para tus paquetes.
|
||||
|
||||
## Versiones disponibles
|
||||
|
||||
Puedes ver las versiones disponibles (por ejemplo, para revisar cuál es la actual) en las [Release Notes](../release-notes.md){.internal-link target=_blank}.
|
||||
|
||||
## Acerca de las versiones
|
||||
|
||||
Siguiendo las convenciones de *Semantic Versioning*, cualquier versión por debajo de `1.0.0` puede potencialmente tener <abbr title="cambios que rompen funcionalidades o compatibilidad">*breaking changes*</abbr>.
|
||||
|
||||
FastAPI también sigue la convención de que cualquier cambio hecho en una <abbr title="versiones de parche">"PATCH" version</abbr> es para solucionar errores y <abbr title="cambios que no rompan funcionalidades o compatibilidad">*non-breaking changes*</abbr>.
|
||||
|
||||
!!! tip
|
||||
El <abbr title="parche">"PATCH"</abbr> es el último número, por ejemplo, en `0.2.3`, la <abbr title="versiones de parche">PATCH version</abbr> es `3`.
|
||||
|
||||
Entonces, deberías fijar la versión así:
|
||||
|
||||
```txt
|
||||
fastapi>=0.45.0,<0.46.0
|
||||
```
|
||||
|
||||
En versiones <abbr title="versiones menores">"MINOR"</abbr> son añadidas nuevas características y posibles <abbr title="Cambios que rompen posibles funcionalidades o compatibilidad">breaking changes</abbr>.
|
||||
|
||||
!!! tip
|
||||
La versión "MINOR" es el número en el medio, por ejemplo, en `0.2.3`, la <abbr title="versión menor">"MINOR" version</abbr> es `2`.
|
||||
|
||||
## Actualizando las versiones de FastAPI
|
||||
|
||||
Para esto es recomendable primero añadir tests a tu aplicación.
|
||||
|
||||
Con **FastAPI** es muy fácil (gracias a Starlette), revisa la documentación [Testing](../tutorial/testing.md){.internal-link target=_blank}
|
||||
|
||||
Luego de tener los tests, puedes actualizar la versión de **FastAPI** a una más reciente y asegurarte de que tu código funciona correctamente ejecutando los tests.
|
||||
|
||||
Si todo funciona correctamente, o haces los cambios necesarios para que esto suceda, y todos tus tests pasan, entonces puedes fijar tu versión de `fastapi` a la más reciente.
|
||||
|
||||
## Acerca de Starlette
|
||||
|
||||
No deberías fijar la versión de `starlette`.
|
||||
|
||||
Diferentes versiones de **FastAPI** pueden usar una versión específica de Starlette.
|
||||
|
||||
Entonces, puedes dejar que **FastAPI** se asegure por sí mismo de qué versión de Starlette usar.
|
||||
|
||||
## Acerca de Pydantic
|
||||
|
||||
Pydantic incluye los tests para **FastAPI** dentro de sus propios tests, esto significa que las versiones de Pydantic (superiores a `1.0.0`) son compatibles con FastAPI.
|
||||
|
||||
Puedes fijar Pydantic a cualquier versión superior a `1.0.0` e inferior a `2.0.0` que funcione para ti.
|
||||
|
||||
Por ejemplo:
|
||||
|
||||
```txt
|
||||
pydantic>=1.2.0,<2.0.0
|
||||
```
|
||||
@@ -4,7 +4,7 @@ FastAPI 어플리케이션을 배포할 때 일반적인 접근 방법은 **리
|
||||
|
||||
리눅스 컨테이너를 사용하는 데에는 **보안**, **반복 가능성**, **단순함** 등의 장점이 있습니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
시간에 쫓기고 있고 이미 이런것들을 알고 있다면 [`Dockerfile`👇](#build-a-docker-image-for-fastapi)로 점프할 수 있습니다.
|
||||
|
||||
<details>
|
||||
@@ -130,7 +130,7 @@ Successfully installed fastapi pydantic uvicorn
|
||||
|
||||
</div>
|
||||
|
||||
!!! 정보
|
||||
!!! info "정보"
|
||||
패키지 종속성을 정의하고 설치하기 위한 방법과 도구는 다양합니다.
|
||||
|
||||
나중에 아래 세션에서 Poetry를 사용한 예시를 보이겠습니다. 👇
|
||||
@@ -222,7 +222,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
프로그램이 `/code`에서 시작하고 그 속에 `./app` 디렉터리가 여러분의 코드와 함께 들어있기 때문에, **Uvicorn**은 이를 보고 `app`을 `app.main`으로부터 **불러 올** 것입니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
각 코드 라인을 코드의 숫자 버블을 클릭하여 리뷰할 수 있습니다. 👆
|
||||
|
||||
이제 여러분은 다음과 같은 디렉터리 구조를 가지고 있을 것입니다:
|
||||
@@ -293,7 +293,7 @@ $ docker build -t myimage .
|
||||
|
||||
</div>
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
맨 끝에 있는 `.` 에 주목합시다. 이는 `./`와 동등하며, 도커에게 컨테이너 이미지를 빌드하기 위한 디렉터리를 알려줍니다.
|
||||
|
||||
이 경우에는 현재 디렉터리(`.`)와 같습니다.
|
||||
@@ -394,7 +394,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
**HTTPS**와 **인증서**의 **자동** 취득을 다루는 것은 다른 컨테이너가 될 수 있는데, 예를 들어 <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>을 사용하는 것입니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
Traefik은 도커, 쿠버네티스, 그리고 다른 도구와 통합되어 있어 여러분의 컨테이너를 포함하는 HTTPS를 셋업하고 설정하는 것이 매우 쉽습니다.
|
||||
|
||||
대안적으로, HTTPS는 클라우드 제공자에 의해 서비스의 일환으로 다루어질 수도 있습니다 (이때도 어플리케이션은 여전히 컨테이너에서 실행될 것입니다).
|
||||
@@ -423,7 +423,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
이 요소가 요청들의 **로드**를 읽어들이고 각 워커에게 (바라건대) **균형적으로** 분배한다면, 이 요소는 일반적으로 **로드 밸런서**라고 불립니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
HTTPS를 위해 사용된 **TLS 종료 프록시** 요소 또한 **로드 밸런서**가 될 수 있습니다.
|
||||
|
||||
또한 컨테이너로 작업할 때, 컨테이너를 시작하고 관리하기 위해 사용한 것과 동일한 시스템은 이미 해당 **로드 밸런서**로 부터 여러분의 앱에 해당하는 컨테이너로 **네트워크 통신**(예를 들어, HTTP 요청)을 전송하는 내부적인 도구를 가지고 있을 것입니다 (여기서도 로드 밸런서는 **TLS 종료 프록시**일 수 있습니다).
|
||||
@@ -503,7 +503,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
만약 여러분이 **여러개의 컨테이너**를 가지고 있다면, 아마도 각각의 컨테이너는 **하나의 프로세스**를 가지고 있을 것입니다(예를 들어, **쿠버네티스** 클러스터에서). 그러면 여러분은 복제된 워커 컨테이너를 실행하기 **이전에**, 하나의 컨테이너에 있는 **이전의 단계들을** 수행하는 단일 프로세스를 가지는 **별도의 컨테이너들**을 가지고 싶을 것입니다.
|
||||
|
||||
!!! 정보
|
||||
!!! info "정보"
|
||||
만약 여러분이 쿠버네티스를 사용하고 있다면, 아마도 이는 <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init Container</a>일 것입니다.
|
||||
|
||||
만약 여러분의 이용 사례에서 이전 단계들을 **병렬적으로 여러번** 수행하는데에 문제가 없다면 (예를 들어 데이터베이스 이전을 실행하지 않고 데이터베이스가 준비되었는지 확인만 하는 경우), 메인 프로세스를 시작하기 전에 이 단계들을 각 컨테이너에 넣을 수 있습니다.
|
||||
@@ -520,7 +520,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
* <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
!!! 경고
|
||||
!!! warning "경고"
|
||||
여러분이 이 베이스 이미지 또는 다른 유사한 이미지를 필요로 하지 **않을** 높은 가능성이 있으며, [위에서 설명된 것처럼: FastAPI를 위한 도커 이미지 빌드하기](#build-a-docker-image-for-fastapi) 처음부터 이미지를 빌드하는 것이 더 나을 수 있습니다.
|
||||
|
||||
이 이미지는 가능한 CPU 코어에 기반한 **몇개의 워커 프로세스**를 설정하는 **자동-튜닝** 메커니즘을 포함하고 있습니다.
|
||||
@@ -529,7 +529,7 @@ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
또한 스크립트를 통해 <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker#pre_start_path" class="external-link" target="_blank">**시작하기 전 사전 단계**</a>를 실행하는 것을 지원합니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
모든 설정과 옵션을 보려면, 도커 이미지 페이지로 이동합니다: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
### 공식 도커 이미지에 있는 프로세스 개수
|
||||
@@ -657,7 +657,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
|
||||
11. `uvicorn` 커맨드를 실행하여, `app.main`에서 불러온 `app` 객체를 사용하도록 합니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
버블 숫자를 클릭해 각 줄이 하는 일을 알아볼 수 있습니다.
|
||||
|
||||
**도커 스테이지**란 `Dockefile`의 일부로서 나중에 사용하기 위한 파일들을 생성하기 위한 **일시적인 컨테이너 이미지**로 작동합니다.
|
||||
|
||||
@@ -13,7 +13,7 @@ FastAPI에서는 응답을 반환한 후에 실행할 백그라운드 작업을
|
||||
|
||||
## `백그라운드 작업` 사용
|
||||
|
||||
먼저 아래와 같이 `BackgroundTasks`를 임포트하고, `BackgroundTasks`를 _경로 동작 함수_ 에서 매개변수로 가져오고 정의합니다.
|
||||
먼저 아래와 같이 `BackgroundTasks`를 임포트하고, `BackgroundTasks`를 _경로 작동 함수_ 에서 매개변수로 가져오고 정의합니다.
|
||||
|
||||
```Python hl_lines="1 13"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
@@ -39,7 +39,7 @@ FastAPI에서는 응답을 반환한 후에 실행할 백그라운드 작업을
|
||||
|
||||
## 백그라운드 작업 추가
|
||||
|
||||
_경로 동작 함수_ 내에서 작업 함수를 `.add_task()` 함수 통해 _백그라운드 작업_ 개체에 전달합니다.
|
||||
_경로 작동 함수_ 내에서 작업 함수를 `.add_task()` 함수 통해 _백그라운드 작업_ 개체에 전달합니다.
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!../../../docs_src/background_tasks/tutorial001.py!}
|
||||
@@ -53,7 +53,7 @@ _경로 동작 함수_ 내에서 작업 함수를 `.add_task()` 함수 통해 _
|
||||
|
||||
## 의존성 주입
|
||||
|
||||
`BackgroundTasks`를 의존성 주입 시스템과 함께 사용하면 _경로 동작 함수_, 종속성, 하위 종속성 등 여러 수준에서 BackgroundTasks 유형의 매개변수를 선언할 수 있습니다.
|
||||
`BackgroundTasks`를 의존성 주입 시스템과 함께 사용하면 _경로 작동 함수_, 종속성, 하위 종속성 등 여러 수준에서 BackgroundTasks 유형의 매개변수를 선언할 수 있습니다.
|
||||
|
||||
**FastAPI**는 각 경우에 수행할 작업과 동일한 개체를 내부적으로 재사용하기에, 모든 백그라운드 작업이 함께 병합되고 나중에 백그라운드에서 실행됩니다.
|
||||
|
||||
@@ -73,7 +73,7 @@ _경로 동작 함수_ 내에서 작업 함수를 `.add_task()` 함수 통해 _
|
||||
|
||||
요청에 쿼리가 있는 경우 백그라운드 작업의 로그에 기록됩니다.
|
||||
|
||||
그리고 _경로 동작 함수_ 에서 생성된 또 다른 백그라운드 작업은 경로 매개 변수를 활용하여 사용하여 메시지를 작성합니다.
|
||||
그리고 _경로 작동 함수_ 에서 생성된 또 다른 백그라운드 작업은 경로 매개 변수를 활용하여 사용하여 메시지를 작성합니다.
|
||||
|
||||
## 기술적 세부사항
|
||||
|
||||
@@ -81,7 +81,7 @@ _경로 동작 함수_ 내에서 작업 함수를 `.add_task()` 함수 통해 _
|
||||
|
||||
`BackgroundTasks` 클래스는 FastAPI에서 직접 임포트하거나 포함하기 때문에 실수로 `BackgroundTask` (끝에 `s`가 없음)을 임포트하더라도 starlette.background에서 `BackgroundTask`를 가져오는 것을 방지할 수 있습니다.
|
||||
|
||||
(`BackgroundTask`가 아닌) `BackgroundTasks`를 사용하면, _경로 동작 함수_ 매개변수로 사용할 수 있게 되고 나머지는 **FastAPI**가 대신 처리하도록 할 수 있습니다. 이것은 `Request` 객체를 직접 사용하는 것과 같은 방식입니다.
|
||||
(`BackgroundTask`가 아닌) `BackgroundTasks`를 사용하면, _경로 작동 함수_ 매개변수로 사용할 수 있게 되고 나머지는 **FastAPI**가 대신 처리하도록 할 수 있습니다. 이것은 `Request` 객체를 직접 사용하는 것과 같은 방식입니다.
|
||||
|
||||
FastAPI에서 `BackgroundTask`를 단독으로 사용하는 것은 여전히 가능합니다. 하지만 객체를 코드에서 생성하고, 이 객체를 포함하는 Starlette `Response`를 반환해야 합니다.
|
||||
|
||||
@@ -99,4 +99,4 @@ RabbitMQ 또는 Redis와 같은 메시지/작업 큐 시스템 보다 복잡한
|
||||
|
||||
## 요약
|
||||
|
||||
백그라운드 작업을 추가하기 위해 _경로 동작 함수_ 에 매개변수로 `BackgroundTasks`를 가져오고 사용합니다.
|
||||
백그라운드 작업을 추가하기 위해 _경로 작동 함수_ 에 매개변수로 `BackgroundTasks`를 가져오고 사용합니다.
|
||||
|
||||
116
docs/ko/docs/tutorial/body-fields.md
Normal file
116
docs/ko/docs/tutorial/body-fields.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# 본문 - 필드
|
||||
|
||||
`Query`, `Path`와 `Body`를 사용해 *경로 작동 함수* 매개변수 내에서 추가적인 검증이나 메타데이터를 선언한 것처럼 Pydantic의 `Field`를 사용하여 모델 내에서 검증과 메타데이터를 선언할 수 있습니다.
|
||||
|
||||
## `Field` 임포트
|
||||
|
||||
먼저 이를 임포트해야 합니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! warning "경고"
|
||||
`Field`는 다른 것들처럼 (`Query`, `Path`, `Body` 등) `fastapi`에서가 아닌 `pydantic`에서 바로 임포트 되는 점에 주의하세요.
|
||||
|
||||
## 모델 어트리뷰트 선언
|
||||
|
||||
그 다음 모델 어트리뷰트와 함께 `Field`를 사용할 수 있습니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="12-15"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
`Field`는 `Query`, `Path`와 `Body`와 같은 방식으로 동작하며, 모두 같은 매개변수들 등을 가집니다.
|
||||
|
||||
!!! note "기술적 세부사항"
|
||||
실제로 `Query`, `Path`등, 여러분이 앞으로 볼 다른 것들은 공통 클래스인 `Param` 클래스의 서브클래스 객체를 만드는데, 그 자체로 Pydantic의 `FieldInfo` 클래스의 서브클래스입니다.
|
||||
|
||||
그리고 Pydantic의 `Field` 또한 `FieldInfo`의 인스턴스를 반환합니다.
|
||||
|
||||
`Body` 또한 `FieldInfo`의 서브클래스 객체를 직접적으로 반환합니다. 그리고 `Body` 클래스의 서브클래스인 것들도 여러분이 나중에 보게될 것입니다.
|
||||
|
||||
`Query`, `Path`와 그 외 것들을 `fastapi`에서 임포트할 때, 이는 실제로 특별한 클래스를 반환하는 함수인 것을 기억해 주세요.
|
||||
|
||||
!!! tip "팁"
|
||||
주목할 점은 타입, 기본 값 및 `Field`로 이루어진 각 모델 어트리뷰트가 `Path`, `Query`와 `Body`대신 `Field`를 사용하는 *경로 작동 함수*의 매개변수와 같은 구조를 가진다는 점 입니다.
|
||||
|
||||
## 별도 정보 추가
|
||||
|
||||
`Field`, `Query`, `Body`, 그 외 안에 별도 정보를 선언할 수 있습니다. 이는 생성된 JSON 스키마에 포함됩니다.
|
||||
|
||||
여러분이 예제를 선언할 때 나중에 이 공식 문서에서 별도 정보를 추가하는 방법을 배울 것입니다.
|
||||
|
||||
!!! warning "경고"
|
||||
별도 키가 전달된 `Field` 또한 여러분의 어플리케이션의 OpenAPI 스키마에 나타날 것입니다.
|
||||
이런 키가 OpenAPI 명세서, [the OpenAPI validator](https://validator.swagger.io/)같은 몇몇 OpenAPI 도구들에 포함되지 못할 수 있으며, 여러분이 생성한 스키마와 호환되지 않을 수 있습니다.
|
||||
|
||||
## 요약
|
||||
|
||||
모델 어트리뷰트를 위한 추가 검증과 메타데이터 선언하기 위해 Pydantic의 `Field` 를 사용할 수 있습니다.
|
||||
|
||||
또한 추가적인 JSON 스키마 메타데이터를 전달하기 위한 별도의 키워드 인자를 사용할 수 있습니다.
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
## 다중 본문 매개변수
|
||||
|
||||
이전 예제에서 보듯이, *경로 동작*은 아래와 같이 `Item` 속성을 가진 JSON 본문을 예상합니다:
|
||||
이전 예제에서 보듯이, *경로 작동*은 아래와 같이 `Item` 속성을 가진 JSON 본문을 예상합니다:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -161,9 +161,9 @@ item: Item = Body(..., embed=True)
|
||||
|
||||
## 정리
|
||||
|
||||
요청이 단 한개의 본문을 가지고 있더라도, *경로 동작 함수*로 다중 본문 매개변수를 추가할 수 있습니다.
|
||||
요청이 단 한개의 본문을 가지고 있더라도, *경로 작동 함수*로 다중 본문 매개변수를 추가할 수 있습니다.
|
||||
|
||||
하지만, **FastAPI**는 이를 처리하고, 함수에 올바른 데이터를 제공하며, *경로 동작*으로 올바른 스키마를 검증하고 문서화 합니다.
|
||||
하지만, **FastAPI**는 이를 처리하고, 함수에 올바른 데이터를 제공하며, *경로 작동*으로 올바른 스키마를 검증하고 문서화 합니다.
|
||||
|
||||
또한, 단일 값을 본문의 일부로 받도록 선언할 수 있습니다.
|
||||
|
||||
|
||||
97
docs/ko/docs/tutorial/cookie-params.md
Normal file
97
docs/ko/docs/tutorial/cookie-params.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 쿠키 매개변수
|
||||
|
||||
쿠키 매개변수를 `Query`와 `Path` 매개변수들과 같은 방식으로 정의할 수 있습니다.
|
||||
|
||||
## `Cookie` 임포트
|
||||
|
||||
먼저 `Cookie`를 임포트합니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
## `Cookie` 매개변수 선언
|
||||
|
||||
그런 다음, `Path`와 `Query`처럼 동일한 구조를 사용하는 쿠키 매개변수를 선언합니다.
|
||||
|
||||
첫 번째 값은 기본값이며, 추가 검증이나 어노테이션 매개변수 모두 전달할 수 있습니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "기술 세부사항"
|
||||
`Cookie`는 `Path` 및 `Query`의 "자매"클래스입니다. 이 역시 동일한 공통 `Param` 클래스를 상속합니다.
|
||||
|
||||
`Query`, `Path`, `Cookie` 그리고 다른 것들은 `fastapi`에서 임포트 할 때, 실제로는 특별한 클래스를 반환하는 함수임을 기억하세요.
|
||||
|
||||
!!! info "정보"
|
||||
쿠키를 선언하기 위해서는 `Cookie`를 사용해야 합니다. 그렇지 않으면 해당 매개변수를 쿼리 매개변수로 해석하기 때문입니다.
|
||||
|
||||
## 요약
|
||||
|
||||
`Cookie`는 `Query`, `Path`와 동일한 패턴을 사용하여 선언합니다.
|
||||
@@ -71,9 +71,9 @@ fluffy = Cat(name="Mr Fluffy")
|
||||
|
||||
FastAPI가 실질적으로 확인하는 것은 "호출 가능성"(함수, 클래스 또는 다른 모든 것)과 정의된 매개변수들입니다.
|
||||
|
||||
"호출 가능"한 것을 의존성으로서 **FastAPI**에 전달하면, 그 "호출 가능"한 것의 매개변수들을 분석한 후 이를 *경로 동작 함수*를 위한 매개변수와 동일한 방식으로 처리합니다. 하위-의존성 또한 같은 방식으로 처리합니다.
|
||||
"호출 가능"한 것을 의존성으로서 **FastAPI**에 전달하면, 그 "호출 가능"한 것의 매개변수들을 분석한 후 이를 *경로 작동 함수*를 위한 매개변수와 동일한 방식으로 처리합니다. 하위-의존성 또한 같은 방식으로 처리합니다.
|
||||
|
||||
매개변수가 없는 "호출 가능"한 것 역시 매개변수가 없는 *경로 동작 함수*와 동일한 방식으로 적용됩니다.
|
||||
매개변수가 없는 "호출 가능"한 것 역시 매개변수가 없는 *경로 작동 함수*와 동일한 방식으로 적용됩니다.
|
||||
|
||||
그래서, 우리는 위 예제에서의 `common_paramenters` 의존성을 클래스 `CommonQueryParams`로 바꿀 수 있습니다.
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
# 경로 작동 데코레이터에서의 의존성
|
||||
|
||||
몇몇 경우에는, *경로 작동 함수* 안에서 의존성의 반환 값이 필요하지 않습니다.
|
||||
|
||||
또는 의존성이 값을 반환하지 않습니다.
|
||||
|
||||
그러나 여전히 실행/해결될 필요가 있습니다.
|
||||
|
||||
그런 경우에, `Depends`를 사용하여 *경로 작동 함수*의 매개변수로 선언하는 것보다 *경로 작동 데코레이터*에 `dependencies`의 `list`를 추가할 수 있습니다.
|
||||
|
||||
## *경로 작동 데코레이터*에 `dependencies` 추가하기
|
||||
|
||||
*경로 작동 데코레이터*는 `dependencies`라는 선택적인 인자를 받습니다.
|
||||
|
||||
`Depends()`로 된 `list`이어야합니다:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8 Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
이러한 의존성들은 기존 의존성들과 같은 방식으로 실행/해결됩니다. 그러나 값은 (무엇이든 반환한다면) *경로 작동 함수*에 제공되지 않습니다.
|
||||
|
||||
!!! tip "팁"
|
||||
일부 편집기에서는 사용되지 않는 함수 매개변수를 검사하고 오류로 표시합니다.
|
||||
|
||||
*경로 작동 데코레이터*에서 `dependencies`를 사용하면 편집기/도구 오류를 피하며 실행되도록 할 수 있습니다.
|
||||
|
||||
또한 코드에서 사용되지 않는 매개변수를 보고 불필요하다고 생각할 수 있는 새로운 개발자의 혼란을 방지하는데 도움이 될 수 있습니다.
|
||||
|
||||
!!! info "정보"
|
||||
이 예시에서 `X-Key`와 `X-Token`이라는 커스텀 헤더를 만들어 사용했습니다.
|
||||
|
||||
그러나 실제로 보안을 구현할 때는 통합된 [보안 유틸리티 (다음 챕터)](../security/index.md){.internal-link target=_blank}를 사용하는 것이 더 많은 이점을 얻을 수 있습니다.
|
||||
|
||||
## 의존성 오류와 값 반환하기
|
||||
|
||||
평소에 사용하던대로 같은 의존성 *함수*를 사용할 수 있습니다.
|
||||
|
||||
### 의존성 요구사항
|
||||
|
||||
(헤더같은) 요청 요구사항이나 하위-의존성을 선언할 수 있습니다:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8 Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
### 오류 발생시키기
|
||||
|
||||
다음 의존성은 기존 의존성과 동일하게 예외를 `raise`를 일으킬 수 있습니다:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8 Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
### 값 반환하기
|
||||
|
||||
값을 반환하거나, 그러지 않을 수 있으며 값은 사용되지 않습니다.
|
||||
|
||||
그래서 이미 다른 곳에서 사용된 (값을 반환하는) 일반적인 의존성을 재사용할 수 있고, 비록 값은 사용되지 않지만 의존성은 실행될 것입니다:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8 Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
## *경로 작동* 모음에 대한 의존성
|
||||
|
||||
나중에 여러 파일을 가지고 있을 수 있는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md){.internal-link target=_blank})을 읽을 때, *경로 작동* 모음에 대한 단일 `dependencies` 매개변수를 선언하는 법에 대해서 배우게 될 것입니다.
|
||||
|
||||
## 전역 의존성
|
||||
|
||||
다음으로 각 *경로 작동*에 적용되도록 `FastAPI` 애플리케이션 전체에 의존성을 추가하는 법을 볼 것입니다.
|
||||
34
docs/ko/docs/tutorial/dependencies/global-dependencies.md
Normal file
34
docs/ko/docs/tutorial/dependencies/global-dependencies.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# 전역 의존성
|
||||
|
||||
몇몇 애플리케이션에서는 애플리케이션 전체에 의존성을 추가하고 싶을 수 있습니다.
|
||||
|
||||
[*경로 작동 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}와 유사한 방법으로 `FastAPI` 애플리케이션에 그것들을 추가할 수 있습니다.
|
||||
|
||||
그런 경우에, 애플리케이션의 모든 *경로 작동*에 적용될 것입니다:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial012_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8 Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/dependencies/tutorial012.py!}
|
||||
```
|
||||
|
||||
그리고 [*경로 작동 데코레이터*에 `dependencies` 추가하기](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}에 대한 아이디어는 여전히 적용되지만 여기에서는 앱에 있는 모든 *경로 작동*에 적용됩니다.
|
||||
|
||||
## *경로 작동* 모음에 대한 의존성
|
||||
|
||||
이후에 여러 파일들을 가지는 더 큰 애플리케이션을 구조화하는 법([더 큰 애플리케이션 - 여러 파일들](../../tutorial/bigger-applications.md){.internal-link target=_blank})을 읽을 때, *경로 작동* 모음에 대한 단일 `dependencies` 매개변수를 선언하는 법에 대해서 배우게 될 것입니다.
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
## "의존성 주입"은 무엇입니까?
|
||||
|
||||
**"의존성 주입"**은 프로그래밍에서 여러분의 코드(이 경우, 경로 동작 함수)가 작동하고 사용하는 데 필요로 하는 것, 즉 "의존성"을 선언할 수 있는 방법을 의미합니다.
|
||||
**"의존성 주입"**은 프로그래밍에서 여러분의 코드(이 경우, 경로 작동 함수)가 작동하고 사용하는 데 필요로 하는 것, 즉 "의존성"을 선언할 수 있는 방법을 의미합니다.
|
||||
|
||||
그 후에, 시스템(이 경우 FastAPI)은 여러분의 코드가 요구하는 의존성을 제공하기 위해 필요한 모든 작업을 처리합니다.(의존성을 "주입"합니다)
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="8-11"
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="1"
|
||||
@@ -123,7 +123,7 @@
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="3"
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="15 20"
|
||||
@@ -180,7 +180,7 @@
|
||||
|
||||
그리고 그 함수는 *경로 작동 함수*가 작동하는 것과 같은 방식으로 매개변수를 받습니다.
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
여러분은 다음 장에서 함수를 제외하고서, "다른 것들"이 어떻게 의존성으로 사용되는지 알게 될 것입니다.
|
||||
|
||||
새로운 요청이 도착할 때마다, **FastAPI**는 다음을 처리합니다:
|
||||
@@ -202,7 +202,7 @@ common_parameters --> read_users
|
||||
|
||||
이렇게 하면 공용 코드를 한번만 적어도 되며, **FastAPI**는 *경로 작동*을 위해 이에 대한 호출을 처리합니다.
|
||||
|
||||
!!! 확인
|
||||
!!! check "확인"
|
||||
특별한 클래스를 만들지 않아도 되며, 이러한 것 혹은 비슷한 종류를 **FastAPI**에 "등록"하기 위해 어떤 곳에 넘겨주지 않아도 됩니다.
|
||||
|
||||
단순히 `Depends`에 넘겨주기만 하면 되며, **FastAPI**는 나머지를 어찌할지 알고 있습니다.
|
||||
@@ -237,7 +237,7 @@ commons: Annotated[dict, Depends(common_parameters)]
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
|
||||
```
|
||||
|
||||
!!! 팁
|
||||
!!! tip "팁"
|
||||
이는 그저 표준 파이썬이고 "type alias"라고 부르며 사실 **FastAPI**에 국한되는 것은 아닙니다.
|
||||
|
||||
하지만, `Annotated`를 포함하여, **FastAPI**가 파이썬 표준을 기반으로 하고 있기에, 이를 여러분의 코드 트릭으로 사용할 수 있습니다. 😎
|
||||
@@ -256,7 +256,7 @@ commons: Annotated[dict, Depends(common_parameters)]
|
||||
|
||||
아무 문제 없습니다. **FastAPI**는 무엇을 할지 알고 있습니다.
|
||||
|
||||
!!! 참고
|
||||
!!! note "참고"
|
||||
잘 모르시겠다면, [Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank} 문서에서 `async`와 `await`에 대해 확인할 수 있습니다.
|
||||
|
||||
## OpenAPI와 통합
|
||||
|
||||
@@ -309,7 +309,7 @@ URL "`/`"에 대한 `GET` 작동을 사용하는 요청을 받을 때마다 **Fa
|
||||
{!../../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! note 참고
|
||||
!!! note "참고"
|
||||
차이점을 모르겠다면 [Async: *"In a hurry?"*](../async.md#in-a-hurry){.internal-link target=_blank}을 확인하세요.
|
||||
|
||||
### 5 단계: 콘텐츠 반환
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 경로 동작 설정
|
||||
# 경로 작동 설정
|
||||
|
||||
*경로 작동 데코레이터*를 설정하기 위해서 전달할수 있는 몇 가지 매개변수가 있습니다.
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ q: Optional[str] = None
|
||||
q: str = Query(None, max_length=50)
|
||||
```
|
||||
|
||||
이는 데이터를 검증할 것이고, 데이터가 유효하지 않다면 명백한 오류를 보여주며, OpenAPI 스키마 *경로 동작*에 매개변수를 문서화 합니다.
|
||||
이는 데이터를 검증할 것이고, 데이터가 유효하지 않다면 명백한 오류를 보여주며, OpenAPI 스키마 *경로 작동*에 매개변수를 문서화 합니다.
|
||||
|
||||
## 검증 추가
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ HTML의 폼들(`<form></form>`)이 서버에 데이터를 전송하는 방식은
|
||||
|
||||
인코딩과 폼 필드에 대해 더 알고싶다면, <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><code>POST</code>에 관한<abbr title="Mozilla Developer Network">MDN</abbr>웹 문서</a> 를 참고하기 바랍니다,.
|
||||
|
||||
!!! warning "주의"
|
||||
!!! warning "경고"
|
||||
다수의 `File` 과 `Form` 매개변수를 한 *경로 작동*에 선언하는 것이 가능하지만, 요청의 본문이 `application/json` 가 아닌 `multipart/form-data` 로 인코딩 되기 때문에 JSON으로 받아야하는 `Body` 필드를 함께 선언할 수는 없습니다.
|
||||
|
||||
이는 **FastAPI**의 한계가 아니라, HTTP 프로토콜에 의한 것입니다.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
어떤 파일들은 `bytes`로, 또 어떤 파일들은 `UploadFile`로 선언할 수 있습니다.
|
||||
|
||||
!!! warning "주의"
|
||||
!!! warning "경고"
|
||||
다수의 `File`과 `Form` 매개변수를 한 *경로 작동*에 선언하는 것이 가능하지만, 요청의 본문이 `application/json`가 아닌 `multipart/form-data`로 인코딩 되기 때문에 JSON으로 받아야하는 `Body` 필드를 함께 선언할 수는 없습니다.
|
||||
|
||||
이는 **FastAPI**의 한계가 아니라, HTTP 프로토콜에 의한 것입니다.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 응답 모델
|
||||
|
||||
어떤 *경로 동작*이든 매개변수 `response_model`를 사용하여 응답을 위한 모델을 선언할 수 있습니다:
|
||||
어떤 *경로 작동*이든 매개변수 `response_model`를 사용하여 응답을 위한 모델을 선언할 수 있습니다:
|
||||
|
||||
* `@app.get()`
|
||||
* `@app.post()`
|
||||
@@ -13,7 +13,7 @@
|
||||
```
|
||||
|
||||
!!! note "참고"
|
||||
`response_model`은 "데코레이터" 메소드(`get`, `post`, 등)의 매개변수입니다. 모든 매개변수들과 본문(body)처럼 *경로 동작 함수*가 아닙니다.
|
||||
`response_model`은 "데코레이터" 메소드(`get`, `post`, 등)의 매개변수입니다. 모든 매개변수들과 본문(body)처럼 *경로 작동 함수*가 아닙니다.
|
||||
|
||||
Pydantic 모델 어트리뷰트를 선언한 것과 동일한 타입을 수신하므로 Pydantic 모델이 될 수 있지만, `List[Item]`과 같이 Pydantic 모델들의 `list`일 수도 있습니다.
|
||||
|
||||
@@ -21,7 +21,7 @@ FastAPI는 이 `response_model`를 사용하여:
|
||||
|
||||
* 출력 데이터를 타입 선언으로 변환.
|
||||
* 데이터 검증.
|
||||
* OpenAPI *경로 동작*의 응답에 JSON 스키마 추가.
|
||||
* OpenAPI *경로 작동*의 응답에 JSON 스키마 추가.
|
||||
* 자동 생성 문서 시스템에 사용.
|
||||
|
||||
하지만 가장 중요한 것은:
|
||||
@@ -49,7 +49,7 @@ FastAPI는 이 `response_model`를 사용하여:
|
||||
|
||||
이 경우, 사용자가 스스로 비밀번호를 발신했기 때문에 문제가 되지 않을 수 있습니다.
|
||||
|
||||
그러나 동일한 모델을 다른 *경로 동작*에서 사용할 경우, 모든 클라이언트에게 사용자의 비밀번호를 발신할 수 있습니다.
|
||||
그러나 동일한 모델을 다른 *경로 작동*에서 사용할 경우, 모든 클라이언트에게 사용자의 비밀번호를 발신할 수 있습니다.
|
||||
|
||||
!!! danger "위험"
|
||||
절대로 사용자의 평문 비밀번호를 저장하거나 응답으로 발신하지 마십시오.
|
||||
@@ -62,7 +62,7 @@ FastAPI는 이 `response_model`를 사용하여:
|
||||
{!../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
여기서 *경로 동작 함수*가 비밀번호를 포함하는 동일한 입력 사용자를 반환할지라도:
|
||||
여기서 *경로 작동 함수*가 비밀번호를 포함하는 동일한 입력 사용자를 반환할지라도:
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!../../../docs_src/response_model/tutorial003.py!}
|
||||
@@ -104,7 +104,7 @@ FastAPI는 이 `response_model`를 사용하여:
|
||||
|
||||
### `response_model_exclude_unset` 매개변수 사용
|
||||
|
||||
*경로 동작 데코레이터* 매개변수를 `response_model_exclude_unset=True`로 설정 할 수 있습니다:
|
||||
*경로 작동 데코레이터* 매개변수를 `response_model_exclude_unset=True`로 설정 할 수 있습니다:
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!../../../docs_src/response_model/tutorial004.py!}
|
||||
@@ -112,7 +112,7 @@ FastAPI는 이 `response_model`를 사용하여:
|
||||
|
||||
이러한 기본값은 응답에 포함되지 않고 실제로 설정된 값만 포함됩니다.
|
||||
|
||||
따라서 해당 *경로 동작*에 ID가 `foo`인 항목(items)을 요청으로 보내면 (기본값을 제외한) 응답은 다음과 같습니다:
|
||||
따라서 해당 *경로 작동*에 ID가 `foo`인 항목(items)을 요청으로 보내면 (기본값을 제외한) 응답은 다음과 같습니다:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -173,7 +173,7 @@ ID가 `baz`인 항목(items)처럼 기본값과 동일한 값을 갖는다면:
|
||||
|
||||
### `response_model_include` 및 `response_model_exclude`
|
||||
|
||||
*경로 동작 데코레이터* 매개변수 `response_model_include` 및 `response_model_exclude`를 사용할 수 있습니다.
|
||||
*경로 작동 데코레이터* 매개변수 `response_model_include` 및 `response_model_exclude`를 사용할 수 있습니다.
|
||||
|
||||
이들은 포함(나머지 생략)하거나 제외(나머지 포함) 할 어트리뷰트의 이름과 `str`의 `set`을 받습니다.
|
||||
|
||||
@@ -205,6 +205,6 @@ Pydantic 모델이 하나만 있고 출력에서 일부 데이터를 제
|
||||
|
||||
## 요약
|
||||
|
||||
응답 모델을 정의하고 개인정보가 필터되는 것을 보장하기 위해 *경로 동작 데코레이터*의 매개변수 `response_model`을 사용하세요.
|
||||
응답 모델을 정의하고 개인정보가 필터되는 것을 보장하기 위해 *경로 작동 데코레이터*의 매개변수 `response_model`을 사용하세요.
|
||||
|
||||
명시적으로 설정된 값만 반환하려면 `response_model_exclude_unset`을 사용하세요.
|
||||
|
||||
326
docs/ko/docs/tutorial/schema-extra-example.md
Normal file
326
docs/ko/docs/tutorial/schema-extra-example.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# 요청 예제 데이터 선언
|
||||
|
||||
여러분의 앱이 받을 수 있는 데이터 예제를 선언할 수 있습니다.
|
||||
|
||||
여기 이를 위한 몇가지 방식이 있습니다.
|
||||
|
||||
## Pydantic 모델 속 추가 JSON 스키마 데이터
|
||||
|
||||
생성된 JSON 스키마에 추가될 Pydantic 모델을 위한 `examples`을 선언할 수 있습니다.
|
||||
|
||||
=== "Python 3.10+ Pydantic v2"
|
||||
|
||||
```Python hl_lines="13-24"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Pydantic v1"
|
||||
|
||||
```Python hl_lines="13-23"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_py310_pv1.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Pydantic v2"
|
||||
|
||||
```Python hl_lines="15-26"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Pydantic v1"
|
||||
|
||||
```Python hl_lines="15-25"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_pv1.py!}
|
||||
```
|
||||
|
||||
추가 정보는 있는 그대로 해당 모델의 **JSON 스키마** 결과에 추가되고, API 문서에서 사용합니다.
|
||||
|
||||
=== "Pydantic v2"
|
||||
|
||||
Pydantic 버전 2에서 <a href="https://docs.pydantic.dev/latest/usage/model_config/" class="external-link" target="_blank">Pydantic 공식 문서: Model Config</a>에 나와 있는 것처럼 `dict`를 받는 `model_config` 어트리뷰트를 사용할 것입니다.
|
||||
|
||||
`"json_schema_extra"`를 생성된 JSON 스키마에서 보여주고 싶은 별도의 데이터와 `examples`를 포함하는 `dict`으로 설정할 수 있습니다.
|
||||
|
||||
=== "Pydantic v1"
|
||||
|
||||
Pydantic v1에서 <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic 공식 문서: Schema customization</a>에서 설명하는 것처럼, 내부 클래스인 `Config`와 `schema_extra`를 사용할 것입니다.
|
||||
|
||||
`schema_extra`를 생성된 JSON 스키마에서 보여주고 싶은 별도의 데이터와 `examples`를 포함하는 `dict`으로 설정할 수 있습니다.
|
||||
|
||||
!!! tip "팁"
|
||||
JSON 스키마를 확장하고 여러분의 별도의 자체 데이터를 추가하기 위해 같은 기술을 사용할 수 있습니다.
|
||||
|
||||
예를 들면, 프론트엔드 사용자 인터페이스에 메타데이터를 추가하는 등에 사용할 수 있습니다.
|
||||
|
||||
!!! info "정보"
|
||||
(FastAPI 0.99.0부터 쓰이기 시작한) OpenAPI 3.1.0은 **JSON 스키마** 표준의 일부인 `examples`에 대한 지원을 추가했습니다.
|
||||
|
||||
그 전에는, 하나의 예제만 가능한 `example` 키워드만 지원했습니다. 이는 아직 OpenAPI 3.1.0에서 지원하지만, 지원이 종료될 것이며 JSON 스키마 표준에 포함되지 않습니다. 그렇기에 `example`을 `examples`으로 이전하는 것을 추천합니다. 🤓
|
||||
|
||||
이 문서 끝에 더 많은 읽을거리가 있습니다.
|
||||
|
||||
## `Field` 추가 인자
|
||||
|
||||
Pydantic 모델과 같이 `Field()`를 사용할 때 추가적인 `examples`를 선언할 수 있습니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="2 8-11"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="4 10-13"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
|
||||
```
|
||||
|
||||
## JSON Schema에서의 `examples` - OpenAPI
|
||||
|
||||
이들 중에서 사용합니다:
|
||||
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* `Body()`
|
||||
* `Form()`
|
||||
* `File()`
|
||||
|
||||
**OpenAPI**의 **JSON 스키마**에 추가될 부가적인 정보를 포함한 `examples` 모음을 선언할 수 있습니다.
|
||||
|
||||
### `examples`를 포함한 `Body`
|
||||
|
||||
여기, `Body()`에 예상되는 예제 데이터 하나를 포함한 `examples`를 넘겼습니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="22-29"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="22-29"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="23-30"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="18-25"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="20-27"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
|
||||
```
|
||||
|
||||
### 문서 UI 예시
|
||||
|
||||
위의 어느 방법과 함께라면 `/docs`에서 다음과 같이 보일 것입니다:
|
||||
|
||||
<img src="/img/tutorial/body-fields/image01.png">
|
||||
|
||||
### 다중 `examples`를 포함한 `Body`
|
||||
|
||||
물론 여러 `examples`를 넘길 수 있습니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="23-38"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="23-38"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="24-39"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="19-34"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="21-36"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
|
||||
```
|
||||
|
||||
이와 같이 하면 이 예제는 그 본문 데이터를 위한 내부 **JSON 스키마**의 일부가 될 것입니다.
|
||||
|
||||
그럼에도 불구하고, 지금 <abbr title="2023-08-26">이 문서를 작성하는 시간</abbr>에, 문서 UI를 보여주는 역할을 맡은 Swagger UI는 **JSON 스키마** 속 데이터를 위한 여러 예제의 표현을 지원하지 않습니다. 하지만 해결 방안을 밑에서 읽어보세요.
|
||||
|
||||
### OpenAPI-특화 `examples`
|
||||
|
||||
**JSON 스키마**가 `examples`를 지원하기 전 부터, OpenAPI는 `examples`이라 불리는 다른 필드를 지원해 왔습니다.
|
||||
|
||||
이 **OpenAPI-특화** `examples`는 OpenAPI 명세서의 다른 구역으로 들어갑니다. 각 JSON 스키마 내부가 아니라 **각 *경로 작동* 세부 정보**에 포함됩니다.
|
||||
|
||||
그리고 Swagger UI는 이 특정한 `examples` 필드를 한동안 지원했습니다. 그래서, 이를 다른 **문서 UI에 있는 예제**를 **표시**하기 위해 사용할 수 있습니다.
|
||||
|
||||
이 OpenAPI-특화 필드인 `examples`의 형태는 (`list`대신에) **다중 예제**가 포함된 `dict`이며, 각각의 별도 정보 또한 **OpenAPI**에 추가될 것입니다.
|
||||
|
||||
이는 OpenAPI에 포함된 JSON 스키마 안으로 포함되지 않으며, *경로 작동*에 직접적으로 포함됩니다.
|
||||
|
||||
### `openapi_examples` 매개변수 사용하기
|
||||
|
||||
다음 예시 속에 OpenAPI-특화 `examples`를 FastAPI 안에서 매개변수 `openapi_examples` 매개변수와 함께 선언할 수 있습니다:
|
||||
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* `Body()`
|
||||
* `Form()`
|
||||
* `File()`
|
||||
|
||||
`dict`의 키가 또 다른 `dict`인 각 예제와 값을 구별합니다.
|
||||
|
||||
각각의 특정 `examples` 속 `dict` 예제는 다음을 포함할 수 있습니다:
|
||||
|
||||
* `summary`: 예제에 대한 짧은 설명문.
|
||||
* `description`: 마크다운 텍스트를 포함할 수 있는 긴 설명문.
|
||||
* `value`: 실제로 보여지는 예시, 예를 들면 `dict`.
|
||||
* `externalValue`: `value`의 대안이며 예제를 가르키는 URL. 비록 `value`처럼 많은 도구를 지원하지 못할 수 있습니다.
|
||||
|
||||
이를 다음과 같이 사용할 수 있습니다:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="23-49"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="23-49"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="24-50"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="19-45"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ Annotated가 없는 경우"
|
||||
|
||||
!!! tip "팁"
|
||||
가능하다면 `Annotated`가 달린 버전을 권장합니다.
|
||||
|
||||
```Python hl_lines="21-47"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005.py!}
|
||||
```
|
||||
|
||||
### 문서 UI에서의 OpenAPI 예시
|
||||
|
||||
`Body()`에 추가된 `openapi_examples`를 포함한 `/docs`는 다음과 같이 보일 것입니다:
|
||||
|
||||
<img src="/img/tutorial/body-fields/image02.png">
|
||||
|
||||
## 기술적 세부 사항
|
||||
|
||||
!!! tip "팁"
|
||||
이미 **FastAPI**의 **0.99.0 혹은 그 이상** 버전을 사용하고 있다면, 이 세부 사항을 **스킵**해도 상관 없을 것입니다.
|
||||
|
||||
세부 사항은 OpenAPI 3.1.0이 사용가능하기 전, 예전 버전과 더 관련있습니다.
|
||||
|
||||
간략한 OpenAPI와 JSON 스키마 **역사 강의**로 생각할 수 있습니다. 🤓
|
||||
|
||||
!!! warning "경고"
|
||||
표준 **JSON 스키마**와 **OpenAPI**에 대한 아주 기술적인 세부사항입니다.
|
||||
|
||||
만약 위의 생각이 작동한다면, 그것으로 충분하며 이 세부 사항은 필요없을 것이니, 마음 편하게 스킵하셔도 됩니다.
|
||||
|
||||
OpenAPI 3.1.0 전에 OpenAPI는 오래된 **JSON 스키마**의 수정된 버전을 사용했습니다.
|
||||
|
||||
JSON 스키마는 `examples`를 가지고 있지 않았고, 따라서 OpenAPI는 그들만의 `example` 필드를 수정된 버전에 추가했습니다.
|
||||
|
||||
OpenAPI는 또한 `example`과 `examples` 필드를 명세서의 다른 부분에 추가했습니다:
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object" class="external-link" target="_blank">`(명세서에 있는) Parameter Object`</a>는 FastAPI의 다음 기능에서 쓰였습니다:
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object" class="external-link" target="_blank">(명세서에 있는)`Media Type Object`속 `content`에 있는 `Request Body Object`</a>는 FastAPI의 다음 기능에서 쓰였습니다:
|
||||
* `Body()`
|
||||
* `File()`
|
||||
* `Form()`
|
||||
|
||||
!!! info "정보"
|
||||
이 예전 OpenAPI-특화 `examples` 매개변수는 이제 FastAPI `0.103.0`부터 `openapi_examples`입니다.
|
||||
|
||||
### JSON 스키마의 `examples` 필드
|
||||
|
||||
하지만, 후에 JSON 스키마는 <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>필드를 명세서의 새 버전에 추가했습니다.
|
||||
|
||||
그리고 새로운 OpenAPI 3.1.0은 이 새로운 `examples` 필드가 포함된 최신 버전 (JSON 스키마 2020-12)을 기반으로 했습니다.
|
||||
|
||||
이제 새로운 `examples` 필드는 이전의 단일 (그리고 커스텀) `example` 필드보다 우선되며, `example`은 사용하지 않는 것이 좋습니다.
|
||||
|
||||
JSON 스키마의 새로운 `examples` 필드는 예제 속 **단순한 `list`**이며, (위에서 상술한 것처럼) OpenAPI의 다른 곳에 존재하는 dict으로 된 추가적인 메타데이터가 아닙니다.
|
||||
|
||||
!!! info "정보"
|
||||
더 쉽고 새로운 JSON 스키마와의 통합과 함께 OpenAPI 3.1.0가 배포되었지만, 잠시동안 자동 문서 생성을 제공하는 도구인 Swagger UI는 OpenAPI 3.1.0을 지원하지 않았습니다 (5.0.0 버전부터 지원합니다 🎉).
|
||||
|
||||
이로인해, FastAPI 0.99.0 이전 버전은 아직 OpenAPI 3.1.0 보다 낮은 버전을 사용했습니다.
|
||||
|
||||
### Pydantic과 FastAPI `examples`
|
||||
|
||||
`examples`를 Pydantic 모델 속에 추가할 때, `schema_extra` 혹은 `Field(examples=["something"])`를 사용하면 Pydantic 모델의 **JSON 스키마**에 해당 예시가 추가됩니다.
|
||||
|
||||
그리고 Pydantic 모델의 **JSON 스키마**는 API의 **OpenAPI**에 포함되고, 그 후 문서 UI 속에서 사용됩니다.
|
||||
|
||||
FastAPI 0.99.0 이전 버전에서 (0.99.0 이상 버전은 새로운 OpenAPI 3.1.0을 사용합니다), `example` 혹은 `examples`를 다른 유틸리티(`Query()`, `Body()` 등)와 함께 사용했을 때, 저러한 예시는 데이터를 설명하는 JSON 스키마에 추가되지 않으며 (심지어 OpenAPI의 자체 JSON 스키마에도 포함되지 않습니다), OpenAPI의 *경로 작동* 선언에 직접적으로 추가됩니다 (JSON 스키마를 사용하는 OpenAPI 부분 외에도).
|
||||
|
||||
하지만 지금은 FastAPI 0.99.0 및 이후 버전에서는 JSON 스키마 2020-12를 사용하는 OpenAPI 3.1.0과 Swagger UI 5.0.0 및 이후 버전을 사용하며, 모든 것이 더 일관성을 띄고 예시는 JSON 스키마에 포함됩니다.
|
||||
|
||||
### Swagger UI와 OpenAPI-특화 `examples`
|
||||
|
||||
현재 (2023-08-26), Swagger UI가 다중 JSON 스키마 예시를 지원하지 않으며, 사용자는 다중 예시를 문서에 표시하는 방법이 없었습니다.
|
||||
|
||||
이를 해결하기 위해, FastAPI `0.103.0`은 새로운 매개변수인 `openapi_examples`를 포함하는 예전 **OpenAPI-특화** `examples` 필드를 선언하기 위한 **지원을 추가**했습니다. 🤓
|
||||
|
||||
### 요약
|
||||
|
||||
저는 역사를 그다지 좋아하는 편이 아니라고 말하고는 했지만... "기술 역사" 강의를 가르치는 지금의 저를 보세요.
|
||||
|
||||
요약하자면 **FastAPI 0.99.0 혹은 그 이상의 버전**으로 업그레이드하는 것은 많은 것들이 더 **쉽고, 일관적이며 직관적이게** 되며, 여러분은 이 모든 역사적 세부 사항을 알 필요가 없습니다. 😎
|
||||
@@ -36,7 +36,7 @@ Pydantic을 사용하여 본문을 선언하는 것과 같은 방식으로 다
|
||||
|
||||
`get_current_user`는 이전에 생성한 것과 동일한 `oauth2_scheme`과 종속성을 갖게 됩니다.
|
||||
|
||||
이전에 *경로 동작*에서 직접 수행했던 것과 동일하게 새 종속성 `get_current_user`는 하위 종속성 `oauth2_scheme`에서 `str`로 `token`을 수신합니다.
|
||||
이전에 *경로 작동*에서 직접 수행했던 것과 동일하게 새 종속성 `get_current_user`는 하위 종속성 `oauth2_scheme`에서 `str`로 `token`을 수신합니다.
|
||||
|
||||
=== "파이썬 3.7 이상"
|
||||
|
||||
|
||||
333
docs/tr/docs/tutorial/first-steps.md
Normal file
333
docs/tr/docs/tutorial/first-steps.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# İlk Adımlar
|
||||
|
||||
En sade FastAPI dosyası şu şekilde görünür:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Yukarıdaki içeriği bir `main.py` dosyasına kopyalayalım.
|
||||
|
||||
Uygulamayı çalıştıralım:
|
||||
|
||||
<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 "Not"
|
||||
`uvicorn main:app` komutunu şu şekilde açıklayabiliriz:
|
||||
|
||||
* `main`: dosya olan `main.py` (yani Python "modülü").
|
||||
* `app`: ise `main.py` dosyasının içerisinde `app = FastAPI()` satırında oluşturduğumuz `FastAPI` nesnesi.
|
||||
* `--reload`: kod değişikliklerinin ardından sunucuyu otomatik olarak yeniden başlatır. Bu parameteyi sadece geliştirme aşamasında kullanmalıyız.
|
||||
|
||||
Çıktı olarak şöyle bir satır ile karşılaşacaksınız:
|
||||
|
||||
```hl_lines="4"
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
Bu satır, yerel makinenizde uygulamanızın çalıştığı bağlantıyı gösterir.
|
||||
|
||||
### Kontrol Edelim
|
||||
|
||||
Tarayıcınızı açıp <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a> bağlantısına gidin.
|
||||
|
||||
Şu şekilde bir JSON yanıtı ile karşılaşacağız:
|
||||
|
||||
```JSON
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
### Etkileşimli API Dokümantasyonu
|
||||
|
||||
Şimdi <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> bağlantısını açalım.
|
||||
|
||||
<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> tarafından sağlanan otomatik etkileşimli bir API dokümantasyonu göreceğiz:
|
||||
|
||||

|
||||
|
||||
### Alternatif API Dokümantasyonu
|
||||
|
||||
Şimdi <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> bağlantısını açalım.
|
||||
|
||||
<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> tarafından sağlanan otomatik dokümantasyonu göreceğiz:
|
||||
|
||||

|
||||
|
||||
### OpenAPI
|
||||
|
||||
**FastAPI**, **OpenAPI** standardını kullanarak tüm API'ınızın tamamını tanımlayan bir "şema" oluşturur.
|
||||
|
||||
#### "Şema"
|
||||
|
||||
"Şema", bir şeyin tanımı veya açıklamasıdır. Geliştirilen koddan ziyade soyut bir açıklamadır.
|
||||
|
||||
#### API "Şeması"
|
||||
|
||||
Bu durumda, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a>, API şemasını nasıl tanımlayacağınızı belirten bir şartnamedir.
|
||||
|
||||
Bu şema tanımı, API yollarınızla birlikte yollarınızın aldığı olası parametreler gibi tanımlamaları içerir.
|
||||
|
||||
#### Veri "Şeması"
|
||||
|
||||
"Şema" terimi, JSON içeriği gibi bazı verilerin şeklini de ifade edebilir.
|
||||
|
||||
Bu durumda, JSON özellikleri ve sahip oldukları veri türleri gibi anlamlarına gelir.
|
||||
|
||||
#### OpenAPI ve JSON Şema
|
||||
|
||||
OpenAPI, API'niz için bir API şeması tanımlar. Ve bu şema, JSON veri şemaları standardı olan **JSON Şema** kullanılarak API'niz tarafından gönderilen ve alınan verilerin tanımlarını (veya "şemalarını") içerir.
|
||||
|
||||
#### `openapi.json` Dosyasına Göz At
|
||||
|
||||
Ham OpenAPI şemasının nasıl göründüğünü merak ediyorsanız, FastAPI otomatik olarak tüm API'ınızın tanımlamalarını içeren bir JSON (şeması) oluşturur.
|
||||
|
||||
Bu şemayı direkt olarak <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a> bağlantısından görüntüleyebilirsiniz.
|
||||
|
||||
Aşağıdaki gibi başlayan bir JSON ile karşılaşacaksınız:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
|
||||
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### OpenAPI Ne İşe Yarar?
|
||||
|
||||
OpenAPI şeması, FastAPI projesinde bulunan iki etkileşimli dokümantasyon sistemine güç veren şeydir.
|
||||
|
||||
OpenAPI'ya dayalı düzinelerce alternatif etkileşimli dokümantasyon aracı mevcuttur. **FastAPI** ile oluşturulmuş uygulamanıza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz.
|
||||
|
||||
Ayrıca, API'ınızla iletişim kuracak önyüz, mobil veya IoT uygulamaları gibi istemciler için otomatik olarak kod oluşturabilirsiniz.
|
||||
|
||||
## Adım Adım Özetleyelim
|
||||
|
||||
### Adım 1: `FastAPI`yı Projemize Dahil Edelim
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`FastAPI`, API'niz için tüm işlevselliği sağlayan bir Python sınıfıdır.
|
||||
|
||||
!!! note "Teknik Detaylar"
|
||||
`FastAPI` doğrudan `Starlette`'i miras alan bir sınıftır.
|
||||
|
||||
<a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>'in tüm işlevselliğini `FastAPI` ile de kullanabilirsiniz.
|
||||
|
||||
### Adım 2: Bir `FastAPI` "Örneği" Oluşturalım
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Burada `app` değişkeni `FastAPI` sınıfının bir örneği olacaktır.
|
||||
|
||||
Bu, tüm API'yı oluşturmak için ana etkileşim noktası olacaktır.
|
||||
|
||||
Bu `app` değişkeni, `uvicorn` komutunda atıfta bulunulan değişkenin ta kendisidir.
|
||||
|
||||
<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>
|
||||
|
||||
Uygulamanızı aşağıdaki gibi oluşturursanız:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
|
||||
Ve bunu `main.py` dosyasına yerleştirirseniz eğer `uvicorn` komutunu şu şekilde çalıştırabilirsiniz:
|
||||
|
||||
<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>
|
||||
|
||||
### Adım 3: Bir *Yol Operasyonu* Oluşturalım
|
||||
|
||||
#### <abbr title="Yol: Path">Yol</abbr>
|
||||
|
||||
Burada "yol" bağlantıda bulunan ilk `/` ile başlayan ve sonrasında gelen kısmı ifade eder.
|
||||
|
||||
Yani, şu şekilde bir bağlantıda:
|
||||
|
||||
```
|
||||
https://example.com/items/foo
|
||||
```
|
||||
|
||||
... yol şöyle olur:
|
||||
|
||||
```
|
||||
/items/foo
|
||||
```
|
||||
|
||||
!!! info "Bilgi"
|
||||
"Yol" genellikle "<abbr title="Endpoint: Bitim Noktası">endpoint</abbr>" veya "<abbr title="Route: Yönlendirme/Yön">route</abbr>" olarak adlandırılır.
|
||||
|
||||
Bir API oluştururken, "yol", "kaynaklar" ile "endişeleri" ayırmanın ana yöntemidir.
|
||||
|
||||
#### Operasyonlar
|
||||
|
||||
Burada "operasyon" HTTP "metodlarından" birini ifade eder.
|
||||
|
||||
Bunlardan biri:
|
||||
|
||||
* `POST`
|
||||
* `GET`
|
||||
* `PUT`
|
||||
* `DELETE`
|
||||
|
||||
...veya daha az kullanılan diğerleri:
|
||||
|
||||
* `OPTIONS`
|
||||
* `HEAD`
|
||||
* `PATCH`
|
||||
* `TRACE`
|
||||
|
||||
HTTP protokolünde, bu "metodlardan" birini (veya daha fazlasını) kullanarak her bir yol ile iletişim kurabilirsiniz.
|
||||
|
||||
---
|
||||
|
||||
API oluştururkan, belirli bir amaca hizmet eden belirli HTTP metodlarını kullanırsınız.
|
||||
|
||||
Normalde kullanılan:
|
||||
|
||||
* `POST`: veri oluşturmak.
|
||||
* `GET`: veri okumak.
|
||||
* `PUT`: veriyi güncellemek.
|
||||
* `DELETE`: veriyi silmek.
|
||||
|
||||
Bu nedenle, OpenAPI'da HTTP metodlarından her birine "operasyon" denir.
|
||||
|
||||
Biz de onları "**operasyonlar**" olarak adlandıracağız.
|
||||
|
||||
#### Bir *Yol Operasyonu Dekoratörü* Tanımlayalım
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`@app.get("/")` dekoratörü, **FastAPI**'a hemen altındaki fonksiyonun aşağıdaki durumlardan sorumlu olduğunu söyler:
|
||||
|
||||
* <abbr title="Bir HTTP GET metodu"><code>get</code> operasyonu</abbr> ile
|
||||
* `/` yoluna gelen istekler
|
||||
|
||||
!!! info "`@decorator` Bilgisi"
|
||||
Python'da `@something` sözdizimi "<abbr title="Decorator">dekoratör</abbr>" olarak adlandırılır.
|
||||
|
||||
Dekoratörler, dekoratif bir şapka gibi (sanırım terim buradan geliyor) fonksiyonların üzerlerine yerleştirilirler.
|
||||
|
||||
Bir "dekoratör" hemen altında bulunan fonksiyonu alır ve o fonksiyon ile bazı işlemler gerçekleştirir.
|
||||
|
||||
Bizim durumumuzda, kullandığımız dekoratör, **FastAPI**'a altındaki fonksiyonun `/` yoluna gelen `get` metodlu isteklerden sorumlu olduğunu söyler.
|
||||
|
||||
Bu bir **yol operasyonu dekoratörüdür**.
|
||||
|
||||
Ayrıca diğer operasyonları da kullanabilirsiniz:
|
||||
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
|
||||
Daha az kullanılanları da kullanabilirsiniz:
|
||||
|
||||
* `@app.options()`
|
||||
* `@app.head()`
|
||||
* `@app.patch()`
|
||||
* `@app.trace()`
|
||||
|
||||
!!! tip "İpucu"
|
||||
Her işlemi (HTTP metod) istediğiniz gibi kullanmakta özgürsünüz.
|
||||
|
||||
**FastAPI** herhangi bir özel amacı veya anlamı olması konusunda ısrarcı olmaz.
|
||||
|
||||
Buradaki bilgiler bir gereklilik değil, bir kılavuz olarak sunulmaktadır.
|
||||
|
||||
Mesela GraphQL kullanırkan genelde tüm işlemleri yalnızca `POST` operasyonunu kullanarak gerçekleştirirsiniz.
|
||||
|
||||
### Adım 4: **Yol Operasyonu Fonksiyonunu** Tanımlayın
|
||||
|
||||
Aşağıdaki, bizim **yol operasyonu fonksiyonumuzdur**:
|
||||
|
||||
* **yol**: `/`
|
||||
* **operasyon**: `get`
|
||||
* **fonksiyon**: "dekoratör"ün (`@app.get("/")`'in) altındaki fonksiyondur.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Bu bir Python fonksiyonudur.
|
||||
|
||||
Bu fonksiyon bir `GET` işlemi kullanılarak "`/`" bağlantısına bir istek geldiğinde **FastAPI** tarafından çağrılır.
|
||||
|
||||
Bu durumda bu fonksiyon bir `async` fonksiyondur.
|
||||
|
||||
---
|
||||
|
||||
Bu fonksiyonu `async def` yerine normal bir fonksiyon olarak da tanımlayabilirsiniz.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! note "Not"
|
||||
Eğer farkı bilmiyorsanız, [Async: *"Aceleniz mi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} sayfasını kontrol edebilirsiniz.
|
||||
|
||||
### Adım 5: İçeriği Geri Döndürün
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Bir `dict`, `list` veya `str`, `int` gibi tekil değerler döndürebilirsiniz.
|
||||
|
||||
Ayrıca, Pydantic modelleri de döndürebilirsiniz (bu konu ileriki aşamalarda irdelenecektir).
|
||||
|
||||
Otomatik olarak JSON'a dönüştürülecek (ORM'ler vb. dahil) başka birçok nesne ve model vardır. En beğendiklerinizi kullanmayı deneyin, yüksek ihtimalle destekleniyordur.
|
||||
|
||||
## Özet
|
||||
|
||||
* `FastAPI`'yı projemize dahil ettik.
|
||||
* Bir `app` örneği oluşturduk.
|
||||
* Bir **yol operasyonu dekoratörü** (`@app.get("/")` gibi) yazdık.
|
||||
* Bir **yol operasyonu fonksiyonu** (`def root(): ...` gibi) yazdık.
|
||||
* Geliştirme sunucumuzu (`uvicorn main:app --reload` gibi) çalıştırdık.
|
||||
@@ -1,336 +0,0 @@
|
||||
# İlk Adımlar
|
||||
|
||||
En basit FastAPI dosyası şu şekildedir:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Bunu bir `main.py` dosyasına kopyalayın.
|
||||
|
||||
Projeyi çalıştırın:
|
||||
|
||||
<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` komutu şunu ifade eder:
|
||||
|
||||
* `main`: `main.py` dosyası (the Python "module").
|
||||
* `app`: `main.py` dosyası içerisinde `app = FastAPI()` satırıyla oluşturulan nesne.
|
||||
* `--reload`: Kod değişikliği sonrasında sunucunun yeniden başlatılmasını sağlar. Yalnızca geliştirme için kullanın.
|
||||
|
||||
Çıktıda şu şekilde bir satır vardır:
|
||||
|
||||
```hl_lines="4"
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
Bu satır, yerel makinenizde uygulamanızın sunulduğu URL'yi gösterir.
|
||||
|
||||
### Kontrol Et
|
||||
|
||||
Tarayıcınızda <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a> adresini açın.
|
||||
|
||||
Bir JSON yanıtı göreceksiniz:
|
||||
|
||||
```JSON
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
### İnteraktif API dokümantasyonu
|
||||
|
||||
<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> adresine gidin.
|
||||
|
||||
Otomatik oluşturulmuş( <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> tarafından sağlanan) interaktif bir API dokümanı göreceksiniz:
|
||||
|
||||

|
||||
|
||||
### Alternatif API dokümantasyonu
|
||||
|
||||
Şimdi, <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> adresine gidin.
|
||||
|
||||
Otomatik oluşturulmuş(<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> tarafından sağlanan) bir API dokümanı göreceksiniz:
|
||||
|
||||

|
||||
|
||||
### OpenAPI
|
||||
|
||||
**FastAPI**, **OpenAPI** standardını kullanarak tüm API'lerinizi açıklayan bir "şema" oluşturur.
|
||||
|
||||
#### "Şema"
|
||||
|
||||
Bir "şema", bir şeyin tanımı veya açıklamasıdır. Soyut bir açıklamadır, uygulayan kod değildir.
|
||||
|
||||
#### API "şemaları"
|
||||
|
||||
Bu durumda, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a>, API şemasını nasıl tanımlayacağınızı belirten şartnamelerdir.
|
||||
|
||||
Bu şema tanımı, API yollarınızı, aldıkları olası parametreleri vb. içerir.
|
||||
|
||||
#### Data "şema"
|
||||
|
||||
"Şema" terimi, JSON içeriği gibi bazı verilerin şeklini de ifade edebilir.
|
||||
|
||||
Bu durumda, JSON öznitelikleri ve sahip oldukları veri türleri vb. anlamına gelir.
|
||||
|
||||
#### OpenAPI and JSON Şema
|
||||
|
||||
OpenAPI, API'niz için bir API şeması tanımlar. Ve bu şema, JSON veri şemaları standardı olan **JSON Şema** kullanılarak API'niz tarafından gönderilen ve alınan verilerin tanımlarını (veya "şemalarını") içerir.
|
||||
|
||||
#### `openapi.json` kontrol et
|
||||
|
||||
OpenAPI şemasının nasıl göründüğünü merak ediyorsanız, FastAPI otomatik olarak tüm API'nizin açıklamalarını içeren bir JSON (şema) oluşturur.
|
||||
|
||||
Doğrudan şu adreste görebilirsiniz: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
|
||||
|
||||
Aşağıdaki gibi bir şeyle başlayan bir JSON gösterecektir:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"openapi": "3.0.2",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
|
||||
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### OpenAPI ne içindir?
|
||||
|
||||
OpenAPI şeması, dahili olarak bulunan iki etkileşimli dokümantasyon sistemine güç veren şeydir.
|
||||
|
||||
Ve tamamen OpenAPI'ye dayalı düzinelerce alternatif vardır. **FastAPI** ile oluşturulmuş uygulamanıza bu alternatiflerden herhangi birini kolayca ekleyebilirsiniz.
|
||||
|
||||
API'nizle iletişim kuran istemciler için otomatik olarak kod oluşturmak için de kullanabilirsiniz. Örneğin, frontend, mobil veya IoT uygulamaları.
|
||||
|
||||
## Adım adım özet
|
||||
|
||||
### Adım 1: `FastAPI`yi içe aktarın
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`FastAPI`, API'niz için tüm fonksiyonları sağlayan bir Python sınıfıdır.
|
||||
|
||||
!!! note "Teknik Detaylar"
|
||||
`FastAPI` doğrudan `Starlette` kalıtım alan bir sınıftır.
|
||||
|
||||
Tüm <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> fonksiyonlarını `FastAPI` ile de kullanabilirsiniz.
|
||||
|
||||
### Adım 2: Bir `FastAPI` örneği oluşturun
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Burada `app` değişkeni `FastAPI` sınıfının bir örneği olacaktır.
|
||||
|
||||
Bu tüm API'yi oluşturmak için ana etkileşim noktası olacaktır.
|
||||
|
||||
`uvicorn` komutunda atıfta bulunulan `app` ile aynıdır.
|
||||
|
||||
<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>
|
||||
|
||||
Uygulamanızı aşağıdaki gibi oluşturursanız:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
|
||||
Ve bunu `main.py` dosyasına koyduktan sonra `uvicorn` komutunu şu şekilde çağırabilirsiniz:
|
||||
|
||||
<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>
|
||||
|
||||
### Adım 3: *Path işlemleri* oluşturmak
|
||||
|
||||
#### Path
|
||||
|
||||
Burada "Path" URL'de ilk "\" ile başlayan son bölümü ifade eder.
|
||||
|
||||
Yani, şu şekilde bir URL'de:
|
||||
|
||||
```
|
||||
https://example.com/items/foo
|
||||
```
|
||||
|
||||
... path şöyle olabilir:
|
||||
|
||||
```
|
||||
/items/foo
|
||||
```
|
||||
|
||||
!!! info
|
||||
Genellikle bir "path", "endpoint" veya "route" olarak adlandırılabilir.
|
||||
|
||||
Bir API oluştururken, "path", "resource" ile "concern" ayırmanın ana yoludur.
|
||||
|
||||
#### İşlemler
|
||||
|
||||
Burada "işlem" HTTP methodlarından birini ifade eder.
|
||||
|
||||
Onlardan biri:
|
||||
|
||||
* `POST`
|
||||
* `GET`
|
||||
* `PUT`
|
||||
* `DELETE`
|
||||
|
||||
... ve daha egzotik olanları:
|
||||
|
||||
* `OPTIONS`
|
||||
* `HEAD`
|
||||
* `PATCH`
|
||||
* `TRACE`
|
||||
|
||||
HTTP protokolünde, bu "methodlardan" birini (veya daha fazlasını) kullanarak her path ile iletişim kurabilirsiniz.
|
||||
|
||||
---
|
||||
|
||||
API'lerinizi oluştururkan, belirli bir işlemi gerçekleştirirken belirli HTTP methodlarını kullanırsınız.
|
||||
|
||||
Normalde kullanılan:
|
||||
|
||||
* `POST`: veri oluşturmak.
|
||||
* `GET`: veri okumak.
|
||||
* `PUT`: veriyi güncellemek.
|
||||
* `DELETE`: veriyi silmek.
|
||||
|
||||
Bu nedenle, OpenAPI'de HTTP methodlarından her birine "işlem" denir.
|
||||
|
||||
Bizde onlara "**işlemler**" diyeceğiz.
|
||||
|
||||
#### Bir *Path işlem decoratorleri* tanımlanmak
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`@app.get("/")` **FastAPI'ye** aşağıdaki fonksiyonun adresine giden istekleri işlemekten sorumlu olduğunu söyler:
|
||||
|
||||
* path `/`
|
||||
* <abbr title="an HTTP GET method"><code>get</code> işlemi</abbr> kullanılarak
|
||||
|
||||
|
||||
!!! info "`@decorator` Bilgisi"
|
||||
Python `@something` şeklinde ifadeleri "decorator" olarak adlandırır.
|
||||
|
||||
Decoratoru bir fonksiyonun üzerine koyarsınız. Dekoratif bir şapka gibi (Sanırım terim buradan gelmektedir).
|
||||
|
||||
Bir "decorator" fonksiyonu alır ve bazı işlemler gerçekleştir.
|
||||
|
||||
Bizim durumumzda decarator **FastAPI'ye** fonksiyonun bir `get` işlemi ile `/` pathine geldiğini söyler.
|
||||
|
||||
Bu **path işlem decoratordür**
|
||||
|
||||
Ayrıca diğer işlemleri de kullanabilirsiniz:
|
||||
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
|
||||
Ve daha egzotik olanları:
|
||||
|
||||
* `@app.options()`
|
||||
* `@app.head()`
|
||||
* `@app.patch()`
|
||||
* `@app.trace()`
|
||||
|
||||
!!! tip
|
||||
Her işlemi (HTTP method) istediğiniz gibi kullanmakta özgürsünüz.
|
||||
|
||||
**FastAPI** herhangi bir özel anlamı zorlamaz.
|
||||
|
||||
Buradaki bilgiler bir gereklilik değil, bir kılavuz olarak sunulmaktadır.
|
||||
|
||||
Örneğin, GraphQL kullanırkan normalde tüm işlemleri yalnızca `POST` işlemini kullanarak gerçekleştirirsiniz.
|
||||
|
||||
### Adım 4: **path işlem fonksiyonunu** tanımlayın
|
||||
|
||||
Aşağıdakiler bizim **path işlem fonksiyonlarımızdır**:
|
||||
|
||||
* **path**: `/`
|
||||
* **işlem**: `get`
|
||||
* **function**: "decorator"ün altındaki fonksiyondur (`@app.get("/")` altında).
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Bu bir Python fonksiyonudur.
|
||||
|
||||
Bir `GET` işlemi kullanarak "`/`" URL'sine bir istek geldiğinde **FastAPI** tarafından çağrılır.
|
||||
|
||||
Bu durumda bir `async` fonksiyonudur.
|
||||
|
||||
---
|
||||
|
||||
Bunu `async def` yerine normal bir fonksiyon olarakta tanımlayabilirsiniz.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
Eğer farkı bilmiyorsanız, [Async: *"Acelesi var?"*](../async.md#in-a-hurry){.internal-link target=_blank} kontrol edebilirsiniz.
|
||||
|
||||
### Adım 5: İçeriği geri döndürün
|
||||
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Bir `dict`, `list` döndürebilir veya `str`, `int` gibi tekil değerler döndürebilirsiniz.
|
||||
|
||||
Ayrıca, Pydantic modellerini de döndürebilirsiniz. (Bununla ilgili daha sonra ayrıntılı bilgi göreceksiniz.)
|
||||
|
||||
Otomatik olarak JSON'a dönüştürülecek(ORM'ler vb. dahil) başka birçok nesne ve model vardır. En beğendiklerinizi kullanmayı deneyin, yüksek ihtimalle destekleniyordur.
|
||||
|
||||
## Özet
|
||||
|
||||
* `FastAPI`'yi içe aktarın.
|
||||
* Bir `app` örneği oluşturun.
|
||||
* **path işlem decorator** yazın. (`@app.get("/")` gibi)
|
||||
* **path işlem fonksiyonu** yazın. (`def root(): ...` gibi)
|
||||
* Development sunucunuzu çalıştırın. (`uvicorn main:app --reload` gibi)
|
||||
254
docs/tr/docs/tutorial/path-params.md
Normal file
254
docs/tr/docs/tutorial/path-params.md
Normal file
@@ -0,0 +1,254 @@
|
||||
# Yol Parametreleri
|
||||
|
||||
Yol "parametrelerini" veya "değişkenlerini" Python <abbr title="String Biçimleme: Format String">string biçimlemede</abbr> kullanılan sözdizimi ile tanımlayabilirsiniz.
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!../../../docs_src/path_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
Yol parametresi olan `item_id`'nin değeri, fonksiyonunuza `item_id` argümanı olarak aktarılacaktır.
|
||||
|
||||
Eğer bu örneği çalıştırıp <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> sayfasına giderseniz, şöyle bir çıktı ile karşılaşırsınız:
|
||||
|
||||
```JSON
|
||||
{"item_id":"foo"}
|
||||
```
|
||||
|
||||
## Tip İçeren Yol Parametreleri
|
||||
|
||||
Standart Python tip belirteçlerini kullanarak yol parametresinin tipini fonksiyonun içerisinde tanımlayabilirsiniz.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/path_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
Bu durumda, `item_id` bir `int` olarak tanımlanacaktır.
|
||||
|
||||
!!! check "Ek bilgi"
|
||||
Bu sayede, fonksiyon içerisinde hata denetimi, kod tamamlama gibi konularda editör desteğine kavuşacaksınız.
|
||||
|
||||
## Veri <abbr title="Dönüşüm: serialization, parsing ve marshalling olarak da biliniyor">Dönüşümü</abbr>
|
||||
|
||||
Eğer bu örneği çalıştırıp tarayıcınızda <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a> sayfasını açarsanız, şöyle bir yanıt ile karşılaşırsınız:
|
||||
|
||||
```JSON
|
||||
{"item_id":3}
|
||||
```
|
||||
|
||||
!!! check "Ek bilgi"
|
||||
Dikkatinizi çekerim ki, fonksiyonunuzun aldığı (ve döndürdüğü) değer olan `3` bir string `"3"` değil aksine bir Python `int`'idir.
|
||||
|
||||
Bu tanımlamayla birlikte, **FastAPI** size otomatik istek <abbr title="HTTP isteği ile birlikte gelen string'i Python verisine dönüştürme">"ayrıştırma"</abbr> özelliği sağlar.
|
||||
|
||||
## Veri Doğrulama
|
||||
|
||||
Eğer tarayıcınızda <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> sayfasını açarsanız, şuna benzer güzel bir HTTP hatası ile karşılaşırsınız:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": [
|
||||
"path",
|
||||
"item_id"
|
||||
],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo",
|
||||
"url": "https://errors.pydantic.dev/2.1/v/int_parsing"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Çünkü burada `item_id` yol parametresi `int` tipinde bir değer beklerken `"foo"` yani `string` tipinde bir değer almıştı.
|
||||
|
||||
Aynı hata <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> sayfasında olduğu gibi `int` yerine `float` bir değer verseydik de ortaya çıkardı.
|
||||
|
||||
!!! check "Ek bilgi"
|
||||
Böylece, aynı Python tip tanımlaması ile birlikte, **FastAPI** veri doğrulama özelliği sağlar.
|
||||
|
||||
Dikkatinizi çekerim ki, karşılaştığınız hata, doğrulamanın geçersiz olduğu mutlak noktayı da açık bir şekilde belirtiyor.
|
||||
|
||||
Bu özellik, API'ınızla iletişime geçen kodu geliştirirken ve ayıklarken inanılmaz derecede yararlı olacaktır.
|
||||
|
||||
## Dokümantasyon
|
||||
|
||||
Ayrıca, tarayıcınızı <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> adresinde açarsanız, aşağıdaki gibi otomatik ve interaktif bir API dökümantasyonu ile karşılaşırsınız:
|
||||
|
||||
<img src="/img/tutorial/path-params/image01.png">
|
||||
|
||||
!!! check "Ek bilgi"
|
||||
Üstelik, sadece aynı Python tip tanımlaması ile, **FastAPI** size otomatik ve interaktif (Swagger UI ile entegre) bir dokümantasyon sağlar.
|
||||
|
||||
Dikkatinizi çekerim ki, yol parametresi integer olarak tanımlanmıştır.
|
||||
|
||||
## Standartlara Dayalı Avantajlar, Alternatif Dokümantasyon
|
||||
|
||||
Oluşturulan şema <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a> standardına uygun olduğu için birçok uyumlu araç mevcuttur.
|
||||
|
||||
Bu sayede, **FastAPI**'ın bizzat kendisi <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> sayfasından erişebileceğiniz alternatif (ReDoc kullanan) bir API dokümantasyonu sağlar:
|
||||
|
||||
<img src="/img/tutorial/path-params/image02.png">
|
||||
|
||||
Aynı şekilde, farklı diller için kod türetme araçları da dahil olmak üzere çok sayıda uyumlu araç bulunur.
|
||||
|
||||
## Pydantic
|
||||
|
||||
Tüm veri doğrulamaları <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> tarafından arka planda gerçekleştirilir, bu sayede tüm avantajlardan faydalanabilirsiniz. Böylece, emin ellerde olduğunuzu hissedebilirsiniz.
|
||||
|
||||
Aynı tip tanımlamalarını `str`, `float`, `bool` ve diğer karmaşık veri tipleri ile kullanma imkanınız vardır.
|
||||
|
||||
Bunlardan birkaçı, bu eğitimin ileriki bölümlerinde irdelenmiştir.
|
||||
|
||||
## Sıralama Önem Arz Eder
|
||||
|
||||
*Yol operasyonları* tasarlarken sabit yol barındıran durumlar ile karşılaşabilirsiniz.
|
||||
|
||||
Farz edelim ki `/users/me` yolu geçerli kullanıcı hakkında bilgi almak için kullanılıyor olsun.
|
||||
|
||||
Benzer şekilde `/users/{user_id}` gibi tanımlanmış ve belirli bir kullanıcı hakkında veri almak için kullanıcının ID bilgisini kullanan bir yolunuz da mevcut olabilir.
|
||||
|
||||
*Yol operasyonları* sıralı bir şekilde gözden geçirildiğinden dolayı `/users/me` yolunun `/users/{user_id}` yolundan önce tanımlanmış olmasından emin olmanız gerekmektedir:
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!../../../docs_src/path_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
Aksi halde, `/users/{user_id}` yolu `"me"` değerinin `user_id` parametresi için gönderildiğini "düşünerek" `/users/me` ile de eşleşir.
|
||||
|
||||
Benzer şekilde, bir yol operasyonunu yeniden tanımlamanız mümkün değildir:
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!../../../docs_src/path_params/tutorial003b.py!}
|
||||
```
|
||||
|
||||
Yol, ilk kısım ile eşleştiğinden dolayı her koşulda ilk yol operasyonu kullanılacaktır.
|
||||
|
||||
## Ön Tanımlı Değerler
|
||||
|
||||
Eğer *yol parametresi* alan bir *yol operasyonunuz* varsa ve alabileceği *yol parametresi* değerlerinin ön tanımlı olmasını istiyorsanız, standart Python <abbr title="Enumeration">`Enum`</abbr> tipini kullanabilirsiniz.
|
||||
|
||||
### Bir `Enum` Sınıfı Oluşturalım
|
||||
|
||||
`Enum` sınıfını projemize dahil edip `str` ile `Enum` sınıflarını miras alan bir alt sınıf yaratalım.
|
||||
|
||||
`str` sınıfı miras alındığından dolayı, API dokümanı, değerlerin `string` tipinde olması gerektiğini anlayabilecek ve doğru bir şekilde işlenecektir.
|
||||
|
||||
Sonrasında, sınıf içerisinde, mevcut ve geçerli değerler olacak olan sabit değerli özelliklerini oluşturalım:
|
||||
|
||||
```Python hl_lines="1 6-9"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
!!! info "Bilgi"
|
||||
3.4 sürümünden beri <a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">enumerationlar (ya da enumlar) Python'da mevcuttur</a>.
|
||||
|
||||
!!! tip "İpucu"
|
||||
Merak ediyorsanız söyleyeyim, "AlexNet", "ResNet" ve "LeNet" isimleri Makine Öğrenmesi <abbr title="Teknik olarak, Derin Öğrenme model mimarileri">modellerini</abbr> temsil eder.
|
||||
|
||||
### Bir *Yol Parametresi* Tanımlayalım
|
||||
|
||||
Sonrasında, yarattığımız enum sınıfını (`ModelName`) kullanarak tip belirteci aracılığıyla bir *yol parametresi* oluşturalım:
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
### Dokümana Göz Atalım
|
||||
|
||||
*Yol parametresi* için mevcut değerler ön tanımlı olduğundan dolayı, interaktif döküman onları güzel bir şekilde gösterebilir:
|
||||
|
||||
<img src="/img/tutorial/path-params/image03.png">
|
||||
|
||||
### Python *Enumerationları* ile Çalışmak
|
||||
|
||||
*Yol parametresinin* değeri bir *enumeration üyesi* olacaktır.
|
||||
|
||||
#### *Enumeration Üyelerini* Karşılaştıralım
|
||||
|
||||
Parametreyi, yarattığınız enum olan `ModelName` içerisindeki *enumeration üyesi* ile karşılaştırabilirsiniz:
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
#### *Enumeration Değerini* Edinelim
|
||||
|
||||
`model_name.value` veya genel olarak `your_enum_member.value` tanımlarını kullanarak (bu durumda bir `str` olan) gerçek değere ulaşabilirsiniz:
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
!!! tip "İpucu"
|
||||
`"lenet"` değerine `ModelName.lenet.value` tanımı ile de ulaşabilirsiniz.
|
||||
|
||||
#### *Enumeration Üyelerini* Döndürelim
|
||||
|
||||
JSON gövdesine (örneğin bir `dict`) gömülü olsalar bile *yol operasyonundaki* *enum üyelerini* döndürebilirsiniz.
|
||||
|
||||
Bu üyeler istemciye iletilmeden önce kendilerine karşılık gelen değerlerine (bu durumda string) dönüştürüleceklerdir:
|
||||
|
||||
```Python hl_lines="18 21 23"
|
||||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
İstemci tarafında şuna benzer bir JSON yanıtı ile karşılaşırsınız:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"model_name": "alexnet",
|
||||
"message": "Deep Learning FTW!"
|
||||
}
|
||||
```
|
||||
|
||||
## Yol İçeren Yol Parametreleri
|
||||
|
||||
Farz edelim ki elinizde `/files/{file_path}` isminde bir *yol operasyonu* var.
|
||||
|
||||
Fakat `file_path` değerinin `home/johndoe/myfile.txt` gibi bir *yol* barındırmasını istiyorsunuz.
|
||||
|
||||
Sonuç olarak, oluşturmak istediğin URL `/files/home/johndoe/myfile.txt` gibi bir şey olacaktır.
|
||||
|
||||
### OpenAPI Desteği
|
||||
|
||||
Test etmesi ve tanımlaması zor senaryolara sebebiyet vereceğinden dolayı OpenAPI, *yol* barındıran *yol parametrelerini* tanımlayacak bir çözüm sunmuyor.
|
||||
|
||||
Ancak bunu, Starlette kütüphanesinin dahili araçlarından birini kullanarak **FastAPI**'da gerçekleştirebilirsiniz.
|
||||
|
||||
Parametrenin bir yol içermesi gerektiğini belirten herhangi bir doküman eklemememize rağmen dokümanlar yine de çalışacaktır.
|
||||
|
||||
### Yol Dönüştürücü
|
||||
|
||||
Direkt olarak Starlette kütüphanesinden gelen bir opsiyon sayesinde aşağıdaki gibi *yol* içeren bir *yol parametresi* bağlantısı tanımlayabilirsiniz:
|
||||
|
||||
```
|
||||
/files/{file_path:path}
|
||||
```
|
||||
|
||||
Bu durumda, parametrenin adı `file_path` olacaktır ve son kısım olan `:path` kısmı, parametrenin herhangi bir *yol* ile eşleşmesi gerektiğini belirtecektir.
|
||||
|
||||
Böylece şunun gibi bir kullanım yapabilirsiniz:
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/path_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! tip "İpucu"
|
||||
Parametrenin başında `/home/johndoe/myfile.txt` yolunda olduğu gibi (`/`) işareti ile birlikte kullanmanız gerektiği durumlar olabilir.
|
||||
|
||||
Bu durumda, URL, `files` ile `home` arasında iki eğik çizgiye (`//`) sahip olup `/files//home/johndoe/myfile.txt` gibi gözükecektir.
|
||||
|
||||
## Özet
|
||||
|
||||
**FastAPI** ile kısa, sezgisel ve standart Python tip tanımlamaları kullanarak şunları elde edersiniz:
|
||||
|
||||
* Editör desteği: hata denetimi, otomatik tamamlama, vb.
|
||||
* Veri "<abbr title="HTTP isteği ile birlikte gelen string'i Python verisine dönüştürme">dönüştürme</abbr>"
|
||||
* Veri doğrulama
|
||||
* API tanımlamaları ve otomatik dokümantasyon
|
||||
|
||||
Ve sadece, bunları bir kez tanımlamanız yeterli.
|
||||
|
||||
Diğer frameworkler ile karşılaştırıldığında (ham performans dışında), üstte anlatılan durum muhtemelen **FastAPI**'ın göze çarpan başlıca avantajıdır.
|
||||
227
docs/tr/docs/tutorial/query-params.md
Normal file
227
docs/tr/docs/tutorial/query-params.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# Sorgu Parametreleri
|
||||
|
||||
Fonksiyonda yol parametrelerinin parçası olmayan diğer tanımlamalar otomatik olarak "sorgu" parametresi olarak yorumlanır.
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!../../../docs_src/query_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
Sorgu, bağlantıdaki `?` kısmından sonra gelen ve `&` işareti ile ayrılan anahtar-değer çiftlerinin oluşturduğu bir kümedir.
|
||||
|
||||
Örneğin, aşağıdaki bağlantıda:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/?skip=0&limit=10
|
||||
```
|
||||
|
||||
...sorgu parametreleri şunlardır:
|
||||
|
||||
* `skip`: değeri `0`'dır
|
||||
* `limit`: değeri `10`'dır
|
||||
|
||||
Parametreler bağlantının bir parçası oldukları için doğal olarak string olarak değerlendirilirler.
|
||||
|
||||
Fakat, Python tipleri ile tanımlandıkları zaman (yukarıdaki örnekte `int` oldukları gibi), parametreler o tiplere dönüştürülür ve o tipler çerçevesinde doğrulanırlar.
|
||||
|
||||
Yol parametreleri için geçerli olan her türlü işlem aynı şekilde sorgu parametreleri için de geçerlidir:
|
||||
|
||||
* Editör desteği (şüphesiz)
|
||||
* Veri "<abbr title="HTTP isteği ile birlikte gelen string'i Python verisine dönüştürme">ayrıştırma</abbr>"
|
||||
* Veri doğrulama
|
||||
* Otomatik dokümantasyon
|
||||
|
||||
## Varsayılanlar
|
||||
|
||||
Sorgu parametreleri, adres yolunun sabit bir parçası olmadıklarından dolayı isteğe bağlı ve varsayılan değere sahip olabilirler.
|
||||
|
||||
Yukarıdaki örnekte `skip=0` ve `limit=10` varsayılan değere sahiplerdir.
|
||||
|
||||
Yani, aşağıdaki bağlantıya gitmek:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/
|
||||
```
|
||||
|
||||
şu adrese gitmek ile aynı etkiye sahiptir:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/?skip=0&limit=10
|
||||
```
|
||||
|
||||
Ancak, mesela şöyle bir adresi ziyaret ederseniz:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/?skip=20
|
||||
```
|
||||
|
||||
Fonksiyonunuzdaki parametre değerleri aşağıdaki gibi olacaktır:
|
||||
|
||||
* `skip=20`: çünkü bağlantıda böyle tanımlandı.
|
||||
* `limit=10`: çünkü varsayılan değer buydu.
|
||||
|
||||
## İsteğe Bağlı Parametreler
|
||||
|
||||
Aynı şekilde, varsayılan değerlerini `None` olarak atayarak isteğe bağlı parametreler tanımlayabilirsiniz:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
Bu durumda, `q` fonksiyon parametresi isteğe bağlı olacak ve varsayılan değer olarak `None` alacaktır.
|
||||
|
||||
!!! check "Ek bilgi"
|
||||
Ayrıca, dikkatinizi çekerim ki; **FastAPI**, `item_id` parametresinin bir yol parametresi olduğunu ve `q` parametresinin yol değil bir sorgu parametresi olduğunu fark edecek kadar beceriklidir.
|
||||
|
||||
## Sorgu Parametresi Tip Dönüşümü
|
||||
|
||||
Aşağıda görüldüğü gibi dönüştürülmek üzere `bool` tipleri de tanımlayabilirsiniz:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
Bu durumda, eğer şu adrese giderseniz:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo?short=1
|
||||
```
|
||||
|
||||
veya
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo?short=True
|
||||
```
|
||||
|
||||
veya
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo?short=true
|
||||
```
|
||||
|
||||
veya
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo?short=on
|
||||
```
|
||||
|
||||
veya
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo?short=yes
|
||||
```
|
||||
|
||||
veya adres, herhangi farklı bir harf varyasyonu içermesi durumuna rağmen (büyük harf, sadece baş harfi büyük kelime, vb.) fonksiyonunuz, `bool` tipli `short` parametresini `True` olarak algılayacaktır. Aksi halde `False` olarak algılanacaktır.
|
||||
|
||||
|
||||
## Çoklu Yol ve Sorgu Parametreleri
|
||||
|
||||
**FastAPI** neyin ne olduğunu ayırt edebileceğinden dolayı aynı anda birden fazla yol ve sorgu parametresi tanımlayabilirsiniz.
|
||||
|
||||
Ve parametreleri, herhangi bir sıraya koymanıza da gerek yoktur.
|
||||
|
||||
İsimlerine göre belirleneceklerdir:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="6 8"
|
||||
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="8 10"
|
||||
{!> ../../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
## Zorunlu Sorgu Parametreleri
|
||||
|
||||
Türü yol olmayan bir parametre (şu ana kadar sadece sorgu parametrelerini gördük) için varsayılan değer tanımlarsanız o parametre zorunlu olmayacaktır.
|
||||
|
||||
Parametre için belirli bir değer atamak istemeyip parametrenin sadece isteğe bağlı olmasını istiyorsanız değerini `None` olarak atayabilirsiniz.
|
||||
|
||||
Fakat, bir sorgu parametresini zorunlu yapmak istiyorsanız varsayılan bir değer atamamanız yeterli olacaktır:
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!../../../docs_src/query_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
Burada `needy` parametresi `str` tipinden oluşan zorunlu bir sorgu parametresidir.
|
||||
|
||||
Eğer tarayıcınızda şu bağlantıyı:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo-item
|
||||
```
|
||||
|
||||
...`needy` parametresini eklemeden açarsanız şuna benzer bir hata ile karşılaşırsınız:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": [
|
||||
"query",
|
||||
"needy"
|
||||
],
|
||||
"msg": "Field required",
|
||||
"input": null,
|
||||
"url": "https://errors.pydantic.dev/2.1/v/missing"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`needy` zorunlu bir parametre olduğundan dolayı bağlantıda tanımlanması gerekir:
|
||||
|
||||
```
|
||||
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
|
||||
```
|
||||
|
||||
...bu iş görür:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item_id": "foo-item",
|
||||
"needy": "sooooneedy"
|
||||
}
|
||||
```
|
||||
|
||||
Ve elbette, bazı parametreleri zorunlu, bazılarını varsayılan değerli ve bazılarını tamamen opsiyonel olarak tanımlayabilirsiniz:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/query_params/tutorial006.py!}
|
||||
```
|
||||
|
||||
Bu durumda, 3 tane sorgu parametresi var olacaktır:
|
||||
|
||||
* `needy`, zorunlu bir `str`.
|
||||
* `skip`, varsayılan değeri `0` olan bir `int`.
|
||||
* `limit`, isteğe bağlı bir `int`.
|
||||
|
||||
!!! tip "İpucu"
|
||||
Ayrıca, [Yol Parametrelerinde](path-params.md#predefined-values){.internal-link target=_blank} de kullanıldığı şekilde `Enum` sınıfından faydalanabilirsiniz.
|
||||
5
docs/zh-hant/docs/learn/index.md
Normal file
5
docs/zh-hant/docs/learn/index.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# 學習
|
||||
|
||||
以下是學習 FastAPI 的入門介紹和教學。
|
||||
|
||||
你可以將其視為一本**書籍**或一門**課程**,這是**官方**認可並推薦的 FastAPI 學習方式。 😎
|
||||
27
docs_src/dependencies/tutorial008c.py
Normal file
27
docs_src/dependencies/tutorial008c.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except InternalError:
|
||||
print("Oops, we didn't raise again, Britney 😱")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: str = Depends(get_username)):
|
||||
if item_id == "portal-gun":
|
||||
raise InternalError(
|
||||
f"The portal gun is too dangerous to be owned by {username}"
|
||||
)
|
||||
if item_id != "plumbus":
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Item not found, there's only a plumbus here"
|
||||
)
|
||||
return item_id
|
||||
28
docs_src/dependencies/tutorial008c_an.py
Normal file
28
docs_src/dependencies/tutorial008c_an.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except InternalError:
|
||||
print("Oops, we didn't raise again, Britney 😱")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id == "portal-gun":
|
||||
raise InternalError(
|
||||
f"The portal gun is too dangerous to be owned by {username}"
|
||||
)
|
||||
if item_id != "plumbus":
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Item not found, there's only a plumbus here"
|
||||
)
|
||||
return item_id
|
||||
29
docs_src/dependencies/tutorial008c_an_py39.py
Normal file
29
docs_src/dependencies/tutorial008c_an_py39.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except InternalError:
|
||||
print("Oops, we didn't raise again, Britney 😱")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id == "portal-gun":
|
||||
raise InternalError(
|
||||
f"The portal gun is too dangerous to be owned by {username}"
|
||||
)
|
||||
if item_id != "plumbus":
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Item not found, there's only a plumbus here"
|
||||
)
|
||||
return item_id
|
||||
28
docs_src/dependencies/tutorial008d.py
Normal file
28
docs_src/dependencies/tutorial008d.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except InternalError:
|
||||
print("We don't swallow the internal error here, we raise again 😎")
|
||||
raise
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: str = Depends(get_username)):
|
||||
if item_id == "portal-gun":
|
||||
raise InternalError(
|
||||
f"The portal gun is too dangerous to be owned by {username}"
|
||||
)
|
||||
if item_id != "plumbus":
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Item not found, there's only a plumbus here"
|
||||
)
|
||||
return item_id
|
||||
29
docs_src/dependencies/tutorial008d_an.py
Normal file
29
docs_src/dependencies/tutorial008d_an.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except InternalError:
|
||||
print("We don't swallow the internal error here, we raise again 😎")
|
||||
raise
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id == "portal-gun":
|
||||
raise InternalError(
|
||||
f"The portal gun is too dangerous to be owned by {username}"
|
||||
)
|
||||
if item_id != "plumbus":
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Item not found, there's only a plumbus here"
|
||||
)
|
||||
return item_id
|
||||
30
docs_src/dependencies/tutorial008d_an_py39.py
Normal file
30
docs_src/dependencies/tutorial008d_an_py39.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class InternalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except InternalError:
|
||||
print("We don't swallow the internal error here, we raise again 😎")
|
||||
raise
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id == "portal-gun":
|
||||
raise InternalError(
|
||||
f"The portal gun is too dangerous to be owned by {username}"
|
||||
)
|
||||
if item_id != "plumbus":
|
||||
raise HTTPException(
|
||||
status_code=404, detail="Item not found, there's only a plumbus here"
|
||||
)
|
||||
return item_id
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.109.2"
|
||||
__version__ = "0.110.0"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ class FastAPI(Starlette):
|
||||
browser tabs open). Or if you want to leave fixed the possible URLs.
|
||||
|
||||
If the servers `list` is not provided, or is an empty `list`, the
|
||||
default value would be a a `dict` with a `url` value of `/`.
|
||||
default value would be a `dict` with a `url` value of `/`.
|
||||
|
||||
Each item in the `list` is a `dict` containing:
|
||||
|
||||
|
||||
@@ -216,19 +216,14 @@ def get_request_handler(
|
||||
actual_response_class = response_class
|
||||
|
||||
async def app(request: Request) -> Response:
|
||||
exception_to_reraise: Optional[Exception] = None
|
||||
response: Union[Response, None] = None
|
||||
async with AsyncExitStack() as async_exit_stack:
|
||||
# TODO: remove this scope later, after a few releases
|
||||
# This scope fastapi_astack is no longer used by FastAPI, kept for
|
||||
# compatibility, just in case
|
||||
request.scope["fastapi_astack"] = async_exit_stack
|
||||
async with AsyncExitStack() as file_stack:
|
||||
try:
|
||||
body: Any = None
|
||||
if body_field:
|
||||
if is_body_form:
|
||||
body = await request.form()
|
||||
async_exit_stack.push_async_callback(body.close)
|
||||
file_stack.push_async_callback(body.close)
|
||||
else:
|
||||
body_bytes = await request.body()
|
||||
if body_bytes:
|
||||
@@ -260,18 +255,17 @@ def get_request_handler(
|
||||
],
|
||||
body=e.doc,
|
||||
)
|
||||
exception_to_reraise = validation_error
|
||||
raise validation_error from e
|
||||
except HTTPException as e:
|
||||
exception_to_reraise = e
|
||||
except HTTPException:
|
||||
# If a middleware raises an HTTPException, it should be raised again
|
||||
raise
|
||||
except Exception as e:
|
||||
http_error = HTTPException(
|
||||
status_code=400, detail="There was an error parsing the body"
|
||||
)
|
||||
exception_to_reraise = http_error
|
||||
raise http_error from e
|
||||
try:
|
||||
errors: List[Any] = []
|
||||
async with AsyncExitStack() as async_exit_stack:
|
||||
solved_result = await solve_dependencies(
|
||||
request=request,
|
||||
dependant=dependant,
|
||||
@@ -280,59 +274,53 @@ def get_request_handler(
|
||||
async_exit_stack=async_exit_stack,
|
||||
)
|
||||
values, errors, background_tasks, sub_response, _ = solved_result
|
||||
except Exception as e:
|
||||
exception_to_reraise = e
|
||||
raise e
|
||||
if not errors:
|
||||
raw_response = await run_endpoint_function(
|
||||
dependant=dependant, values=values, is_coroutine=is_coroutine
|
||||
)
|
||||
if isinstance(raw_response, Response):
|
||||
if raw_response.background is None:
|
||||
raw_response.background = background_tasks
|
||||
response = raw_response
|
||||
else:
|
||||
response_args: Dict[str, Any] = {"background": background_tasks}
|
||||
# If status_code was set, use it, otherwise use the default from the
|
||||
# response class, in the case of redirect it's 307
|
||||
current_status_code = (
|
||||
status_code if status_code else sub_response.status_code
|
||||
)
|
||||
if current_status_code is not None:
|
||||
response_args["status_code"] = current_status_code
|
||||
if sub_response.status_code:
|
||||
response_args["status_code"] = sub_response.status_code
|
||||
content = await serialize_response(
|
||||
field=response_field,
|
||||
response_content=raw_response,
|
||||
include=response_model_include,
|
||||
exclude=response_model_exclude,
|
||||
by_alias=response_model_by_alias,
|
||||
exclude_unset=response_model_exclude_unset,
|
||||
exclude_defaults=response_model_exclude_defaults,
|
||||
exclude_none=response_model_exclude_none,
|
||||
is_coroutine=is_coroutine,
|
||||
)
|
||||
response = actual_response_class(content, **response_args)
|
||||
if not is_body_allowed_for_status_code(response.status_code):
|
||||
response.body = b""
|
||||
response.headers.raw.extend(sub_response.headers.raw)
|
||||
if errors:
|
||||
validation_error = RequestValidationError(
|
||||
_normalize_errors(errors), body=body
|
||||
)
|
||||
exception_to_reraise = validation_error
|
||||
raise validation_error
|
||||
else:
|
||||
try:
|
||||
raw_response = await run_endpoint_function(
|
||||
dependant=dependant, values=values, is_coroutine=is_coroutine
|
||||
)
|
||||
except Exception as e:
|
||||
exception_to_reraise = e
|
||||
raise e
|
||||
if isinstance(raw_response, Response):
|
||||
if raw_response.background is None:
|
||||
raw_response.background = background_tasks
|
||||
response = raw_response
|
||||
else:
|
||||
response_args: Dict[str, Any] = {"background": background_tasks}
|
||||
# If status_code was set, use it, otherwise use the default from the
|
||||
# response class, in the case of redirect it's 307
|
||||
current_status_code = (
|
||||
status_code if status_code else sub_response.status_code
|
||||
)
|
||||
if current_status_code is not None:
|
||||
response_args["status_code"] = current_status_code
|
||||
if sub_response.status_code:
|
||||
response_args["status_code"] = sub_response.status_code
|
||||
content = await serialize_response(
|
||||
field=response_field,
|
||||
response_content=raw_response,
|
||||
include=response_model_include,
|
||||
exclude=response_model_exclude,
|
||||
by_alias=response_model_by_alias,
|
||||
exclude_unset=response_model_exclude_unset,
|
||||
exclude_defaults=response_model_exclude_defaults,
|
||||
exclude_none=response_model_exclude_none,
|
||||
is_coroutine=is_coroutine,
|
||||
)
|
||||
response = actual_response_class(content, **response_args)
|
||||
if not is_body_allowed_for_status_code(response.status_code):
|
||||
response.body = b""
|
||||
response.headers.raw.extend(sub_response.headers.raw)
|
||||
# This exception was possibly handled by the dependency but it should
|
||||
# still bubble up so that the ServerErrorMiddleware can return a 500
|
||||
# or the ExceptionMiddleware can catch and handle any other exceptions
|
||||
if exception_to_reraise:
|
||||
raise exception_to_reraise
|
||||
assert response is not None, "An error occurred while generating the request"
|
||||
if response is None:
|
||||
raise FastAPIError(
|
||||
"No response object was returned. There's a high chance that the "
|
||||
"application code is raising an exception and a dependency with yield "
|
||||
"has a block with a bare except, or a block with except Exception, "
|
||||
"and is not raising the exception again. Read more about it in the "
|
||||
"docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
|
||||
)
|
||||
return response
|
||||
|
||||
return app
|
||||
|
||||
@@ -55,6 +55,7 @@ async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
|
||||
yield state["/async_raise"]
|
||||
except AsyncDependencyError:
|
||||
errors.append("/async_raise")
|
||||
raise
|
||||
finally:
|
||||
state["/async_raise"] = "asyncgen raise finalized"
|
||||
|
||||
@@ -65,6 +66,7 @@ def generator_state_try(state: Dict[str, str] = Depends(get_state)):
|
||||
yield state["/sync_raise"]
|
||||
except SyncDependencyError:
|
||||
errors.append("/sync_raise")
|
||||
raise
|
||||
finally:
|
||||
state["/sync_raise"] = "generator raise finalized"
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ async def get_database():
|
||||
fake_database.update(temp_database)
|
||||
except HTTPException:
|
||||
state["except"] = True
|
||||
raise
|
||||
finally:
|
||||
state["finally"] = True
|
||||
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from docs_src.dependencies.tutorial008b_an import app
|
||||
|
||||
client = TestClient(app)
|
||||
from ...utils import needs_py39
|
||||
|
||||
|
||||
def test_get_no_item():
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008b_an_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found"}
|
||||
|
||||
|
||||
def test_owner_error():
|
||||
@needs_py39
|
||||
def test_owner_error(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 400, response.text
|
||||
assert response.json() == {"detail": "Owner error: Rick"}
|
||||
|
||||
|
||||
def test_get_item():
|
||||
@needs_py39
|
||||
def test_get_item(client: TestClient):
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"}
|
||||
|
||||
38
tests/test_tutorial/test_dependencies/test_tutorial008c.py
Normal file
38
tests/test_tutorial/test_dependencies/test_tutorial008c.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import pytest
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008c import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
|
||||
|
||||
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == "plumbus"
|
||||
|
||||
|
||||
def test_fastapi_error(client: TestClient):
|
||||
with pytest.raises(FastAPIError) as exc_info:
|
||||
client.get("/items/portal-gun")
|
||||
assert "No response object was returned" in exc_info.value.args[0]
|
||||
|
||||
|
||||
def test_internal_server_error():
|
||||
from docs_src.dependencies.tutorial008c import app
|
||||
|
||||
client = TestClient(app, raise_server_exceptions=False)
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 500, response.text
|
||||
assert response.text == "Internal Server Error"
|
||||
@@ -0,0 +1,38 @@
|
||||
import pytest
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008c_an import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
|
||||
|
||||
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == "plumbus"
|
||||
|
||||
|
||||
def test_fastapi_error(client: TestClient):
|
||||
with pytest.raises(FastAPIError) as exc_info:
|
||||
client.get("/items/portal-gun")
|
||||
assert "No response object was returned" in exc_info.value.args[0]
|
||||
|
||||
|
||||
def test_internal_server_error():
|
||||
from docs_src.dependencies.tutorial008c_an import app
|
||||
|
||||
client = TestClient(app, raise_server_exceptions=False)
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 500, response.text
|
||||
assert response.text == "Internal Server Error"
|
||||
@@ -0,0 +1,44 @@
|
||||
import pytest
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py39
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008c_an_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == "plumbus"
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_fastapi_error(client: TestClient):
|
||||
with pytest.raises(FastAPIError) as exc_info:
|
||||
client.get("/items/portal-gun")
|
||||
assert "No response object was returned" in exc_info.value.args[0]
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_internal_server_error():
|
||||
from docs_src.dependencies.tutorial008c_an_py39 import app
|
||||
|
||||
client = TestClient(app, raise_server_exceptions=False)
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 500, response.text
|
||||
assert response.text == "Internal Server Error"
|
||||
41
tests/test_tutorial/test_dependencies/test_tutorial008d.py
Normal file
41
tests/test_tutorial/test_dependencies/test_tutorial008d.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008d import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
|
||||
|
||||
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == "plumbus"
|
||||
|
||||
|
||||
def test_internal_error(client: TestClient):
|
||||
from docs_src.dependencies.tutorial008d import InternalError
|
||||
|
||||
with pytest.raises(InternalError) as exc_info:
|
||||
client.get("/items/portal-gun")
|
||||
assert (
|
||||
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
|
||||
)
|
||||
|
||||
|
||||
def test_internal_server_error():
|
||||
from docs_src.dependencies.tutorial008d import app
|
||||
|
||||
client = TestClient(app, raise_server_exceptions=False)
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 500, response.text
|
||||
assert response.text == "Internal Server Error"
|
||||
@@ -0,0 +1,41 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008d_an import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
|
||||
|
||||
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == "plumbus"
|
||||
|
||||
|
||||
def test_internal_error(client: TestClient):
|
||||
from docs_src.dependencies.tutorial008d_an import InternalError
|
||||
|
||||
with pytest.raises(InternalError) as exc_info:
|
||||
client.get("/items/portal-gun")
|
||||
assert (
|
||||
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
|
||||
)
|
||||
|
||||
|
||||
def test_internal_server_error():
|
||||
from docs_src.dependencies.tutorial008d_an import app
|
||||
|
||||
client = TestClient(app, raise_server_exceptions=False)
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 500, response.text
|
||||
assert response.text == "Internal Server Error"
|
||||
@@ -0,0 +1,47 @@
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from ...utils import needs_py39
|
||||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
def get_client():
|
||||
from docs_src.dependencies.tutorial008d_an_py39 import app
|
||||
|
||||
client = TestClient(app)
|
||||
return client
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_get_no_item(client: TestClient):
|
||||
response = client.get("/items/foo")
|
||||
assert response.status_code == 404, response.text
|
||||
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_get(client: TestClient):
|
||||
response = client.get("/items/plumbus")
|
||||
assert response.status_code == 200, response.text
|
||||
assert response.json() == "plumbus"
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_internal_error(client: TestClient):
|
||||
from docs_src.dependencies.tutorial008d_an_py39 import InternalError
|
||||
|
||||
with pytest.raises(InternalError) as exc_info:
|
||||
client.get("/items/portal-gun")
|
||||
assert (
|
||||
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
|
||||
)
|
||||
|
||||
|
||||
@needs_py39
|
||||
def test_internal_server_error():
|
||||
from docs_src.dependencies.tutorial008d_an_py39 import app
|
||||
|
||||
client = TestClient(app, raise_server_exceptions=False)
|
||||
response = client.get("/items/portal-gun")
|
||||
assert response.status_code == 500, response.text
|
||||
assert response.text == "Internal Server Error"
|
||||
Reference in New Issue
Block a user