mirror of
https://github.com/fastapi/fastapi.git
synced 2025-12-28 16:49:26 -05:00
Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb95d1cb89 | ||
|
|
7c1aeb5db2 | ||
|
|
5e583199b3 | ||
|
|
c3e0625423 | ||
|
|
c46eba8004 | ||
|
|
5b1e6865c5 | ||
|
|
69cb005f61 | ||
|
|
0da980cb0b | ||
|
|
135dcba746 | ||
|
|
21145d8e9f | ||
|
|
07f8d31ec9 | ||
|
|
91d7fb6d25 | ||
|
|
b584faffee | ||
|
|
1334485435 | ||
|
|
843bc85155 | ||
|
|
1cd23a1dbc | ||
|
|
06bf7781df | ||
|
|
7e0cdf2510 | ||
|
|
84cd488df1 | ||
|
|
958425a899 | ||
|
|
7eeacc9958 | ||
|
|
3b9a2bcb1b | ||
|
|
f73be1d599 | ||
|
|
dd6cf5d710 | ||
|
|
aa6586d51a | ||
|
|
f43fc82267 | ||
|
|
0108b002f3 | ||
|
|
f226040d28 | ||
|
|
cbd53f3bc8 | ||
|
|
e628e1928e | ||
|
|
809b21c849 | ||
|
|
7dd944deda | ||
|
|
6f43539d87 | ||
|
|
d62b3ea69c | ||
|
|
d2c7ffb447 | ||
|
|
33e57e6f02 | ||
|
|
e986894344 | ||
|
|
43489beb98 | ||
|
|
5e5cabefe1 | ||
|
|
6c15776406 | ||
|
|
c2dc0252b0 | ||
|
|
04dbcf416c | ||
|
|
ed3e79be77 | ||
|
|
6efd537204 | ||
|
|
aa53a48fe3 | ||
|
|
7d8241acb9 | ||
|
|
60e1259ca4 | ||
|
|
cee422f073 | ||
|
|
9ddc71e317 | ||
|
|
d305a67a81 | ||
|
|
8f70f8c43b | ||
|
|
11a5993c8c | ||
|
|
9f7902925a | ||
|
|
a64b2fed91 | ||
|
|
933668b42e | ||
|
|
c5bbcb8c9c | ||
|
|
f27e818edb | ||
|
|
fe620a6c12 | ||
|
|
179c8a0763 | ||
|
|
4023510e4c | ||
|
|
d29709fee8 | ||
|
|
623ee4460b | ||
|
|
da9bd0ee4c | ||
|
|
5eab5dbed6 | ||
|
|
152171e455 | ||
|
|
271b4f3144 | ||
|
|
031000fc6e | ||
|
|
c471c93113 | ||
|
|
1021152f0a | ||
|
|
b4ad143e37 | ||
|
|
cb53749798 | ||
|
|
01b106c290 | ||
|
|
3256c3ff07 | ||
|
|
d6b4c6c65c | ||
|
|
0f4b6294bf | ||
|
|
0a3dc7d107 | ||
|
|
23ad827597 | ||
|
|
4fa251beb5 | ||
|
|
3af6766e26 | ||
|
|
ce9aba258e | ||
|
|
f9cbaa5f39 | ||
|
|
eecc7a8113 | ||
|
|
2090e9a3e2 | ||
|
|
5b63406aa5 | ||
|
|
ca10d3927b | ||
|
|
631601787b | ||
|
|
d129910323 | ||
|
|
e10bdb82cc | ||
|
|
7111d69f28 | ||
|
|
635d1a2d6d | ||
|
|
423cdd24cc | ||
|
|
7fbb7963d3 | ||
|
|
78ff6e3efd | ||
|
|
fe694766ae | ||
|
|
a1ea708044 | ||
|
|
897cde9fe2 | ||
|
|
ed628ddb92 | ||
|
|
4491ea6882 | ||
|
|
57d4d93841 | ||
|
|
136fe2b70f | ||
|
|
e9ffa20c8e | ||
|
|
d5498274f9 | ||
|
|
3c7685273f | ||
|
|
04016d3bf9 | ||
|
|
1780c21e7a | ||
|
|
040ad986d4 | ||
|
|
84d400b916 | ||
|
|
dd790c34ff | ||
|
|
fe0249a23e | ||
|
|
43e2223804 | ||
|
|
c55f90df32 | ||
|
|
f933fd6ff8 | ||
|
|
9090bf4084 | ||
|
|
d633953f13 | ||
|
|
a751032c09 | ||
|
|
505ae06c0b | ||
|
|
4de60e153a | ||
|
|
8b5843ebcd | ||
|
|
5826c4f31f | ||
|
|
91510db620 | ||
|
|
bcd5a424cd | ||
|
|
678bed2fc9 | ||
|
|
a4aa79e0b4 | ||
|
|
e7756ae7dc | ||
|
|
dc2fdd56af |
@@ -1,6 +1,8 @@
|
||||
FROM python:3.9
|
||||
FROM python:3.10
|
||||
|
||||
RUN pip install httpx "pydantic==1.5.1" pygithub
|
||||
COPY ./requirements.txt /app/requirements.txt
|
||||
|
||||
RUN pip install -r /app/requirements.txt
|
||||
|
||||
COPY ./app /app
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ from typing import Union
|
||||
import httpx
|
||||
from github import Github
|
||||
from github.PullRequest import PullRequest
|
||||
from pydantic import BaseModel, BaseSettings, SecretStr, ValidationError
|
||||
from pydantic import BaseModel, SecretStr, ValidationError
|
||||
from pydantic_settings import BaseSettings
|
||||
|
||||
github_api = "https://api.github.com"
|
||||
|
||||
|
||||
4
.github/actions/comment-docs-preview-in-pr/requirements.txt
vendored
Normal file
4
.github/actions/comment-docs-preview-in-pr/requirements.txt
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
PyGithub
|
||||
pydantic>=2.5.3,<3.0.0
|
||||
pydantic-settings>=2.1.0,<3.0.0
|
||||
httpx
|
||||
3
.github/workflows/label-approved.yml
vendored
3
.github/workflows/label-approved.yml
vendored
@@ -3,6 +3,7 @@ name: Label Approved
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 12 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
label-approved:
|
||||
@@ -13,6 +14,6 @@ jobs:
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: docker://tiangolo/label-approved:0.0.2
|
||||
- uses: docker://tiangolo/label-approved:0.0.4
|
||||
with:
|
||||
token: ${{ secrets.FASTAPI_LABEL_APPROVED }}
|
||||
|
||||
2
.github/workflows/latest-changes.yml
vendored
2
.github/workflows/latest-changes.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }}
|
||||
with:
|
||||
limit-access-to-actor: true
|
||||
- uses: docker://tiangolo/latest-changes:0.2.0
|
||||
- uses: docker://tiangolo/latest-changes:0.3.0
|
||||
# - uses: tiangolo/latest-changes@main
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
7
.github/workflows/test.yml
vendored
7
.github/workflows/test.yml
vendored
@@ -42,7 +42,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11"]
|
||||
python-version:
|
||||
- "3.12"
|
||||
- "3.11"
|
||||
- "3.10"
|
||||
- "3.9"
|
||||
- "3.8"
|
||||
pydantic-version: ["pydantic-v1", "pydantic-v2"]
|
||||
fail-fast: false
|
||||
steps:
|
||||
|
||||
464
docs/bn/docs/index.md
Normal file
464
docs/bn/docs/index.md
Normal file
@@ -0,0 +1,464 @@
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI উচ্চক্ষমতা সম্পন্ন, সহজে শেখার এবং দ্রুত কোড করে প্রোডাকশনের জন্য ফ্রামওয়ার্ক।</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**নির্দেশিকা নথি**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**সোর্স কোড**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI একটি আধুনিক, দ্রুত ( বেশি ক্ষমতা ) সম্পন্ন, Python 3.6+ দিয়ে API তৈরির জন্য স্ট্যান্ডার্ড পাইথন টাইপ ইঙ্গিত ভিত্তিক ওয়েব ফ্রেমওয়ার্ক।
|
||||
|
||||
এর মূল বৈশিষ্ট্য গুলো হলঃ
|
||||
|
||||
- **গতি**: এটি **NodeJS** এবং **Go** এর মত কার্যক্ষমতা সম্পন্ন (Starlette এবং Pydantic এর সাহায্যে)। [পাইথন এর দ্রুততম ফ্রেমওয়ার্ক গুলোর মধ্যে এটি একটি](#_11)।
|
||||
- **দ্রুত কোড করা**:বৈশিষ্ট্য তৈরির গতি ২০০% থেকে ৩০০% বৃদ্ধি করে৷ \*
|
||||
- **স্বল্প bugs**: মানুব (ডেভেলপার) সৃষ্ট ত্রুটির প্রায় ৪০% হ্রাস করে। \*
|
||||
- **স্বজ্ঞাত**: দুর্দান্ত এডিটর সাহায্য <abbr title="also known as auto-complete, autocompletion, IntelliSense">Completion</abbr> নামেও পরিচিত। দ্রুত ডিবাগ করা যায়।
|
||||
|
||||
- **সহজ**: এটি এমন ভাবে সজানো হয়েছে যেন নির্দেশিকা নথি পড়ে সহজে শেখা এবং ব্যবহার করা যায়।
|
||||
- **সংক্ষিপ্ত**: কোড পুনরাবৃত্তি কমানোর পাশাপাশি, bug কমায় এবং প্রতিটি প্যারামিটার ঘোষণা থেকে একাধিক ফিচার পাওয়া যায় ।
|
||||
- **জোরালো**: স্বয়ংক্রিয় ভাবে তৈরি ক্রিয়াশীল নির্দেশনা নথি (documentation) সহ উৎপাদন উপযোগি (Production-ready) কোড পাওয়া যায়।
|
||||
- **মান-ভিত্তিক**: এর ভিত্তি <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (যা পুর্বে Swagger নামে পরিচিত ছিল) এবং <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a> এর আদর্শের মানের ওপর
|
||||
|
||||
<small>\* উৎপাদনমুখি এপ্লিকেশন বানানোর এক দল ডেভেলপার এর মতামত ভিত্তিক ফলাফল।</small>
|
||||
|
||||
## স্পনসর গণ
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">অন্যান্য স্পনসর গণ</a>
|
||||
|
||||
## মতামত সমূহ
|
||||
|
||||
"_আমি আজকাল **FastAPI** ব্যবহার করছি। [...] আমরা ভাবছি মাইক্রোসফ্টে **ML সার্ভিস** এ সকল দলের জন্য এটি ব্যবহার করব। যার মধ্যে কিছু পণ্য **Windows** এ সংযোযন হয় এবং কিছু **Office** এর সাথে সংযোযন হচ্ছে।_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">কবির খান - <strong>মাইক্রোসফ্টে</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_আমরা **FastAPI** লাইব্রেরি গ্রহণ করেছি একটি **REST** সার্ভার তৈরি করতে, যা **ভবিষ্যদ্বাণী** পাওয়ার জন্য কুয়েরি করা যেতে পারে। [লুডউইগের জন্য]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">পিয়েরো মোলিনো, ইয়ারোস্লাভ দুদিন, এবং সাই সুমন্থ মিরিয়ালা - <strong>উবার</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** আমাদের **ক্রাইসিস ম্যানেজমেন্ট** অর্কেস্ট্রেশন ফ্রেমওয়ার্ক: **ডিসপ্যাচ** এর ওপেন সোর্স রিলিজ ঘোষণা করতে পেরে আনন্দিত! [যাকিনা **FastAPI** দিয়ে নির্মিত]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">কেভিন গ্লিসন, মার্ক ভিলানোভা, ফরেস্ট মনসেন - <strong>নেটফ্লিক্স</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_আমি **FastAPI** নিয়ে চাঁদের সমান উৎসাহিত। এটি খুবই মজার!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">ব্রায়ান ওকেন - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">পাইথন বাইটস</a> পডকাস্ট হোস্ট</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"\_সত্যিই, আপনি যা তৈরি করেছেন তা খুব মজবুত এবং পরিপূর্ন৷ অনেক উপায়ে, আমি যা **Hug** এ করতে চেয়েছিলাম - তা কাউকে তৈরি করতে দেখে আমি সত্যিই অনুপ্রানিত৷\_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">টিমোথি ক্রসলে - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> স্রষ্টা</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"আপনি যদি REST API তৈরির জন্য একটি **আধুনিক ফ্রেমওয়ার্ক** শিখতে চান, তাহলে **FastAPI** দেখুন [...] এটি দ্রুত, ব্যবহার করা সহজ এবং শিখতেও সহজ [...]\_"
|
||||
|
||||
"_আমরা আমাদের **APIs** [...] এর জন্য **FastAPI**- তে এসেছি [...] আমি মনে করি আপনিও এটি পছন্দ করবেন [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">ইনেস মন্টানি - ম্যাথিউ হোনিবাল - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> প্রতিষ্ঠাতা - <a href="https://spacy.io" target="_blank">spaCy</a> স্রষ্টা</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, CLI এর জন্য FastAPI
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
আপনি যদি <abbr title="Command Line Interface">CLI</abbr> অ্যাপ বানাতে চান, যা কিনা ওয়েব API এর পরিবর্তে টার্মিনালে ব্যবহার হবে, তাহলে দেখুন<a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**টাইপার** হল FastAPI এর ছোট ভাইয়ের মত। এবং এটির উদ্দেশ্য ছিল **CLIs এর FastAPI** হওয়া। ⌨️ 🚀
|
||||
|
||||
## প্রয়োজনীয়তা গুলো
|
||||
|
||||
Python 3.7+
|
||||
|
||||
FastAPI কিছু দানবেদের কাঁধে দাঁড়িয়ে আছে:
|
||||
|
||||
- <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> ওয়েব অংশের জন্য.
|
||||
- <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> ডেটা অংশগুলির জন্য.
|
||||
|
||||
## ইনস্টলেশন প্রক্রিয়া
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
আপনার একটি ASGI সার্ভারেরও প্রয়োজন হবে, প্রোডাকশনের জন্য <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> অথবা <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## উদাহরণ
|
||||
|
||||
### তৈরি
|
||||
|
||||
- `main.py` নামে একটি ফাইল তৈরি করুন:
|
||||
|
||||
```Python
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>অথবা ব্যবহার করুন <code>async def</code>...</summary>
|
||||
|
||||
যদি আপনার কোড `async` / `await`, ব্যবহার করে তাহলে `async def` ব্যবহার করুন:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**টীকা**:
|
||||
|
||||
আপনি যদি না জানেন, _"তাড়াহুড়ো?"_ বিভাগটি দেখুন <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` এবং `await` নথির মধ্যে দেখুন </a>.
|
||||
|
||||
</details>
|
||||
|
||||
### এটি চালান
|
||||
|
||||
সার্ভার চালু করুন:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>নির্দেশনা সম্পর্কে <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
`uvicorn main:app` নির্দেশনাটি দ্বারা বোঝায়:
|
||||
|
||||
- `main`: ফাইল `main.py` (পাইথন "মডিউল")।
|
||||
- `app`: `app = FastAPI()` লাইন দিয়ে `main.py` এর ভিতরে তৈরি করা অবজেক্ট।
|
||||
- `--reload`: কোড পরিবর্তনের পরে সার্ভার পুনরায় চালু করুন। এটি শুধুমাত্র ডেভেলপমেন্ট এর সময় ব্যবহার করুন।
|
||||
|
||||
</details>
|
||||
|
||||
### এটা চেক করুন
|
||||
|
||||
আপনার ব্রাউজার খুলুন <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a> এ।
|
||||
|
||||
আপনি JSON রেসপন্স দেখতে পাবেন:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
আপনি ইতিমধ্যে একটি API তৈরি করেছেন যা:
|
||||
|
||||
- `/` এবং `/items/{item_id}` _paths_ এ HTTP অনুরোধ গ্রহণ করে।
|
||||
- উভয় *path*ই `GET` <em>অপারেশন</em> নেয় ( যা HTTP _methods_ নামেও পরিচিত)।
|
||||
- _path_ `/items/{item_id}`-এ একটি _path প্যারামিটার_ `item_id` আছে যা কিনা `int` হতে হবে।
|
||||
- _path_ `/items/{item_id}`-এর একটি ঐচ্ছিক `str` _query প্যারামিটার_ `q` আছে।
|
||||
|
||||
### ক্রিয়াশীল API নির্দেশিকা নথি
|
||||
|
||||
এখন যান <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
আপনি স্বয়ংক্রিয় ভাবে প্রস্তুত ক্রিয়াশীল API নির্দেশিকা নথি দেখতে পাবেন (<a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a> প্রদত্ত):
|
||||
|
||||

|
||||
|
||||
### বিকল্প API নির্দেশিকা নথি
|
||||
|
||||
এবং এখন <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> এ যান.
|
||||
|
||||
আপনি স্বয়ংক্রিয় ভাবে প্রস্তুত বিকল্প নির্দেশিকা নথি দেখতে পাবেন (<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> প্রদত্ত):
|
||||
|
||||

|
||||
|
||||
## উদাহরণস্বরূপ আপগ্রেড
|
||||
|
||||
এখন `main.py` ফাইলটি পরিবর্তন করুন যেন এটি `PUT` রিকুয়েস্ট থেকে বডি পেতে পারে।
|
||||
|
||||
Python স্ট্যান্ডার্ড লাইব্রেরি, Pydantic এর সাহায্যে বডি ঘোষণা করুন।
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Union[bool, None] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
সার্ভারটি স্বয়ংক্রিয়ভাবে পুনরায় লোড হওয়া উচিত (কারণ আপনি উপরের `uvicorn` কমান্ডে `--reload` যোগ করেছেন)।
|
||||
|
||||
### ক্রিয়াশীল API নির্দেশিকা নথি উন্নীতকরণ
|
||||
|
||||
এখন <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> এডড্রেসে যান.
|
||||
|
||||
- ক্রিয়াশীল API নির্দেশিকা নথিটি স্বয়ংক্রিয়ভাবে উন্নীত হযে যাবে, নতুন বডি সহ:
|
||||
|
||||

|
||||
|
||||
- "Try it out" বাটনে চাপুন, এটি আপনাকে পেরামিটারগুলো পূরণ করতে এবং API এর সাথে সরাসরি ক্রিয়া-কলাপ করতে দিবে:
|
||||
|
||||

|
||||
|
||||
- তারপরে "Execute" বাটনে চাপুন, ব্যবহারকারীর ইন্টারফেস আপনার API এর সাথে যোগাযোগ করবে, পেরামিটার পাঠাবে, ফলাফলগুলি পাবে এবং সেগুলি পর্রদায় দেখাবে:
|
||||
|
||||

|
||||
|
||||
### বিকল্প API নির্দেশিকা নথি আপগ্রেড
|
||||
|
||||
এবং এখন <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> এ যান।
|
||||
|
||||
- বিকল্প নির্দেশিকা নথিতেও নতুন কুয়েরি প্যারামিটার এবং বডি প্রতিফলিত হবে:
|
||||
|
||||

|
||||
|
||||
### সংক্ষিপ্তকরণ
|
||||
|
||||
সংক্ষেপে, আপনি **শুধু একবার** প্যারামিটারের ধরন, বডি ইত্যাদি ফাংশন প্যারামিটার হিসেবে ঘোষণা করেন।
|
||||
|
||||
আপনি সেটি আধুনিক পাইথনের সাথে করেন।
|
||||
|
||||
আপনাকে নতুন করে নির্দিষ্ট কোন লাইব্রেরির বাক্য গঠন, ফাংশন বা ক্লাস কিছুই শিখতে হচ্ছে না।
|
||||
|
||||
শুধুই আধুনিক **Python 3.6+**
|
||||
|
||||
উদাহরণস্বরূপ, `int` এর জন্য:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
অথবা আরও জটিল `Item` মডেলের জন্য:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...এবং সেই একই ঘোষণার সাথে আপনি পাবেন:
|
||||
|
||||
- এডিটর সাহায্য, যেমন
|
||||
- সমাপ্তি।
|
||||
- ধরণ যাচাই
|
||||
- তথ্য যাচাইকরণ:
|
||||
- ডেটা অবৈধ হলে স্বয়ংক্রিয় এবং পরিষ্কার ত্রুটির নির্দেশনা।
|
||||
- এমনকি গভীরভাবে নেস্ট করা JSON অবজেক্টের জন্য বৈধতা।
|
||||
- প্রেরিত তথ্য <abbr title="যা পরিচিত: serialization, parsing, marshalling">রূপান্তর</abbr>: যা নেটওয়ার্ক থেকে পাইথনের তথ্য এবং ধরনে আসে, এবং সেখান থেকে পড়া:
|
||||
|
||||
- JSON।
|
||||
- পাথ প্যারামিটার।
|
||||
- কুয়েরি প্যারামিটার।
|
||||
- কুকিজ
|
||||
- হেডার
|
||||
- ফর্ম
|
||||
- ফাইল
|
||||
|
||||
- আউটপুট ডেটার <abbr title="যা পরিচিত: serialization, parsing, marshalling">রূপান্তর</abbr>: পাইথন ডেটা এবং টাইপ থেকে নেটওয়ার্ক ডেটাতে রূপান্তর করা (JSON হিসাবে):
|
||||
-পাইথন টাইপে রূপান্তর করুন (`str`, `int`, `float`, `bool`, `list`, ইত্যাদি)।
|
||||
- `datetime` অবজেক্ট।
|
||||
- `UUID` objeঅবজেক্টcts।
|
||||
- ডাটাবেস মডেল।
|
||||
- ...এবং আরো অনেক।
|
||||
- স্বয়ংক্রিয় ক্রিয়াশীল API নির্দেশিকা নথি, 2টি বিকল্প ব্যবহারকারীর ইন্টারফেস সহ:
|
||||
- সোয়াগার ইউ আই (Swagger UI)।
|
||||
- রিডক (ReDoc)।
|
||||
|
||||
---
|
||||
|
||||
পূর্ববর্তী কোড উদাহরণে ফিরে আসা যাক, **FastAPI** যা করবে:
|
||||
|
||||
- `GET` এবং `PUT` অনুরোধের জন্য পথে `item_id` আছে কিনা তা যাচাই করবে।
|
||||
- `GET` এবং `PUT` অনুরোধের জন্য `item_id` টাইপ `int` এর হতে হবে তা যাচাই করবে।
|
||||
- যদি না হয় তবে ক্লায়েন্ট একটি উপযুক্ত, পরিষ্কার ত্রুটি দেখতে পাবেন।
|
||||
- `GET` অনুরোধের জন্য একটি ঐচ্ছিক ক্যুয়েরি প্যারামিটার নামক `q` (যেমন `http://127.0.0.1:8000/items/foo?q=somequery`) আছে কি তা চেক করবে।
|
||||
- যেহেতু `q` প্যারামিটারটি `= None` দিয়ে ঘোষণা করা হয়েছে, তাই এটি ঐচ্ছিক।
|
||||
- `None` ছাড়া এটি প্রয়োজনীয় হতো (যেমন `PUT` এর ক্ষেত্রে হয়েছে)।
|
||||
- `/items/{item_id}` এর জন্য `PUT` অনুরোধের বডি JSON হিসাবে পড়ুন:
|
||||
- লক্ষ করুন, `name` একটি প্রয়োজনীয় অ্যাট্রিবিউট হিসাবে বিবেচনা করেছে এবং এটি `str` হতে হবে।
|
||||
- লক্ষ করুন এখানে, `price` অ্যাট্রিবিউটটি আবশ্যক এবং এটি `float` হতে হবে।
|
||||
- লক্ষ করুন `is_offer` একটি ঐচ্ছিক অ্যাট্রিবিউট এবং এটি `bool` হতে হবে যদি উপস্থিত থাকে।
|
||||
- এই সবটি গভীরভাবে অবস্থানরত JSON অবজেক্টগুলিতেও কাজ করবে।
|
||||
- স্বয়ংক্রিয়ভাবে JSON হতে এবং JSON থেকে কনভার্ট করুন।
|
||||
- OpenAPI দিয়ে সবকিছু ডকুমেন্ট করুন, যা ব্যবহার করা যেতে পারে:
|
||||
- ক্রিয়াশীল নির্দেশিকা নথি।
|
||||
- অনেক ভাষার জন্য স্বয়ংক্রিয় ক্লায়েন্ট কোড তৈরির ব্যবস্থা।
|
||||
- সরাসরি 2টি ক্রিয়াশীল নির্দেশিকা নথি ওয়েব পৃষ্ঠ প্রদান করা হয়েছে।
|
||||
|
||||
---
|
||||
|
||||
আমরা এতক্ষন শুধু এর পৃষ্ঠ তৈরি করেছি, কিন্তু আপনি ইতমধ্যেই এটি কিভাবে কাজ করে তার ধারণাও পেয়ে গিয়েছেন।
|
||||
|
||||
নিম্নোক্ত লাইন গুলো পরিবর্তন করার চেষ্টা করুন:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...পুর্বে:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...পরবর্তীতে:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...এবং দেখুন কিভাবে আপনার এডিটর উপাদানগুলোকে সয়ংক্রিয়ভাবে-সম্পন্ন করবে এবং তাদের ধরন জানতে পারবে:
|
||||
|
||||

|
||||
|
||||
আরও বৈশিষ্ট্য সম্পন্ন উদাহরণের জন্য, দেখুন <a href="https://fastapi.tiangolo.com/tutorial/">টিউটোরিয়াল - ব্যবহারকারীর গাইড</a>.
|
||||
|
||||
**স্পয়লার সতর্কতা**: টিউটোরিয়াল - ব্যবহারকারীর গাইড নিম্নোক্ত বিষয়গুলি অন্তর্ভুক্ত করে:
|
||||
|
||||
- **হেডার**, **কুকিজ**, **ফর্ম ফিল্ড** এবং **ফাইলগুলি** এমন অন্যান্য জায়গা থেকে প্যারামিটার ঘোষণা করা।
|
||||
- `maximum_length` বা `regex` এর মতো **যাচাইকরণ বাধামুক্তি** সেট করা হয় কিভাবে, তা নিয়ে আলোচনা করা হবে।
|
||||
- একটি খুব শক্তিশালী এবং ব্যবহার করা সহজ <abbr title="also known as components, resources, providers, services, injectables">ডিপেন্ডেন্সি ইনজেকশন</abbr> পদ্ধতি
|
||||
- **OAuth2** এবং **JWT টোকেন** এবং **HTTP Basic** auth সহ নিরাপত্তা এবং অনুমোদনপ্রাপ্তি সম্পর্কিত বিষয়সমূহের উপর।
|
||||
- **গভীরভাবে অবস্থানরত JSON মডেল** ঘোষণা করার জন্য আরও উন্নত (কিন্তু সমান সহজ) কৌশল (Pydantic কে ধন্যবাদ)।
|
||||
- আরো অতিরিক্ত বৈশিষ্ট্য (স্টারলেটকে ধন্যবাদ) হিসাবে:
|
||||
- **WebSockets**
|
||||
- **GraphQL**
|
||||
- HTTPX এবং `pytest` ভিত্তিক অত্যন্ত সহজ পরীক্ষা
|
||||
- **CORS**
|
||||
- **Cookie Sessions**
|
||||
- ...এবং আরো।
|
||||
|
||||
## কর্মক্ষমতা
|
||||
|
||||
স্বাধীন TechEmpower Benchmarks দেখায় যে **FastAPI** অ্যাপ্লিকেশনগুলি Uvicorn-এর অধীনে চলমান দ্রুততম<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">পাইথন ফ্রেমওয়ার্কগুলির মধ্যে একটি,</a> শুধুমাত্র Starlette এবং Uvicorn-এর পর (FastAPI দ্বারা অভ্যন্তরীণভাবে ব্যবহৃত)। (\*)
|
||||
|
||||
এটি সম্পর্কে আরও বুঝতে, দেখুন <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## ঐচ্ছিক নির্ভরশীলতা
|
||||
|
||||
Pydantic দ্বারা ব্যবহৃত:
|
||||
|
||||
- <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - দ্রুত JSON এর জন্য <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>.
|
||||
- <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - ইমেল যাচাইকরণের জন্য।
|
||||
|
||||
স্টারলেট দ্বারা ব্যবহৃত:
|
||||
|
||||
- <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - আপনি যদি `TestClient` ব্যবহার করতে চান তাহলে আবশ্যক।
|
||||
- <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - আপনি যদি প্রদত্ত টেমপ্লেট রূপরেখা ব্যবহার করতে চান তাহলে প্রয়োজন।
|
||||
- <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - আপনি যদি ফর্ম সহায়তা করতে চান তাহলে প্রয়োজন <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, `request.form()` সহ।
|
||||
- <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - `SessionMiddleware` সহায়তার জন্য প্রয়োজন।
|
||||
- <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - স্টারলেটের SchemaGenerator সাপোর্ট এর জন্য প্রয়োজন (আপনার সম্ভাবত FastAPI প্রয়োজন নেই)।
|
||||
- <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - `GraphQLApp` সহায়তার জন্য প্রয়োজন।
|
||||
- <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - আপনি `UJSONResponse` ব্যবহার করতে চাইলে প্রয়োজন।
|
||||
|
||||
FastAPI / Starlette দ্বারা ব্যবহৃত:
|
||||
|
||||
- <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - সার্ভারের জন্য যা আপনার অ্যাপ্লিকেশন লোড করে এবং পরিবেশন করে।
|
||||
- <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - আপনি `ORJSONResponse` ব্যবহার করতে চাইলে প্রয়োজন।
|
||||
|
||||
আপনি এই সব ইনস্টল করতে পারেন `pip install fastapi[all]` দিয়ে.
|
||||
|
||||
## লাইসেন্স
|
||||
|
||||
এই প্রজেক্ট MIT লাইসেন্স নীতিমালার অধীনে শর্তায়িত।
|
||||
1
docs/bn/mkdocs.yml
Normal file
1
docs/bn/mkdocs.yml
Normal file
@@ -0,0 +1 @@
|
||||
INHERIT: ../en/mkdocs.yml
|
||||
333
docs/de/docs/tutorial/first-steps.md
Normal file
333
docs/de/docs/tutorial/first-steps.md
Normal file
@@ -0,0 +1,333 @@
|
||||
# Erste Schritte
|
||||
|
||||
Die einfachste FastAPI-Datei könnte wie folgt aussehen:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Kopieren Sie dies in eine Datei `main.py`.
|
||||
|
||||
Starten Sie den Live-Server:
|
||||
|
||||
<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 "Hinweis"
|
||||
Der Befehl `uvicorn main:app` bezieht sich auf:
|
||||
|
||||
* `main`: die Datei `main.py` (das sogenannte Python-„Modul“).
|
||||
* `app`: das Objekt, welches in der Datei `main.py` mit der Zeile `app = FastAPI()` erzeugt wurde.
|
||||
* `--reload`: lässt den Server nach Codeänderungen neu starten. Verwenden Sie das nur während der Entwicklung.
|
||||
|
||||
In der Konsolenausgabe sollte es eine Zeile geben, die ungefähr so aussieht:
|
||||
|
||||
```hl_lines="4"
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
Diese Zeile zeigt die URL, unter der Ihre Anwendung auf Ihrem lokalen Computer bereitgestellt wird.
|
||||
|
||||
### Testen Sie es
|
||||
|
||||
Öffnen Sie Ihren Browser unter <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000.</a>
|
||||
|
||||
Sie werden folgende JSON-Antwort sehen:
|
||||
|
||||
```JSON
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
### Interaktive API-Dokumentation
|
||||
|
||||
Gehen Sie als Nächstes auf <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs </a>.
|
||||
|
||||
Sie werden die automatisch erzeugte, interaktive API-Dokumentation sehen (bereitgestellt durch <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Alternative API-Dokumentation
|
||||
|
||||
Gehen Sie nun auf <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
Dort sehen Sie die alternative, automatische Dokumentation (bereitgestellt durch <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
### OpenAPI
|
||||
|
||||
**FastAPI** generiert ein „Schema“ mit all Ihren APIs unter Verwendung des **OpenAPI**-Standards zur Definition von APIs.
|
||||
|
||||
#### „Schema“
|
||||
|
||||
Ein „Schema“ ist eine Definition oder Beschreibung von etwas. Nicht der eigentliche Code, der es implementiert, sondern lediglich eine abstrakte Beschreibung.
|
||||
|
||||
#### API-„Schema“
|
||||
|
||||
In diesem Fall ist <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> eine Spezifikation, die vorschreibt, wie ein Schema für Ihre API zu definieren ist.
|
||||
|
||||
Diese Schemadefinition enthält Ihre API-Pfade, die möglichen Parameter, welche diese entgegennehmen, usw.
|
||||
|
||||
#### Daten-„Schema“
|
||||
|
||||
Der Begriff „Schema“ kann sich auch auf die Form von Daten beziehen, wie z.B. einen JSON-Inhalt.
|
||||
|
||||
In diesem Fall sind die JSON-Attribute und deren Datentypen, usw. gemeint.
|
||||
|
||||
#### OpenAPI und JSON Schema
|
||||
|
||||
OpenAPI definiert ein API-Schema für Ihre API. Dieses Schema enthält Definitionen (oder „Schemas“) der Daten, die von Ihrer API unter Verwendung von **JSON Schema**, dem Standard für JSON-Datenschemata, gesendet und empfangen werden.
|
||||
|
||||
#### Überprüfen Sie die `openapi.json`
|
||||
|
||||
Falls Sie wissen möchten, wie das rohe OpenAPI-Schema aussieht: FastAPI generiert automatisch ein JSON (Schema) mit den Beschreibungen Ihrer gesamten API.
|
||||
|
||||
Sie können es direkt einsehen unter: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
|
||||
|
||||
Es wird ein JSON angezeigt, welches ungefähr so aussieht:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"paths": {
|
||||
"/items/": {
|
||||
"get": {
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
|
||||
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
#### Wofür OpenAPI gedacht ist
|
||||
|
||||
Das OpenAPI-Schema ist die Grundlage für die beiden enthaltenen interaktiven Dokumentationssysteme.
|
||||
|
||||
Es gibt dutzende Alternativen, die alle auf OpenAPI basieren. Sie können jede dieser Alternativen problemlos zu Ihrer mit **FastAPI** erstellten Anwendung hinzufügen.
|
||||
|
||||
Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generieren, die mit Ihrer API kommunizieren. Zum Beispiel für Frontend-, Mobile- oder IoT-Anwendungen.
|
||||
|
||||
## Rückblick, Schritt für Schritt
|
||||
|
||||
### Schritt 1: Importieren von `FastAPI`
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
`FastAPI` ist eine Python-Klasse, die die gesamte Funktionalität für Ihre API bereitstellt.
|
||||
|
||||
!!! note "Technische Details"
|
||||
`FastAPI` ist eine Klasse, die direkt von `Starlette` erbt.
|
||||
|
||||
Sie können alle <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>-Funktionalitäten auch mit `FastAPI` nutzen.
|
||||
|
||||
### Schritt 2: Erzeugen einer `FastAPI`-„Instanz“
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
In diesem Beispiel ist die Variable `app` eine „Instanz“ der Klasse `FastAPI`.
|
||||
|
||||
Dies wird der Hauptinteraktionspunkt für die Erstellung all Ihrer APIs sein.
|
||||
|
||||
Die Variable `app` ist dieselbe, auf die sich der Befehl `uvicorn` bezieht:
|
||||
|
||||
<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>
|
||||
|
||||
Wenn Sie Ihre Anwendung wie folgt erstellen:
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!../../../docs_src/first_steps/tutorial002.py!}
|
||||
```
|
||||
|
||||
Und in eine Datei `main.py` einfügen, dann würden Sie `uvicorn` wie folgt aufrufen:
|
||||
|
||||
<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>
|
||||
|
||||
### Schritt 3: Erstellen einer *Pfadoperation*
|
||||
|
||||
#### Pfad
|
||||
|
||||
„Pfad“ bezieht sich hier auf den letzten Teil der URL, beginnend mit dem ersten `/`.
|
||||
|
||||
In einer URL wie:
|
||||
|
||||
```
|
||||
https://example.com/items/foo
|
||||
```
|
||||
|
||||
... wäre der Pfad folglich:
|
||||
|
||||
```
|
||||
/items/foo
|
||||
```
|
||||
|
||||
!!! info
|
||||
Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet.
|
||||
|
||||
Bei der Erstellung einer API ist der „Pfad“ die wichtigste Möglichkeit zur Trennung von „Anliegen“ und „Ressourcen“.
|
||||
|
||||
#### Operation
|
||||
|
||||
„Operation“ bezieht sich hier auf eine der HTTP-„Methoden“.
|
||||
|
||||
Eine von diesen:
|
||||
|
||||
* `POST`
|
||||
* `GET`
|
||||
* `PUT`
|
||||
* `DELETE`
|
||||
|
||||
... und die etwas Exotischeren:
|
||||
|
||||
* `OPTIONS`
|
||||
* `HEAD`
|
||||
* `PATCH`
|
||||
* `TRACE`
|
||||
|
||||
Im HTTP-Protokoll können Sie mit jedem Pfad über eine (oder mehrere) dieser „Methoden“ kommunizieren.
|
||||
|
||||
---
|
||||
|
||||
Bei der Erstellung von APIs verwenden Sie normalerweise diese spezifischen HTTP-Methoden, um eine bestimmte Aktion durchzuführen.
|
||||
|
||||
Normalerweise verwenden Sie:
|
||||
|
||||
* `POST`: um Daten zu erzeugen (create).
|
||||
* `GET`: um Daten zu lesen (read).
|
||||
* `PUT`: um Daten zu aktualisieren (update).
|
||||
* `DELETE`: um Daten zu löschen (delete).
|
||||
|
||||
In OpenAPI wird folglich jede dieser HTTP-Methoden als „Operation“ bezeichnet.
|
||||
|
||||
Wir werden sie auch „**Operationen**“ nennen.
|
||||
|
||||
#### Definieren eines *Pfadoperation-Dekorators*
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die Bearbeitung von Anfragen zuständig ist, die an:
|
||||
|
||||
* den Pfad `/`
|
||||
* unter der Verwendung der <abbr title="eine HTTP GET Methode"><code>get</code>-Operation</abbr> gehen
|
||||
|
||||
!!! info "`@decorator` Information"
|
||||
Diese `@something`-Syntax wird in Python „Dekorator“ genannt.
|
||||
|
||||
Sie platzieren ihn über einer Funktion. Wie ein hübscher, dekorativer Hut (daher kommt wohl der Begriff).
|
||||
|
||||
Ein „Dekorator“ nimmt die darunter stehende Funktion und macht etwas damit.
|
||||
|
||||
In unserem Fall teilt dieser Dekorator **FastAPI** mit, dass die folgende Funktion mit dem **Pfad** `/` und der **Operation** `get` zusammenhängt.
|
||||
|
||||
Dies ist der „**Pfadoperation-Dekorator**“.
|
||||
|
||||
Sie können auch die anderen Operationen verwenden:
|
||||
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
|
||||
Oder die exotischeren:
|
||||
|
||||
* `@app.options()`
|
||||
* `@app.head()`
|
||||
* `@app.patch()`
|
||||
* `@app.trace()`
|
||||
|
||||
!!! tip "Tipp"
|
||||
Es steht Ihnen frei, jede Operation (HTTP-Methode) so zu verwenden, wie Sie es möchten.
|
||||
|
||||
**FastAPI** erzwingt keine bestimmte Bedeutung.
|
||||
|
||||
Die hier aufgeführten Informationen dienen als Leitfaden und sind nicht verbindlich.
|
||||
|
||||
Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktionen nur mit „POST“-Operationen durch.
|
||||
|
||||
### Schritt 4: Definieren der **Pfadoperation-Funktion**
|
||||
|
||||
Das ist unsere „**Pfadoperation-Funktion**“:
|
||||
|
||||
* **Pfad**: ist `/`.
|
||||
* **Operation**: ist `get`.
|
||||
* **Funktion**: ist die Funktion direkt unter dem „Dekorator“ (unter `@app.get("/")`).
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Dies ist eine Python-Funktion.
|
||||
|
||||
Sie wird von **FastAPI** immer dann aufgerufen, wenn sie eine Anfrage an die URL "`/`" mittels einer `GET`-Operation erhält.
|
||||
|
||||
In diesem Fall handelt es sich um eine `async`-Funktion.
|
||||
|
||||
---
|
||||
|
||||
Sie könnten sie auch als normale Funktion anstelle von `async def` definieren:
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!../../../docs_src/first_steps/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Wenn Sie den Unterschied nicht kennen, lesen Sie [Async: *„In Eile?“*](../async.md#in-eile){.internal-link target=_blank}.
|
||||
|
||||
### Schritt 5: den Inhalt zurückgeben
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!../../../docs_src/first_steps/tutorial001.py!}
|
||||
```
|
||||
|
||||
Sie können ein `dict`, eine `list`, einzelne Werte wie `str`, `int`, usw. zurückgeben.
|
||||
|
||||
Sie können auch Pydantic-Modelle zurückgeben (dazu später mehr).
|
||||
|
||||
Es gibt viele andere Objekte und Modelle, die automatisch zu JSON konvertiert werden (einschließlich ORMs usw.). Versuchen Sie, Ihre Lieblingsobjekte zu verwenden. Es ist sehr wahrscheinlich, dass sie bereits unterstützt werden.
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
* Importieren Sie `FastAPI`.
|
||||
* Erstellen Sie eine `app` Instanz.
|
||||
* Schreiben Sie einen **Pfadoperation-Dekorator** (wie z.B. `@app.get("/")`).
|
||||
* Schreiben Sie eine **Pfadoperation-Funktion** (wie z.B. oben `def root(): ...`).
|
||||
* Starten Sie den Entwicklungsserver (z.B. `uvicorn main:app --reload`).
|
||||
@@ -27,7 +27,7 @@ $ pip install jinja2
|
||||
* 📣 `Request` 🔢 *➡ 🛠️* 👈 🔜 📨 📄.
|
||||
* ⚙️ `templates` 👆 ✍ ✍ & 📨 `TemplateResponse`, 🚶♀️ `request` 1️⃣ 🔑-💲 👫 Jinja2️⃣ "🔑".
|
||||
|
||||
```Python hl_lines="4 11 15-16"
|
||||
```Python hl_lines="4 11 15-18"
|
||||
{!../../../docs_src/templates/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
Articles:
|
||||
English:
|
||||
- author: Visual Studio Code Team
|
||||
author_link: https://code.visualstudio.com/
|
||||
link: https://code.visualstudio.com/docs/python/tutorial-fastapi
|
||||
title: FastAPI Tutorial in Visual Studio Code
|
||||
- author: Apitally
|
||||
author_link: https://apitally.io
|
||||
link: https://blog.apitally.io/fastapi-application-monitoring-made-easy
|
||||
title: FastAPI application monitoring made easy
|
||||
- author: John Philip
|
||||
author_link: https://medium.com/@amjohnphilip
|
||||
link: https://python.plainenglish.io/building-a-restful-api-with-fastapi-secure-signup-and-login-functionality-included-45cdbcb36106
|
||||
title: "Building a RESTful API with FastAPI: Secure Signup and Login Functionality Included"
|
||||
- author: Keshav Malik
|
||||
author_link: https://theinfosecguy.xyz/
|
||||
link: https://blog.theinfosecguy.xyz/building-a-crud-api-with-fastapi-and-supabase-a-step-by-step-guide
|
||||
title: Building a CRUD API with FastAPI and Supabase
|
||||
- author: Adejumo Ridwan Suleiman
|
||||
author_link: https://www.linkedin.com/in/adejumoridwan/
|
||||
link: https://medium.com/python-in-plain-english/build-an-sms-spam-classifier-serverless-database-with-faunadb-and-fastapi-23dbb275bc5b
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
sponsors:
|
||||
- - login: bump-sh
|
||||
- - login: scalar
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4
|
||||
url: https://github.com/scalar
|
||||
- login: codacy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1834093?v=4
|
||||
url: https://github.com/codacy
|
||||
- login: bump-sh
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33217836?v=4
|
||||
url: https://github.com/bump-sh
|
||||
- login: Alek99
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38776361?u=bd6c163fe787c2de1a26c881598e54b67e2482dd&v=4
|
||||
url: https://github.com/Alek99
|
||||
- login: cryptapi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44925437?u=61369138589bc7fee6c417f3fbd50fbd38286cc4&v=4
|
||||
url: https://github.com/cryptapi
|
||||
- login: porter-dev
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4
|
||||
url: https://github.com/porter-dev
|
||||
- login: fern-api
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/102944815?v=4
|
||||
url: https://github.com/fern-api
|
||||
- login: nanram22
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/116367316?v=4
|
||||
url: https://github.com/nanram22
|
||||
- login: andrew-propelauth
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=1188c27cb744bbec36447a2cfd4453126b2ddb5c&v=4
|
||||
url: https://github.com/andrew-propelauth
|
||||
- - login: nihpo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1841030?u=0264956d7580f7e46687a762a7baa629f84cf97c&v=4
|
||||
url: https://github.com/nihpo
|
||||
@@ -21,7 +27,7 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4
|
||||
url: https://github.com/ObliviousAI
|
||||
- - login: mikeckennedy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=1bb18268bcd4d9249e1f783a063c27df9a84c05b&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2035561?u=ce6165b799ea3164cb6f5ff54ea08042057442af&v=4
|
||||
url: https://github.com/mikeckennedy
|
||||
- login: ndimares
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6267663?u=cfb27efde7a7212be8142abb6c058a1aeadb41b1&v=4
|
||||
@@ -32,12 +38,12 @@ sponsors:
|
||||
- login: deepset-ai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51827949?v=4
|
||||
url: https://github.com/deepset-ai
|
||||
- login: databento
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4
|
||||
url: https://github.com/databento
|
||||
- login: svix
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4
|
||||
url: https://github.com/svix
|
||||
- login: databento-bot
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/98378480?u=494f679996e39427f7ddb1a7de8441b7c96fb670&v=4
|
||||
url: https://github.com/databento-bot
|
||||
- login: VincentParedes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/103889729?v=4
|
||||
url: https://github.com/VincentParedes
|
||||
@@ -59,16 +65,10 @@ sponsors:
|
||||
- login: jina-ai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60539444?v=4
|
||||
url: https://github.com/jina-ai
|
||||
- - login: HiredScore
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3908850?v=4
|
||||
url: https://github.com/HiredScore
|
||||
- login: Trivie
|
||||
- - login: Trivie
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8161763?v=4
|
||||
url: https://github.com/Trivie
|
||||
- - login: moellenbeck
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/169372?v=4
|
||||
url: https://github.com/moellenbeck
|
||||
- login: birkjernstrom
|
||||
- - login: birkjernstrom
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/281715?u=4be14b43f76b4bd497b1941309bb390250b405e6&v=4
|
||||
url: https://github.com/birkjernstrom
|
||||
- login: yasyf
|
||||
@@ -83,27 +83,39 @@ sponsors:
|
||||
- login: mainframeindustries
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4
|
||||
url: https://github.com/mainframeindustries
|
||||
- login: doseiai
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/57115726?v=4
|
||||
url: https://github.com/doseiai
|
||||
- login: CanoaPBC
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/64223768?v=4
|
||||
url: https://github.com/CanoaPBC
|
||||
- - login: povilasb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1213442?u=b11f58ed6ceea6e8297c9b310030478ebdac894d&v=4
|
||||
url: https://github.com/povilasb
|
||||
- login: primer-io
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62146168?v=4
|
||||
url: https://github.com/primer-io
|
||||
- - login: NateXVI
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/48195620?u=4bc8751ae50cb087c40c1fe811764aa070b9eea6&v=4
|
||||
url: https://github.com/NateXVI
|
||||
- - login: upciti
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4
|
||||
url: https://github.com/upciti
|
||||
- - login: Kludex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: samuelcolvin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4
|
||||
url: https://github.com/samuelcolvin
|
||||
- login: koconder
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25068?u=582657b23622aaa3dfe68bd028a780f272f456fa&v=4
|
||||
url: https://github.com/koconder
|
||||
- login: jefftriplett
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50527?u=af1ddfd50f6afd6d99f333ba2ac8d0a5b245ea74&v=4
|
||||
url: https://github.com/jefftriplett
|
||||
- login: jstanden
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4
|
||||
url: https://github.com/jstanden
|
||||
- login: andreaso
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/285964?u=837265cc7562c0685f25b2d81cd9de0434fe107c&v=4
|
||||
url: https://github.com/andreaso
|
||||
- login: pamelafox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/297042?v=4
|
||||
url: https://github.com/pamelafox
|
||||
@@ -119,18 +131,21 @@ sponsors:
|
||||
- login: falkben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/653031?u=ad9838e089058c9e5a0bab94c0eec7cc181e0cd0&v=4
|
||||
url: https://github.com/falkben
|
||||
- login: jqueguiner
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/690878?u=bd65cc1f228ce6455e56dfaca3ef47c33bc7c3b0&v=4
|
||||
url: https://github.com/jqueguiner
|
||||
- login: mintuhouse
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4
|
||||
url: https://github.com/mintuhouse
|
||||
- login: tcsmith
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/989034?u=7d8d741552b3279e8f4d3878679823a705a46f8f&v=4
|
||||
url: https://github.com/tcsmith
|
||||
- login: mrkmcknz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1089376?u=2b9b8a8c25c33a4f6c220095638bd821cdfd13a3&v=4
|
||||
url: https://github.com/mrkmcknz
|
||||
- login: mickaelandrieu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1247388?u=599f6e73e452a9453f2bd91e5c3100750e731ad4&v=4
|
||||
url: https://github.com/mickaelandrieu
|
||||
- login: knallgelb
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2358812?u=c48cb6362b309d74cbf144bd6ad3aed3eb443e82&v=4
|
||||
url: https://github.com/knallgelb
|
||||
- login: johannquerne
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2736484?u=9b3381546a25679913a2b08110e4373c98840821&v=4
|
||||
url: https://github.com/johannquerne
|
||||
- login: Shark009
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3163309?u=0c6f4091b0eda05c44c390466199826e6dc6e431&v=4
|
||||
url: https://github.com/Shark009
|
||||
@@ -150,7 +165,7 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4
|
||||
url: https://github.com/anomaly
|
||||
- login: jgreys
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=c66ae617d614f6c886f1f1c1799d22100b3c848d&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4136890?u=096820d1ef89877d57d0f68e669ead8b0fde84df&v=4
|
||||
url: https://github.com/jgreys
|
||||
- login: jaredtrog
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4
|
||||
@@ -174,7 +189,7 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6152183?u=c485eefca5c6329600cae63dd35e4f5682ce6924&v=4
|
||||
url: https://github.com/iwpnd
|
||||
- login: FernandoCelmer
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=ab6108a843a2fb9df0934f482375d2907609f3ff&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=d29fff3fd862fda4ca752079f13f32e84c762ea4&v=4
|
||||
url: https://github.com/FernandoCelmer
|
||||
- login: simw
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4
|
||||
@@ -188,6 +203,9 @@ sponsors:
|
||||
- login: wdwinslow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11562137?u=dc01daafb354135603a263729e3d26d939c0c452&v=4
|
||||
url: https://github.com/wdwinslow
|
||||
- login: drcat101
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11951946?u=e714b957185b8cf3d301cced7fc3ad2842122c6a&v=4
|
||||
url: https://github.com/drcat101
|
||||
- login: jsoques
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12414216?u=620921d94196546cc8b9eae2cc4cbc3f95bab42f&v=4
|
||||
url: https://github.com/jsoques
|
||||
@@ -212,45 +230,48 @@ sponsors:
|
||||
- login: Filimoa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21352040?u=0be845711495bbd7b756e13fcaeb8efc1ebd78ba&v=4
|
||||
url: https://github.com/Filimoa
|
||||
- login: rahulsalgare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21974430?u=ade6f182b94554ab8491d7421de5e78f711dcaf8&v=4
|
||||
url: https://github.com/rahulsalgare
|
||||
- login: ehaca
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25950317?u=cec1a3e0643b785288ae8260cc295a85ab344995&v=4
|
||||
url: https://github.com/ehaca
|
||||
- login: timlrx
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28362229?u=9a745ca31372ee324af682715ae88ce8522f9094&v=4
|
||||
url: https://github.com/timlrx
|
||||
- login: BrettskiPy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/30988215?u=d8a94a67e140d5ee5427724b292cc52d8827087a&v=4
|
||||
url: https://github.com/BrettskiPy
|
||||
- login: mauroalejandrojm
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31569442?u=cdada990a1527926a36e95f62c30a8b48bbc49a1&v=4
|
||||
url: https://github.com/mauroalejandrojm
|
||||
- login: Leay15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32212558?u=c4aa9c1737e515959382a5515381757b1fd86c53&v=4
|
||||
url: https://github.com/Leay15
|
||||
- login: dvlpjrs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32254642?u=fbd6ad0324d4f1eb6231cf775be1c7bd4404e961&v=4
|
||||
url: https://github.com/dvlpjrs
|
||||
- login: ygorpontelo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32963605?u=35f7103f9c4c4c2589ae5737ee882e9375ef072e&v=4
|
||||
url: https://github.com/ygorpontelo
|
||||
- login: ProteinQure
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4
|
||||
url: https://github.com/ProteinQure
|
||||
- login: RafaelWO
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38643099?u=56c676f024667ee416dc8b1cdf0c2611b9dc994f&v=4
|
||||
url: https://github.com/RafaelWO
|
||||
- login: arleybri18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39681546?u=5c028f81324b0e8c73b3c15bc4e7b0218d2ba0c3&v=4
|
||||
url: https://github.com/arleybri18
|
||||
- login: thenickben
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40610922?u=1e907d904041b7c91213951a3cb344cd37c14aaf&v=4
|
||||
url: https://github.com/thenickben
|
||||
- login: adtalos
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40748353?v=4
|
||||
url: https://github.com/adtalos
|
||||
- login: ybressler
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40807730?u=41e2c00f1eebe3c402635f0325e41b4e6511462c&v=4
|
||||
url: https://github.com/ybressler
|
||||
- login: ddilidili
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/42176885?u=c0a849dde06987434653197b5f638d3deb55fc6c&v=4
|
||||
url: https://github.com/ddilidili
|
||||
- login: ramonalmeidam
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/45269580?u=3358750b3a5854d7c3ed77aaca7dd20a0f529d32&v=4
|
||||
url: https://github.com/ramonalmeidam
|
||||
- login: dudikbender
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4
|
||||
url: https://github.com/dudikbender
|
||||
- login: Amirshox
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/56707784?u=2a2f8cc243d6f5b29cd63fd2772f7a97aadc6c6b&v=4
|
||||
url: https://github.com/Amirshox
|
||||
- login: prodhype
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60444672?u=3f278cff25ea37ead487d7861d4a984795de819e&v=4
|
||||
url: https://github.com/prodhype
|
||||
- login: yakkonaut
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/60633704?u=90a71fd631aa998ba4a96480788f017c9904e07b&v=4
|
||||
url: https://github.com/yakkonaut
|
||||
@@ -260,18 +281,24 @@ sponsors:
|
||||
- login: anthonycepeda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72019805?u=4252c6b6dc5024af502a823a3ac5e7a03a69963f&v=4
|
||||
url: https://github.com/anthonycepeda
|
||||
- login: patricioperezv
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/73832292?u=5f471f156e19ee7920e62ae0f4a47b95580e61cf&v=4
|
||||
url: https://github.com/patricioperezv
|
||||
- login: kaoru0310
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4
|
||||
url: https://github.com/kaoru0310
|
||||
- login: DelfinaCare
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/83734439?v=4
|
||||
url: https://github.com/DelfinaCare
|
||||
- login: osawa-koki
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/94336223?u=59c6fe6945bcbbaff87b2a794238671b060620d2&v=4
|
||||
url: https://github.com/osawa-koki
|
||||
- login: pyt3h
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/99658549?v=4
|
||||
url: https://github.com/pyt3h
|
||||
- - login: SebTota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4
|
||||
url: https://github.com/SebTota
|
||||
- login: apitally
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/138365043?v=4
|
||||
url: https://github.com/apitally
|
||||
- - login: getsentry
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1396951?v=4
|
||||
url: https://github.com/getsentry
|
||||
- - login: pawamoy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3999221?u=b030e4c89df2f3a36bc4710b925bdeb6745c9856&v=4
|
||||
url: https://github.com/pawamoy
|
||||
@@ -281,9 +308,6 @@ sponsors:
|
||||
- login: bryanculbertson
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/144028?u=defda4f90e93429221cc667500944abde60ebe4a&v=4
|
||||
url: https://github.com/bryanculbertson
|
||||
- login: yourkin
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/178984?u=b43a7e5f8818f7d9083d3b110118d9c27d48a794&v=4
|
||||
url: https://github.com/yourkin
|
||||
- login: slafs
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/210173?v=4
|
||||
url: https://github.com/slafs
|
||||
@@ -299,15 +323,18 @@ sponsors:
|
||||
- login: securancy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/606673?v=4
|
||||
url: https://github.com/securancy
|
||||
- login: natehouk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/805439?u=d8e4be629dc5d7efae7146157e41ee0bd129d9bc&v=4
|
||||
url: https://github.com/natehouk
|
||||
- login: browniebroke
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4
|
||||
url: https://github.com/browniebroke
|
||||
- login: janfilips
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/870699?u=80702ec63f14e675cd4cdcc6ce3821d2ed207fd7&v=4
|
||||
url: https://github.com/janfilips
|
||||
- login: dodo5522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1362607?u=9bf1e0e520cccc547c046610c468ce6115bbcf9f&v=4
|
||||
url: https://github.com/dodo5522
|
||||
- login: miguelgr
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4
|
||||
url: https://github.com/miguelgr
|
||||
- login: WillHogan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1661551?u=7036c064cf29781470573865264ec8e60b6b809f&v=4
|
||||
url: https://github.com/WillHogan
|
||||
@@ -323,15 +350,12 @@ sponsors:
|
||||
- login: anthonycorletti
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3477132?v=4
|
||||
url: https://github.com/anthonycorletti
|
||||
- login: nikeee
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4068864?u=bbe73151f2b409c120160d032dc9aa6875ef0c4b&v=4
|
||||
url: https://github.com/nikeee
|
||||
- login: Alisa-lisa
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4137964?u=e7e393504f554f4ff15863a1e01a5746863ef9ce&v=4
|
||||
url: https://github.com/Alisa-lisa
|
||||
- login: piotrgredowski
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4294480?v=4
|
||||
url: https://github.com/piotrgredowski
|
||||
- login: gowikel
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4339072?u=0e325ffcc539c38f89d9aa876bd87f9ec06ce0ee&v=4
|
||||
url: https://github.com/gowikel
|
||||
- login: danielunderwood
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4472301?v=4
|
||||
url: https://github.com/danielunderwood
|
||||
@@ -347,6 +371,9 @@ sponsors:
|
||||
- login: Baghdady92
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5708590?v=4
|
||||
url: https://github.com/Baghdady92
|
||||
- login: jakeecolution
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/5884696?u=4a7c7883fb064b593b50cb6697b54687e6f7aafe&v=4
|
||||
url: https://github.com/jakeecolution
|
||||
- login: KentShikama
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6329898?u=8b236810db9b96333230430837e1f021f9246da1&v=4
|
||||
url: https://github.com/KentShikama
|
||||
@@ -366,7 +393,7 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/8574425?u=aad2a9674273c9275fe414d99269b7418d144089&v=4
|
||||
url: https://github.com/albertkun
|
||||
- login: xncbf
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=866a1311e4bd3ec5ae84185c4fcc99f397c883d7&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9462045?u=ee91e210ae93b9cdd8f248b21cb028316cc0b747&v=4
|
||||
url: https://github.com/xncbf
|
||||
- login: DMantis
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9536869?v=4
|
||||
@@ -386,30 +413,42 @@ sponsors:
|
||||
- login: pheanex
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10408624?u=5b6bab6ee174aa6e991333e06eb29f628741013d&v=4
|
||||
url: https://github.com/pheanex
|
||||
- login: dzoladz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10561752?u=5ee314d54aa79592c18566827ad8914debd5630d&v=4
|
||||
url: https://github.com/dzoladz
|
||||
- login: JimFawkes
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12075115?u=dc58ecfd064d72887c34bf500ddfd52592509acd&v=4
|
||||
url: https://github.com/JimFawkes
|
||||
- login: artempronevskiy
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/12235104?u=03df6e1e55c9c6fe5d230adabb8dd7d43d8bbe8f&v=4
|
||||
url: https://github.com/artempronevskiy
|
||||
- login: giuliano-oliveira
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13181797?u=0ef2dfbf7fc9a9726d45c21d32b5d1038a174870&v=4
|
||||
url: https://github.com/giuliano-oliveira
|
||||
- login: TheR1D
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16740832?u=b0dfdbdb27b79729430c71c6128962f77b7b53f7&v=4
|
||||
url: https://github.com/TheR1D
|
||||
- login: joshuatz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4
|
||||
url: https://github.com/joshuatz
|
||||
- login: jangia
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/17927101?u=9261b9bb0c3e3bb1ecba43e8915dc58d8c9a077e&v=4
|
||||
url: https://github.com/jangia
|
||||
- login: timzaz
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/19709244?u=264d7db95c28156363760229c30ee1116efd4eeb&v=4
|
||||
url: https://github.com/timzaz
|
||||
- login: shuheng-liu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22414322?u=813c45f30786c6b511b21a661def025d8f7b609e&v=4
|
||||
url: https://github.com/shuheng-liu
|
||||
- login: salahelfarissi
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23387408?u=73222a4be627c1a3dee9736e0da22224eccdc8f6&v=4
|
||||
url: https://github.com/salahelfarissi
|
||||
- login: pers0n4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24864600?u=f211a13a7b572cbbd7779b9c8d8cb428cc7ba07e&v=4
|
||||
url: https://github.com/pers0n4
|
||||
- login: kxzk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25046261?u=e185e58080090f9e678192cd214a14b14a2b232b&v=4
|
||||
url: https://github.com/kxzk
|
||||
- login: SebTota
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25122511?v=4
|
||||
url: https://github.com/SebTota
|
||||
- login: nisutec
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25281462?u=e562484c451fdfc59053163f64405f8eb262b8b0&v=4
|
||||
url: https://github.com/nisutec
|
||||
@@ -419,15 +458,12 @@ sponsors:
|
||||
- login: joerambo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26282974?v=4
|
||||
url: https://github.com/joerambo
|
||||
- login: msniezynski
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27588547?u=0e3be5ac57dcfdf124f470bcdf74b5bf79af1b6c&v=4
|
||||
url: https://github.com/msniezynski
|
||||
- login: rlnchow
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28018479?u=a93ca9cf1422b9ece155784a72d5f2fdbce7adff&v=4
|
||||
url: https://github.com/rlnchow
|
||||
- login: mertguvencli
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/29762151?u=16a906d90df96c8cff9ea131a575c4bc171b1523&v=4
|
||||
url: https://github.com/mertguvencli
|
||||
- login: White-Mask
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31826970?u=8625355dc25ddf9c85a8b2b0b9932826c4c8f44c&v=4
|
||||
url: https://github.com/White-Mask
|
||||
- login: HosamAlmoghraby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32025281?u=aa1b09feabccbf9dc506b81c71155f32d126cefa&v=4
|
||||
url: https://github.com/HosamAlmoghraby
|
||||
@@ -435,17 +471,11 @@ sponsors:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4
|
||||
url: https://github.com/engineerjoe440
|
||||
- login: bnkc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=1a104991a2ea90bfe304bc0b9ef191c7e4891a0e&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34930566?u=fa1dc8db3e920cf5c5636b97180a6f811fa01aaf&v=4
|
||||
url: https://github.com/bnkc
|
||||
- login: declon
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36180226?v=4
|
||||
url: https://github.com/declon
|
||||
- login: miraedbswo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/36796047?u=9e7a5b3e558edc61d35d0f9dfac37541bae7f56d&v=4
|
||||
url: https://github.com/miraedbswo
|
||||
- login: DSMilestone6538
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37230924?u=f299dce910366471523155e0cb213356d34aadc1&v=4
|
||||
url: https://github.com/DSMilestone6538
|
||||
- login: curegit
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37978051?u=1733c322079118c0cdc573c03d92813f50a9faec&v=4
|
||||
url: https://github.com/curegit
|
||||
@@ -458,51 +488,51 @@ sponsors:
|
||||
- login: ArtyomVancyan
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/44609997?v=4
|
||||
url: https://github.com/ArtyomVancyan
|
||||
- login: josehenriqueroveda
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/46685746?u=2e672057a7dbe1dba47e57c378fc0cac336022eb&v=4
|
||||
url: https://github.com/josehenriqueroveda
|
||||
- login: hgalytoby
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=f4888c2c54929bd86eed0d3971d09fcb306e5088&v=4
|
||||
url: https://github.com/hgalytoby
|
||||
- login: eladgunders
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52347338?u=83d454817cf991a035c8827d46ade050c813e2d6&v=4
|
||||
url: https://github.com/eladgunders
|
||||
- login: conservative-dude
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4
|
||||
url: https://github.com/conservative-dude
|
||||
- login: Calesi19
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/58052598?u=273d4fc364c004602c93dd6adeaf5cc915b93cd2&v=4
|
||||
url: https://github.com/Calesi19
|
||||
- login: 0417taehyun
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/63915557?u=47debaa860fd52c9b98c97ef357ddcec3b3fb399&v=4
|
||||
url: https://github.com/0417taehyun
|
||||
- login: fernandosmither
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66154723?u=a76a037b5d674938a75d2cff862fb6dfd63ec214&v=4
|
||||
url: https://github.com/fernandosmither
|
||||
- login: romabozhanovgithub
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67696229?u=e4b921eef096415300425aca249348f8abb78ad7&v=4
|
||||
url: https://github.com/romabozhanovgithub
|
||||
- login: mbukeRepo
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/70356088?u=d2eb23e2b222a3b316c4183b05a3236b32819dc2&v=4
|
||||
url: https://github.com/mbukeRepo
|
||||
- login: adriiamontoto
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/75563346?u=eeb1350b82ecb4d96592f9b6cd1a16870c355e38&v=4
|
||||
url: https://github.com/adriiamontoto
|
||||
- login: PelicanQ
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4
|
||||
url: https://github.com/PelicanQ
|
||||
- login: tahmarrrr23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/138208610?u=465a46b0ff72a74252d3e3a71ac7d2f1919cda28&v=4
|
||||
url: https://github.com/tahmarrrr23
|
||||
- - login: ssbarnea
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/102495?u=b4bf6818deefe59952ac22fec6ed8c76de1b8f7c&v=4
|
||||
url: https://github.com/ssbarnea
|
||||
- login: Patechoc
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2376641?u=23b49e9eda04f078cb74fa3f93593aa6a57bb138&v=4
|
||||
url: https://github.com/Patechoc
|
||||
- login: LanceMoe
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/18505474?u=7fd3ead4364bdf215b6d75cb122b3811c391ef6b&v=4
|
||||
url: https://github.com/LanceMoe
|
||||
- login: DazzyMlv
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23006212?u=df429da52882b0432e5ac81d4f1b489abc86433c&v=4
|
||||
url: https://github.com/DazzyMlv
|
||||
- login: sadikkuzu
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/23168063?u=d179c06bb9f65c4167fcab118526819f8e0dac17&v=4
|
||||
url: https://github.com/sadikkuzu
|
||||
- login: samnimoh
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/33413170?u=147bc516be6cb647b28d7e3b3fea3a018a331145&v=4
|
||||
url: https://github.com/samnimoh
|
||||
- login: danburonline
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=2cad4388c1544e539ecb732d656e42fb07b4ff2d&v=4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/34251194?u=94935cccfbec58083ab1e535212d54f1bf2c978a&v=4
|
||||
url: https://github.com/danburonline
|
||||
- login: rwxd
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/40308458?u=cd04a39e3655923be4f25c2ba8a5a07b3da3230a&v=4
|
||||
url: https://github.com/rwxd
|
||||
- login: shywn-mrk
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51455763?u=389e2608e4056fe5e1f23e9ad56a9415277504d3&v=4
|
||||
url: https://github.com/shywn-mrk
|
||||
- login: almeida-matheus
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/66216198?u=54335eaa0ced626be5c1ff52fead1ebc032286ec&v=4
|
||||
url: https://github.com/almeida-matheus
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
maintainers:
|
||||
- login: tiangolo
|
||||
answers: 1868
|
||||
prs: 496
|
||||
answers: 1870
|
||||
prs: 523
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=740f11212a731f56798f558ceddb0bd07642afa7&v=4
|
||||
url: https://github.com/tiangolo
|
||||
experts:
|
||||
- login: Kludex
|
||||
count: 501
|
||||
count: 522
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: dmontagu
|
||||
count: 240
|
||||
count: 241
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
url: https://github.com/dmontagu
|
||||
- login: Mause
|
||||
@@ -21,26 +21,26 @@ experts:
|
||||
count: 217
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: jgould22
|
||||
count: 205
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: JarroVGIT
|
||||
count: 193
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13659033?u=e8bea32d07a5ef72f7dde3b2079ceb714923ca05&v=4
|
||||
url: https://github.com/JarroVGIT
|
||||
- login: jgould22
|
||||
count: 168
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: euri10
|
||||
count: 153
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1104190?u=321a2e953e6645a7d09b732786c7a8061e0f8a8b&v=4
|
||||
url: https://github.com/euri10
|
||||
- login: iudeen
|
||||
count: 127
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: phy25
|
||||
count: 126
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/331403?v=4
|
||||
url: https://github.com/phy25
|
||||
- login: iudeen
|
||||
count: 122
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: raphaelauv
|
||||
count: 83
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10202690?u=e6f86f5c0c3026a15d6b51792fa3e532b12f1371&v=4
|
||||
@@ -61,26 +61,26 @@ experts:
|
||||
count: 49
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/516999?u=437c0c5038558c67e887ccd863c1ba0f846c03da&v=4
|
||||
url: https://github.com/sm-Fifteen
|
||||
- login: acidjunk
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: yinziyan1206
|
||||
count: 48
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: insomnes
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16958893?u=f8be7088d5076d963984a21f95f44e559192d912&v=4
|
||||
url: https://github.com/insomnes
|
||||
- login: Dustyposa
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||
url: https://github.com/Dustyposa
|
||||
- login: adriangb
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4
|
||||
url: https://github.com/adriangb
|
||||
- login: yinziyan1206
|
||||
count: 44
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/37829370?u=da44ca53aefd5c23f346fab8e9fd2e108294c179&v=4
|
||||
url: https://github.com/yinziyan1206
|
||||
- login: acidjunk
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/685002?u=b5094ab4527fc84b006c0ac9ff54367bdebb2267&v=4
|
||||
url: https://github.com/acidjunk
|
||||
- login: Dustyposa
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/27180793?u=5cf2877f50b3eb2bc55086089a78a36f07042889&v=4
|
||||
url: https://github.com/Dustyposa
|
||||
- login: odiseo0
|
||||
count: 43
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87550035?u=241a71f6b7068738b81af3e57f45ffd723538401&v=4
|
||||
@@ -93,6 +93,10 @@ experts:
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/11836741?u=8bd5ef7e62fe6a82055e33c4c0e0a7879ff8cfb6&v=4
|
||||
url: https://github.com/includeamin
|
||||
- login: n8sty
|
||||
count: 40
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
- login: chbndrhnns
|
||||
count: 38
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7534547?v=4
|
||||
@@ -105,14 +109,14 @@ experts:
|
||||
count: 35
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/31960541?u=47f4829c77f4962ab437ffb7995951e41eeebe9b&v=4
|
||||
url: https://github.com/krishnardt
|
||||
- login: n8sty
|
||||
count: 32
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
- login: panla
|
||||
count: 32
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41326348?u=ba2fda6b30110411ecbf406d187907e2b420ac19&v=4
|
||||
url: https://github.com/panla
|
||||
- login: JavierSanchezCastro
|
||||
count: 30
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4
|
||||
url: https://github.com/JavierSanchezCastro
|
||||
- login: prostomarkeloff
|
||||
count: 28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/28061158?u=72309cc1f2e04e40fa38b29969cb4e9d3f722e7b&v=4
|
||||
@@ -125,22 +129,22 @@ experts:
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4
|
||||
url: https://github.com/wshayes
|
||||
- login: SirTelemak
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
|
||||
url: https://github.com/SirTelemak
|
||||
- login: acnebs
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9054108?v=4
|
||||
url: https://github.com/acnebs
|
||||
- login: SirTelemak
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/9435877?u=719327b7d2c4c62212456d771bfa7c6b8dbb9eac&v=4
|
||||
url: https://github.com/SirTelemak
|
||||
- login: rafsaf
|
||||
count: 21
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/51059348?u=5fe59a56e1f2f9ccd8005d71752a8276f133ae1a&v=4
|
||||
url: https://github.com/rafsaf
|
||||
- login: JavierSanchezCastro
|
||||
- login: nymous
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4
|
||||
url: https://github.com/JavierSanchezCastro
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4
|
||||
url: https://github.com/nymous
|
||||
- login: nsidnev
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22559461?u=a9cc3238217e21dc8796a1a500f01b722adb082c&v=4
|
||||
@@ -150,21 +154,21 @@ experts:
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/565544?v=4
|
||||
url: https://github.com/chris-allnutt
|
||||
- login: chrisK824
|
||||
count: 19
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4
|
||||
url: https://github.com/chrisK824
|
||||
- login: zoliknemet
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
|
||||
url: https://github.com/zoliknemet
|
||||
- login: ebottos94
|
||||
count: 20
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4
|
||||
url: https://github.com/ebottos94
|
||||
- login: retnikt
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24581770?v=4
|
||||
url: https://github.com/retnikt
|
||||
- login: ebottos94
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/100039558?u=e2c672da5a7977fd24d87ce6ab35f8bf5b1ed9fa&v=4
|
||||
url: https://github.com/ebottos94
|
||||
- login: zoliknemet
|
||||
count: 18
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/22326718?u=31ba446ac290e23e56eea8e4f0c558aaf0b40779&v=4
|
||||
url: https://github.com/zoliknemet
|
||||
- login: Hultner
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2669034?u=115e53df959309898ad8dc9443fbb35fee71df07&v=4
|
||||
@@ -181,39 +185,39 @@ experts:
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16540232?u=05d2beb8e034d584d0a374b99d8826327bd7f614&v=4
|
||||
url: https://github.com/caeser1996
|
||||
- login: nymous
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4
|
||||
url: https://github.com/nymous
|
||||
- login: jonatasoli
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
||||
url: https://github.com/jonatasoli
|
||||
- login: dstlny
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41964673?u=9f2174f9d61c15c6e3a4c9e3aeee66f711ce311f&v=4
|
||||
url: https://github.com/dstlny
|
||||
- login: abhint
|
||||
- login: jonatasoli
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/26334101?u=071c062d2861d3dd127f6b4a5258cd8ef55d4c50&v=4
|
||||
url: https://github.com/jonatasoli
|
||||
- login: ghost
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/25699289?u=b5d219277b4d001ac26fb8be357fddd88c29d51b&v=4
|
||||
url: https://github.com/abhint
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10137?u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4
|
||||
url: https://github.com/ghost
|
||||
last_month_active:
|
||||
- login: Ventura94
|
||||
count: 5
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43103937?u=ccb837005aaf212a449c374618c4339089e2f733&v=4
|
||||
url: https://github.com/Ventura94
|
||||
- login: JavierSanchezCastro
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/72013291?u=ae5679e6bd971d9d98cd5e76e8683f83642ba950&v=4
|
||||
url: https://github.com/JavierSanchezCastro
|
||||
- login: jgould22
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4335847?u=ed77f67e0bb069084639b24d812dbb2a2b1dc554&v=4
|
||||
url: https://github.com/jgould22
|
||||
- login: Kludex
|
||||
count: 8
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: n8sty
|
||||
count: 7
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2964996?v=4
|
||||
url: https://github.com/n8sty
|
||||
- login: chrisK824
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/79946379?u=03d85b22d696a58a9603e55fbbbe2de6b0f4face&v=4
|
||||
url: https://github.com/chrisK824
|
||||
- login: danielfcollier
|
||||
count: 3
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/38995330?u=5799be795fc310f75f3a5fe9242307d59b194520&v=4
|
||||
url: https://github.com/danielfcollier
|
||||
top_contributors:
|
||||
- login: waynerv
|
||||
count: 25
|
||||
@@ -331,6 +335,10 @@ top_contributors:
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: adriangb
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4
|
||||
url: https://github.com/adriangb
|
||||
- login: iudeen
|
||||
count: 4
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
@@ -349,25 +357,29 @@ top_contributors:
|
||||
url: https://github.com/rostik1410
|
||||
top_reviewers:
|
||||
- login: Kludex
|
||||
count: 139
|
||||
count: 145
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/7353520?u=62adc405ef418f4b6c8caa93d3eb8ab107bc4927&v=4
|
||||
url: https://github.com/Kludex
|
||||
- login: yezz123
|
||||
count: 80
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4
|
||||
url: https://github.com/yezz123
|
||||
- login: BilalAlpaslan
|
||||
count: 79
|
||||
count: 86
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/47563997?u=63ed66e304fe8d765762c70587d61d9196e5c82d&v=4
|
||||
url: https://github.com/BilalAlpaslan
|
||||
- login: yezz123
|
||||
count: 82
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52716203?u=d7062cbc6eb7671d5dc9cc0e32a24ae335e0f225&v=4
|
||||
url: https://github.com/yezz123
|
||||
- login: iudeen
|
||||
count: 54
|
||||
count: 55
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/10519440?u=2843b3303282bff8b212dcd4d9d6689452e4470c&v=4
|
||||
url: https://github.com/iudeen
|
||||
- login: tokusumi
|
||||
count: 51
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/41147016?u=55010621aece725aa702270b54fed829b6a1fe60&v=4
|
||||
url: https://github.com/tokusumi
|
||||
- login: Xewus
|
||||
count: 50
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: waynerv
|
||||
count: 47
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4
|
||||
@@ -380,10 +392,6 @@ top_reviewers:
|
||||
count: 45
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/62724709?u=bba5af018423a2858d49309bed2a899bb5c34ac5&v=4
|
||||
url: https://github.com/ycd
|
||||
- login: Xewus
|
||||
count: 44
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/85196001?u=f8e2dc7e5104f109cef944af79050ea8d1b8f914&v=4
|
||||
url: https://github.com/Xewus
|
||||
- login: cikay
|
||||
count: 41
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/24587499?u=e772190a051ab0eaa9c8542fcff1892471638f2b&v=4
|
||||
@@ -404,22 +412,22 @@ top_reviewers:
|
||||
count: 28
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/3127847?u=b0a652331da17efeb85cd6e3a4969182e5004804&v=4
|
||||
url: https://github.com/cassiobotaro
|
||||
- login: lsglucas
|
||||
count: 27
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: komtaki
|
||||
count: 27
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/39375566?u=260ad6b1a4b34c07dbfa728da5e586f16f6d1824&v=4
|
||||
url: https://github.com/komtaki
|
||||
- login: lsglucas
|
||||
count: 26
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/61513630?u=320e43fe4dc7bc6efc64e9b8f325f8075634fd20&v=4
|
||||
url: https://github.com/lsglucas
|
||||
- login: Ryandaydev
|
||||
count: 25
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=48f68868db8886fce31a1d802c1003914c6cd7c6&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: LorhanSohaky
|
||||
count: 24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16273730?u=095b66f243a2cd6a0aadba9a095009f8aaf18393&v=4
|
||||
url: https://github.com/LorhanSohaky
|
||||
- login: Ryandaydev
|
||||
count: 24
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=809f3d1074d04bbc28012a7f17f06ea56f5bd71a&v=4
|
||||
url: https://github.com/Ryandaydev
|
||||
- login: dmontagu
|
||||
count: 23
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4
|
||||
@@ -448,6 +456,10 @@ top_reviewers:
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/67154681?u=5d634834cc514028ea3f9115f7030b99a1f4d5a4&v=4
|
||||
url: https://github.com/zy7y
|
||||
- login: peidrao
|
||||
count: 17
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=a66902b40c13647d0ed0e573d598128240a4dd04&v=4
|
||||
url: https://github.com/peidrao
|
||||
- login: yanever
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/21978760?v=4
|
||||
@@ -456,6 +468,10 @@ top_reviewers:
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/52768429?u=6a3aa15277406520ad37f6236e89466ed44bc5b8&v=4
|
||||
url: https://github.com/SwftAlpc
|
||||
- login: nilslindemann
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6892179?u=1dca6a22195d6cd1ab20737c0e19a4c55d639472&v=4
|
||||
url: https://github.com/nilslindemann
|
||||
- login: axel584
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/1334088?u=9667041f5b15dc002b6f9665fda8c0412933ac04&v=4
|
||||
@@ -468,6 +484,10 @@ top_reviewers:
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/87962045?u=08e10fa516e844934f4b3fc7c38b33c61697e4a1&v=4
|
||||
url: https://github.com/DevDae
|
||||
- login: hasansezertasan
|
||||
count: 16
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13135006?u=99f0b0f0fc47e88e8abb337b4447357939ef93e7&v=4
|
||||
url: https://github.com/hasansezertasan
|
||||
- login: pedabraham
|
||||
count: 15
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/16860088?u=abf922a7b920bf8fdb7867d8b43e091f1e796178&v=4
|
||||
@@ -480,10 +500,6 @@ top_reviewers:
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/6478810?u=af15d724875cec682ed8088a86d36b2798f981c0&v=4
|
||||
url: https://github.com/sh0nk
|
||||
- login: peidrao
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/32584628?u=a66902b40c13647d0ed0e573d598128240a4dd04&v=4
|
||||
url: https://github.com/peidrao
|
||||
- login: wdh99
|
||||
count: 13
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/108172295?u=8a8fb95d5afe3e0fa33257b2aecae88d436249eb&v=4
|
||||
@@ -524,6 +540,10 @@ top_reviewers:
|
||||
count: 10
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/43503750?u=f440bc9062afb3c43b9b9c6cdfdcfe31d58699ef&v=4
|
||||
url: https://github.com/ComicShrimp
|
||||
- login: romashevchenko
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/132477732?v=4
|
||||
url: https://github.com/romashevchenko
|
||||
- login: izaguerreiro
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/2241504?v=4
|
||||
@@ -532,15 +552,3 @@ top_reviewers:
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/413772?u=64b77b6aa405c68a9c6bcf45f84257c66eea5f32&v=4
|
||||
url: https://github.com/graingert
|
||||
- login: PandaHun
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/13096845?u=646eba44db720e37d0dbe8e98e77ab534ea78a20&v=4
|
||||
url: https://github.com/PandaHun
|
||||
- login: kty4119
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/49435654?v=4
|
||||
url: https://github.com/kty4119
|
||||
- login: bezaca
|
||||
count: 9
|
||||
avatarUrl: https://avatars.githubusercontent.com/u/69092910?u=4ac58eab99bd37d663f3d23551df96d4fbdbf760&v=4
|
||||
url: https://github.com/bezaca
|
||||
|
||||
@@ -84,6 +84,9 @@ response = client.get('/')
|
||||
!!! tip
|
||||
Note that we're using async/await with the new `AsyncClient` - the request is asynchronous.
|
||||
|
||||
!!! warning
|
||||
If your application relies on lifespan events, the `AsyncClient` won't trigger these events. To ensure they are triggered, use `LifespanManager` from <a href="florimondmanca/asgi-lifespan" class="external-link" target="_blank">https://github.com/florimondmanca/asgi-lifespan#usage</a>.
|
||||
|
||||
## Other Asynchronous Function Calls
|
||||
|
||||
As the testing function is now asynchronous, you can now also call (and `await`) other `async` functions apart from sending requests to your FastAPI application in your tests, exactly as you would call them anywhere else in your code.
|
||||
|
||||
@@ -229,9 +229,17 @@ But for the generated client we could **modify** the OpenAPI operation IDs right
|
||||
|
||||
We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this:
|
||||
|
||||
```Python
|
||||
{!../../../docs_src/generate_clients/tutorial004.py!}
|
||||
```
|
||||
=== "Python"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/generate_clients/tutorial004.py!}
|
||||
```
|
||||
|
||||
=== "Node.js"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/generate_clients/tutorial004.js!}
|
||||
```
|
||||
|
||||
With that, the operation IDs would be renamed from things like `items-get_items` to just `get_items`, that way the client generator can generate simpler method names.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ This part is pretty normal, most of the code is probably already familiar to you
|
||||
!!! tip
|
||||
The `callback_url` query parameter uses a Pydantic <a href="https://pydantic-docs.helpmanual.io/usage/types/#urls" class="external-link" target="_blank">URL</a> type.
|
||||
|
||||
The only new thing is the `callbacks=messages_callback_router.routes` as an argument to the *path operation decorator*. We'll see what that is next.
|
||||
The only new thing is the `callbacks=invoices_callback_router.routes` as an argument to the *path operation decorator*. We'll see what that is next.
|
||||
|
||||
## Documenting the callback
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
|
||||
...
|
||||
```
|
||||
|
||||
But right at the moment Python compares the first `j` in `johndoe` to the first `s` in `stanleyjobson`, it will return `False`, because it already knows that those two strings are not the same, thinking that "there's no need to waste more computation comparing the rest of the letters". And your application will say "incorrect user or password".
|
||||
But right at the moment Python compares the first `j` in `johndoe` to the first `s` in `stanleyjobson`, it will return `False`, because it already knows that those two strings are not the same, thinking that "there's no need to waste more computation comparing the rest of the letters". And your application will say "Incorrect username or password".
|
||||
|
||||
But then the attackers try with username `stanleyjobsox` and password `love123`.
|
||||
|
||||
@@ -116,11 +116,11 @@ if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
|
||||
...
|
||||
```
|
||||
|
||||
Python will have to compare the whole `stanleyjobso` in both `stanleyjobsox` and `stanleyjobson` before realizing that both strings are not the same. So it will take some extra microseconds to reply back "incorrect user or password".
|
||||
Python will have to compare the whole `stanleyjobso` in both `stanleyjobsox` and `stanleyjobson` before realizing that both strings are not the same. So it will take some extra microseconds to reply back "Incorrect username or password".
|
||||
|
||||
#### The time to answer helps the attackers
|
||||
|
||||
At that point, by noticing that the server took some microseconds longer to send the "incorrect user or password" response, the attackers will know that they got _something_ right, some of the initial letters were right.
|
||||
At that point, by noticing that the server took some microseconds longer to send the "Incorrect username or password" response, the attackers will know that they got _something_ right, some of the initial letters were right.
|
||||
|
||||
And then they can try again knowing that it's probably something more similar to `stanleyjobsox` than to `johndoe`.
|
||||
|
||||
|
||||
@@ -25,14 +25,16 @@ $ pip install jinja2
|
||||
* Import `Jinja2Templates`.
|
||||
* Create a `templates` object that you can re-use later.
|
||||
* Declare a `Request` parameter in the *path operation* that will return a template.
|
||||
* Use the `templates` you created to render and return a `TemplateResponse`, passing the `request` as one of the key-value pairs in the Jinja2 "context".
|
||||
* Use the `templates` you created to render and return a `TemplateResponse`, pass the name of the template, the request object, and a "context" dictionary with key-value pairs to be used inside of the Jinja2 template.
|
||||
|
||||
```Python hl_lines="4 11 15-16"
|
||||
```Python hl_lines="4 11 15-18"
|
||||
{!../../../docs_src/templates/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
Notice that you have to pass the `request` as part of the key-value pairs in the context for Jinja2. So, you also have to declare it in your *path operation*.
|
||||
Before FastAPI 0.108.0, Starlette 0.29.0, the `name` was the first parameter.
|
||||
|
||||
Also, before that, in previous versions, the `request` object was passed as part of the key-value pairs in the context for Jinja2.
|
||||
|
||||
!!! tip
|
||||
By declaring `response_class=HTMLResponse` the docs UI will be able to know that the response will be HTML.
|
||||
@@ -58,7 +60,7 @@ It will show the `id` taken from the "context" `dict` you passed:
|
||||
|
||||
## Templates and static files
|
||||
|
||||
And you can also use `url_for()` inside of the template, and use it, for example, with the `StaticFiles` you mounted.
|
||||
You can also use `url_for()` inside of the template, and use it, for example, with the `StaticFiles` you mounted.
|
||||
|
||||
```jinja hl_lines="4"
|
||||
{!../../../docs_src/templates/templates/item.html!}
|
||||
|
||||
@@ -185,13 +185,13 @@ It's a Flask plug-in, that ties together Webargs, Marshmallow and APISpec.
|
||||
|
||||
It uses the information from Webargs and Marshmallow to automatically generate OpenAPI schemas, using APISpec.
|
||||
|
||||
It's a great tool, very under-rated. It should be way more popular than many Flask plug-ins out there. It might be due to its documentation being too concise and abstract.
|
||||
It's a great tool, very underrated. It should be way more popular than many Flask plug-ins out there. It might be due to its documentation being too concise and abstract.
|
||||
|
||||
This solved having to write YAML (another syntax) inside of Python docstrings.
|
||||
|
||||
This combination of Flask, Flask-apispec with Marshmallow and Webargs was my favorite backend stack until building **FastAPI**.
|
||||
|
||||
Using it led to the creation of several Flask full-stack generators. These are the main stack I (and several external teams) have been using up to now:
|
||||
Using it led to the creation of several Flask full-stack generators. These are the main stacks I (and several external teams) have been using up to now:
|
||||
|
||||
* <a href="https://github.com/tiangolo/full-stack" class="external-link" target="_blank">https://github.com/tiangolo/full-stack</a>
|
||||
* <a href="https://github.com/tiangolo/full-stack-flask-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-flask-couchbase</a>
|
||||
@@ -211,7 +211,7 @@ This isn't even Python, NestJS is a JavaScript (TypeScript) NodeJS framework ins
|
||||
|
||||
It achieves something somewhat similar to what can be done with Flask-apispec.
|
||||
|
||||
It has an integrated dependency injection system, inspired by Angular two. It requires pre-registering the "injectables" (like all the other dependency injection systems I know), so, it adds to the verbosity and code repetition.
|
||||
It has an integrated dependency injection system, inspired by Angular 2. It requires pre-registering the "injectables" (like all the other dependency injection systems I know), so, it adds to the verbosity and code repetition.
|
||||
|
||||
As the parameters are described with TypeScript types (similar to Python type hints), editor support is quite good.
|
||||
|
||||
@@ -263,7 +263,7 @@ I discovered Molten in the first stages of building **FastAPI**. And it has quit
|
||||
|
||||
It doesn't use a data validation, serialization and documentation third-party library like Pydantic, it has its own. So, these data type definitions would not be reusable as easily.
|
||||
|
||||
It requires a little bit more verbose configurations. And as it is based on WSGI (instead of ASGI), it is not designed to take advantage of the high-performance provided by tools like Uvicorn, Starlette and Sanic.
|
||||
It requires a little bit more verbose configurations. And as it is based on WSGI (instead of ASGI), it is not designed to take advantage of the high performance provided by tools like Uvicorn, Starlette and Sanic.
|
||||
|
||||
The dependency injection system requires pre-registration of the dependencies and the dependencies are solved based on the declared types. So, it's not possible to declare more than one "component" that provides a certain type.
|
||||
|
||||
@@ -357,7 +357,7 @@ It is comparable to Marshmallow. Although it's faster than Marshmallow in benchm
|
||||
|
||||
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
|
||||
|
||||
Starlette is a lightweight <abbr title="The new standard for building asynchronous Python web">ASGI</abbr> framework/toolkit, which is ideal for building high-performance asyncio services.
|
||||
Starlette is a lightweight <abbr title="The new standard for building asynchronous Python web applications">ASGI</abbr> framework/toolkit, which is ideal for building high-performance asyncio services.
|
||||
|
||||
It is very simple and intuitive. It's designed to be easily extensible, and have modular components.
|
||||
|
||||
|
||||
@@ -150,32 +150,7 @@ For it to sort them correctly, you need to have FastAPI installed locally in you
|
||||
|
||||
First, make sure you set up your environment as described above, that will install all the requirements.
|
||||
|
||||
The documentation uses <a href="https://www.mkdocs.org/" class="external-link" target="_blank">MkDocs</a>.
|
||||
|
||||
And there are extra tools/scripts in place to handle translations in `./scripts/docs.py`.
|
||||
|
||||
!!! tip
|
||||
You don't need to see the code in `./scripts/docs.py`, you just use it in the command line.
|
||||
|
||||
All the documentation is in Markdown format in the directory `./docs/en/`.
|
||||
|
||||
Many of the tutorials have blocks of code.
|
||||
|
||||
In most of the cases, these blocks of code are actual complete applications that can be run as is.
|
||||
|
||||
In fact, those blocks of code are not written inside the Markdown, they are Python files in the `./docs_src/` directory.
|
||||
|
||||
And those Python files are included/injected in the documentation when generating the site.
|
||||
|
||||
### Docs for tests
|
||||
|
||||
Most of the tests actually run against the example source files in the documentation.
|
||||
|
||||
This helps making sure that:
|
||||
|
||||
* The documentation is up to date.
|
||||
* The documentation examples can be run as is.
|
||||
* Most of the features are covered by the documentation, ensured by test coverage.
|
||||
### Docs live
|
||||
|
||||
During local development, there is a script that builds the site and checks for any changes, live-reloading:
|
||||
|
||||
@@ -229,6 +204,37 @@ Completion will take effect once you restart the terminal.
|
||||
|
||||
</div>
|
||||
|
||||
### Docs Structure
|
||||
|
||||
The documentation uses <a href="https://www.mkdocs.org/" class="external-link" target="_blank">MkDocs</a>.
|
||||
|
||||
And there are extra tools/scripts in place to handle translations in `./scripts/docs.py`.
|
||||
|
||||
!!! tip
|
||||
You don't need to see the code in `./scripts/docs.py`, you just use it in the command line.
|
||||
|
||||
All the documentation is in Markdown format in the directory `./docs/en/`.
|
||||
|
||||
Many of the tutorials have blocks of code.
|
||||
|
||||
In most of the cases, these blocks of code are actual complete applications that can be run as is.
|
||||
|
||||
In fact, those blocks of code are not written inside the Markdown, they are Python files in the `./docs_src/` directory.
|
||||
|
||||
And those Python files are included/injected in the documentation when generating the site.
|
||||
|
||||
### Docs for tests
|
||||
|
||||
Most of the tests actually run against the example source files in the documentation.
|
||||
|
||||
This helps making sure that:
|
||||
|
||||
* The documentation is up to date.
|
||||
* The documentation examples can be run as is.
|
||||
* Most of the features are covered by the documentation, ensured by test coverage.
|
||||
|
||||
|
||||
|
||||
### Apps and docs at the same time
|
||||
|
||||
If you run the examples with, e.g.:
|
||||
|
||||
@@ -114,6 +114,11 @@ Create the *path operation function* to create notes:
|
||||
{!../../../docs_src/async_sql_databases/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
|
||||
|
||||
The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
|
||||
|
||||
!!! Note
|
||||
Notice that as we communicate with the database using `await`, the *path operation function* is declared with `async`.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
These are the exceptions that you can raise to show errors to the client.
|
||||
|
||||
When you raise an exception, as would happen with normal Python, the rest of the
|
||||
excecution is aborted. This way you can raise these exceptions from anywhere in the
|
||||
execution is aborted. This way you can raise these exceptions from anywhere in the
|
||||
code to abort a request and show the error to the client.
|
||||
|
||||
You can use:
|
||||
|
||||
@@ -8,7 +8,7 @@ from fastapi import status
|
||||
|
||||
`status` is provided directly by Starlette.
|
||||
|
||||
It containes a group of named constants (variables) with integer status codes.
|
||||
It contains a group of named constants (variables) with integer status codes.
|
||||
|
||||
For example:
|
||||
|
||||
|
||||
@@ -7,6 +7,209 @@ hide:
|
||||
|
||||
## Latest Changes
|
||||
|
||||
## 0.109.0
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add support for Python 3.12. PR [#10666](https://github.com/tiangolo/fastapi/pull/10666) by [@Jamim](https://github.com/Jamim).
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette to >=0.35.0,<0.36.0. PR [#10938](https://github.com/tiangolo/fastapi/pull/10938) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Docs
|
||||
|
||||
* ✏️ Fix typo in `docs/en/docs/alternatives.md`. PR [#10931](https://github.com/tiangolo/fastapi/pull/10931) by [@s111d](https://github.com/s111d).
|
||||
* 📝 Replace `email` with `username` in `docs_src/security/tutorial007` code examples. PR [#10649](https://github.com/tiangolo/fastapi/pull/10649) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 📝 Add VS Code tutorial link. PR [#10592](https://github.com/tiangolo/fastapi/pull/10592) by [@nilslindemann](https://github.com/nilslindemann).
|
||||
* 📝 Add notes about Pydantic v2's new `.model_dump()`. PR [#10929](https://github.com/tiangolo/fastapi/pull/10929) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 📝 Fix broken link in `docs/en/docs/tutorial/sql-databases.md`. PR [#10765](https://github.com/tiangolo/fastapi/pull/10765) by [@HurSungYun](https://github.com/HurSungYun).
|
||||
* 📝 Add External Link: FastAPI application monitoring made easy. PR [#10917](https://github.com/tiangolo/fastapi/pull/10917) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ✨ Generate automatic language names for docs translations. PR [#5354](https://github.com/tiangolo/fastapi/pull/5354) by [@jakul](https://github.com/jakul).
|
||||
* ✏️ Fix typos in `docs/en/docs/alternatives.md` and `docs/en/docs/tutorial/dependencies/index.md`. PR [#10906](https://github.com/tiangolo/fastapi/pull/10906) by [@s111d](https://github.com/s111d).
|
||||
* ✏️ Fix typos in `docs/en/docs/tutorial/dependencies/dependencies-with-yield.md`. PR [#10834](https://github.com/tiangolo/fastapi/pull/10834) by [@Molkree](https://github.com/Molkree).
|
||||
* 📝 Add article: "Building a RESTful API with FastAPI: Secure Signup and Login Functionality Included". PR [#9733](https://github.com/tiangolo/fastapi/pull/9733) by [@dxphilo](https://github.com/dxphilo).
|
||||
* 📝 Add warning about lifecycle events with `AsyncClient`. PR [#4167](https://github.com/tiangolo/fastapi/pull/4167) by [@andrew-chang-dewitt](https://github.com/andrew-chang-dewitt).
|
||||
* ✏️ Fix typos in `/docs/reference/exceptions.md` and `/en/docs/reference/status.md`. PR [#10809](https://github.com/tiangolo/fastapi/pull/10809) by [@clarencepenz](https://github.com/clarencepenz).
|
||||
* ✏️ Fix typo in `openapi-callbacks.md`. PR [#10673](https://github.com/tiangolo/fastapi/pull/10673) by [@kayjan](https://github.com/kayjan).
|
||||
* ✏️ Fix typo in `fastapi/routing.py` . PR [#10520](https://github.com/tiangolo/fastapi/pull/10520) by [@sepsh](https://github.com/sepsh).
|
||||
* 📝 Replace HTTP code returned in case of existing user error in docs for testing. PR [#4482](https://github.com/tiangolo/fastapi/pull/4482) by [@TristanMarion](https://github.com/TristanMarion).
|
||||
* 📝 Add blog for FastAPI & Supabase. PR [#6018](https://github.com/tiangolo/fastapi/pull/6018) by [@theinfosecguy](https://github.com/theinfosecguy).
|
||||
* 📝 Update example source files for SQL databases with SQLAlchemy. PR [#9508](https://github.com/tiangolo/fastapi/pull/9508) by [@s-mustafa](https://github.com/s-mustafa).
|
||||
* 📝 Update code examples in docs for body, replace name `create_item` with `update_item` when appropriate. PR [#5913](https://github.com/tiangolo/fastapi/pull/5913) by [@OttoAndrey](https://github.com/OttoAndrey).
|
||||
* ✏️ Fix typo in dependencies with yield source examples. PR [#10847](https://github.com/tiangolo/fastapi/pull/10847) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Translations
|
||||
|
||||
* 🌐 Add Bengali translation for `docs/bn/docs/index.md`. PR [#9177](https://github.com/tiangolo/fastapi/pull/9177) by [@Fahad-Md-Kamal](https://github.com/Fahad-Md-Kamal).
|
||||
* ✏️ Update Python version in `index.md` in several languages. PR [#10711](https://github.com/tiangolo/fastapi/pull/10711) by [@tamago3keran](https://github.com/tamago3keran).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-forms-and-files.md`. PR [#10347](https://github.com/tiangolo/fastapi/pull/10347) by [@AlertRED](https://github.com/AlertRED).
|
||||
* 🌐 Add Ukrainian translation for `docs/uk/docs/index.md`. PR [#10362](https://github.com/tiangolo/fastapi/pull/10362) by [@rostik1410](https://github.com/rostik1410).
|
||||
* ✏️ Update Python version in `docs/ko/docs/index.md`. PR [#10680](https://github.com/tiangolo/fastapi/pull/10680) by [@Eeap](https://github.com/Eeap).
|
||||
* 🌐 Add Persian translation for `docs/fa/docs/features.md`. PR [#5887](https://github.com/tiangolo/fastapi/pull/5887) by [@amirilf](https://github.com/amirilf).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/advanced/additional-responses.md`. PR [#10325](https://github.com/tiangolo/fastapi/pull/10325) by [@ShuibeiC](https://github.com/ShuibeiC).
|
||||
* 🌐 Fix typos in Russian translations for `docs/ru/docs/tutorial/background-tasks.md`, `docs/ru/docs/tutorial/body-nested-models.md`, `docs/ru/docs/tutorial/debugging.md`, `docs/ru/docs/tutorial/testing.md`. PR [#10311](https://github.com/tiangolo/fastapi/pull/10311) by [@AlertRED](https://github.com/AlertRED).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-files.md`. PR [#10332](https://github.com/tiangolo/fastapi/pull/10332) by [@AlertRED](https://github.com/AlertRED).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/deployment/server-workers.md`. PR [#10292](https://github.com/tiangolo/fastapi/pull/10292) by [@xzmeng](https://github.com/xzmeng).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/deployment/cloud.md`. PR [#10291](https://github.com/tiangolo/fastapi/pull/10291) by [@xzmeng](https://github.com/xzmeng).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#10279](https://github.com/tiangolo/fastapi/pull/10279) by [@xzmeng](https://github.com/xzmeng).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/deployment/https.md`. PR [#10277](https://github.com/tiangolo/fastapi/pull/10277) by [@xzmeng](https://github.com/xzmeng).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/deployment/index.md`. PR [#10275](https://github.com/tiangolo/fastapi/pull/10275) by [@xzmeng](https://github.com/xzmeng).
|
||||
* 🌐 Add German translation for `docs/de/docs/tutorial/first-steps.md`. PR [#9530](https://github.com/tiangolo/fastapi/pull/9530) by [@fhabers21](https://github.com/fhabers21).
|
||||
* 🌐 Update Turkish translation for `docs/tr/docs/index.md`. PR [#10444](https://github.com/tiangolo/fastapi/pull/10444) by [@hasansezertasan](https://github.com/hasansezertasan).
|
||||
* 🌐 Add Chinese translation for `docs/zh/docs/learn/index.md`. PR [#10479](https://github.com/tiangolo/fastapi/pull/10479) by [@KAZAMA-DREAM](https://github.com/KAZAMA-DREAM).
|
||||
* 🌐 Add Russian translation for `docs/ru/docs/learn/index.md`. PR [#10539](https://github.com/tiangolo/fastapi/pull/10539) by [@AlertRED](https://github.com/AlertRED).
|
||||
* 🌐 Update SQLAlchemy instruction in Chinese translation `docs/zh/docs/tutorial/sql-databases.md`. PR [#9712](https://github.com/tiangolo/fastapi/pull/9712) by [@Royc30ne](https://github.com/Royc30ne).
|
||||
* 🌐 Add Turkish translation for `docs/tr/docs/external-links.md`. PR [#10549](https://github.com/tiangolo/fastapi/pull/10549) by [@hasansezertasan](https://github.com/hasansezertasan).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/learn/index.md`. PR [#10885](https://github.com/tiangolo/fastapi/pull/10885) by [@pablocm83](https://github.com/pablocm83).
|
||||
* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/body-fields.md`. PR [#10670](https://github.com/tiangolo/fastapi/pull/10670) by [@ArtemKhymenko](https://github.com/ArtemKhymenko).
|
||||
* 🌐 Add Hungarian translation for `/docs/hu/docs/index.md`. PR [#10812](https://github.com/tiangolo/fastapi/pull/10812) by [@takacs](https://github.com/takacs).
|
||||
* 🌐 Add Turkish translation for `docs/tr/docs/newsletter.md`. PR [#10550](https://github.com/tiangolo/fastapi/pull/10550) by [@hasansezertasan](https://github.com/hasansezertasan).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/help/index.md`. PR [#10907](https://github.com/tiangolo/fastapi/pull/10907) by [@pablocm83](https://github.com/pablocm83).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/about/index.md`. PR [#10908](https://github.com/tiangolo/fastapi/pull/10908) by [@pablocm83](https://github.com/pablocm83).
|
||||
* 🌐 Add Spanish translation for `docs/es/docs/resources/index.md`. PR [#10909](https://github.com/tiangolo/fastapi/pull/10909) by [@pablocm83](https://github.com/pablocm83).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People. PR [#10871](https://github.com/tiangolo/fastapi/pull/10871) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Upgrade custom GitHub Action comment-docs-preview-in-pr. PR [#10916](https://github.com/tiangolo/fastapi/pull/10916) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade GitHub Action latest-changes. PR [#10915](https://github.com/tiangolo/fastapi/pull/10915) by [@tiangolo](https://github.com/tiangolo).
|
||||
* 👷 Upgrade GitHub Action label-approved. PR [#10913](https://github.com/tiangolo/fastapi/pull/10913) by [@tiangolo](https://github.com/tiangolo).
|
||||
* ⬆️ Upgrade GitHub Action label-approved. PR [#10905](https://github.com/tiangolo/fastapi/pull/10905) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.108.0
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette to `>=0.29.0,<0.33.0`, update docs and usage of templates with new Starlette arguments. PR [#10846](https://github.com/tiangolo/fastapi/pull/10846) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.107.0
|
||||
|
||||
### Upgrades
|
||||
|
||||
* ⬆️ Upgrade Starlette to 0.28.0. PR [#9636](https://github.com/tiangolo/fastapi/pull/9636) by [@adriangb](https://github.com/adriangb).
|
||||
|
||||
### Docs
|
||||
|
||||
* 📝 Add docs: Node.js script alternative to update OpenAPI for generated clients. PR [#10845](https://github.com/tiangolo/fastapi/pull/10845) by [@alejsdev](https://github.com/alejsdev).
|
||||
* 📝 Restructure Docs section in Contributing page. PR [#10844](https://github.com/tiangolo/fastapi/pull/10844) by [@alejsdev](https://github.com/alejsdev).
|
||||
|
||||
## 0.106.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
Using resources from dependencies with `yield` in background tasks is no longer supported.
|
||||
|
||||
This change is what supports the new features, read below. 🤓
|
||||
|
||||
### Dependencies with `yield`, `HTTPException` and Background Tasks
|
||||
|
||||
Dependencies with `yield` now can raise `HTTPException` and other exceptions after `yield`. 🎉
|
||||
|
||||
Read the new docs here: [Dependencies with `yield` and `HTTPException`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-httpexception).
|
||||
|
||||
```Python
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
data = {
|
||||
"plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
|
||||
"portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
|
||||
}
|
||||
|
||||
|
||||
class OwnerError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except OwnerError as e:
|
||||
raise HTTPException(status_code=400, detail=f"Owner error: {e}")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id not in data:
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
item = data[item_id]
|
||||
if item["owner"] != username:
|
||||
raise OwnerError(username)
|
||||
return item
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
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](https://fastapi.tiangolo.com/tutorial/handling-errors/#install-custom-exception-handlers) 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.
|
||||
|
||||
Nevertheless, as this would mean waiting for the response to travel through the network while unnecessarily holding a resource in a dependency with yield (for example a database connection), this was changed in FastAPI 0.106.0.
|
||||
|
||||
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
|
||||
|
||||
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`.
|
||||
|
||||
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.
|
||||
|
||||
The sequence of execution before FastAPI 0.106.0 was like this diagram:
|
||||
|
||||
Time flows from top to bottom. And each column is one of the parts interacting or executing code.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
participant client as Client
|
||||
participant handler as Exception handler
|
||||
participant dep as Dep with yield
|
||||
participant operation as Path Operation
|
||||
participant tasks as Background tasks
|
||||
|
||||
Note over client,tasks: Can raise exception for dependency, handled after response is sent
|
||||
Note over client,operation: Can raise HTTPException and can change the response
|
||||
client ->> dep: Start request
|
||||
Note over dep: Run code up to yield
|
||||
opt raise
|
||||
dep -->> handler: Raise HTTPException
|
||||
handler -->> client: HTTP error response
|
||||
dep -->> dep: Raise other exception
|
||||
end
|
||||
dep ->> operation: Run dependency, e.g. DB session
|
||||
opt raise
|
||||
operation -->> dep: Raise HTTPException
|
||||
dep -->> handler: Auto forward exception
|
||||
handler -->> client: HTTP error response
|
||||
operation -->> dep: Raise other exception
|
||||
dep -->> handler: Auto forward exception
|
||||
end
|
||||
operation ->> client: Return response to client
|
||||
Note over client,operation: Response is already sent, can't change it anymore
|
||||
opt Tasks
|
||||
operation -->> tasks: Send background tasks
|
||||
end
|
||||
opt Raise other exception
|
||||
tasks -->> dep: Raise other exception
|
||||
end
|
||||
Note over dep: After yield
|
||||
opt Handle other exception
|
||||
dep -->> dep: Handle exception, can't change response. E.g. close DB session.
|
||||
end
|
||||
```
|
||||
|
||||
The new execution flow can be found in the docs: [Execution of dependencies with `yield`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#execution-of-dependencies-with-yield).
|
||||
|
||||
### Features
|
||||
|
||||
* ✨ Add support for raising exceptions (including `HTTPException`) in dependencies with `yield` in the exit code, do not support them in background tasks. PR [#10831](https://github.com/tiangolo/fastapi/pull/10831) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
### Internal
|
||||
|
||||
* 👥 Update FastAPI People. PR [#10567](https://github.com/tiangolo/fastapi/pull/10567) by [@tiangolo](https://github.com/tiangolo).
|
||||
|
||||
## 0.105.0
|
||||
|
||||
### Features
|
||||
|
||||
@@ -59,9 +59,14 @@ This means that you can send only the data that you want to update, leaving the
|
||||
|
||||
### Using Pydantic's `exclude_unset` parameter
|
||||
|
||||
If you want to receive partial updates, it's very useful to use the parameter `exclude_unset` in Pydantic's model's `.dict()`.
|
||||
If you want to receive partial updates, it's very useful to use the parameter `exclude_unset` in Pydantic's model's `.model_dump()`.
|
||||
|
||||
Like `item.dict(exclude_unset=True)`.
|
||||
Like `item.model_dump(exclude_unset=True)`.
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
|
||||
|
||||
The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
|
||||
|
||||
That would generate a `dict` with only the data that was set when creating the `item` model, excluding default values.
|
||||
|
||||
@@ -87,9 +92,14 @@ Then you can use this to generate a `dict` with only the data that was set (sent
|
||||
|
||||
### Using Pydantic's `update` parameter
|
||||
|
||||
Now, you can create a copy of the existing model using `.copy()`, and pass the `update` parameter with a `dict` containing the data to update.
|
||||
Now, you can create a copy of the existing model using `.model_copy()`, and pass the `update` parameter with a `dict` containing the data to update.
|
||||
|
||||
Like `stored_item_model.copy(update=update_data)`:
|
||||
!!! info
|
||||
In Pydantic v1 the method was called `.copy()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_copy()`.
|
||||
|
||||
The examples here use `.copy()` for compatibility with Pydantic v1, but you should use `.model_copy()` instead if you can use Pydantic v2.
|
||||
|
||||
Like `stored_item_model.model_copy(update=update_data)`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
@@ -120,7 +130,7 @@ In summary, to apply partial updates you would:
|
||||
* This way you can update only the values actually set by the user, instead of overriding values already stored with default values in your model.
|
||||
* Create a copy of the stored model, updating it's attributes with the received partial updates (using the `update` parameter).
|
||||
* Convert the copied model to something that can be stored in your DB (for example, using the `jsonable_encoder`).
|
||||
* This is comparable to using the model's `.dict()` method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example, `datetime` to `str`.
|
||||
* This is comparable to using the model's `.model_dump()` method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example, `datetime` to `str`.
|
||||
* Save the data to your DB.
|
||||
* Return the updated model.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Dependencies with yield
|
||||
|
||||
FastAPI supports dependencies that do some <abbr title='sometimes also called "exit", "cleanup", "teardown", "close", "context managers", ...'>extra steps after finishing</abbr>.
|
||||
FastAPI supports dependencies that do some <abbr title='sometimes also called "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code", etc.'>extra steps after finishing</abbr>.
|
||||
|
||||
To do this, use `yield` instead of `return`, and write the extra steps after.
|
||||
To do this, use `yield` instead of `return`, and write the extra steps (code) after.
|
||||
|
||||
!!! tip
|
||||
Make sure to use `yield` one single time.
|
||||
@@ -21,7 +21,7 @@ To do this, use `yield` instead of `return`, and write the extra steps after.
|
||||
|
||||
For example, you could use this to create a database session and close it after finishing.
|
||||
|
||||
Only the code prior to and including the `yield` statement is executed before sending a response:
|
||||
Only the code prior to and including the `yield` statement is executed before creating a response:
|
||||
|
||||
```Python hl_lines="2-4"
|
||||
{!../../../docs_src/dependencies/tutorial007.py!}
|
||||
@@ -40,7 +40,7 @@ The code following the `yield` statement is executed after the response has been
|
||||
```
|
||||
|
||||
!!! tip
|
||||
You can use `async` or normal functions.
|
||||
You can use `async` or regular functions.
|
||||
|
||||
**FastAPI** will do the right thing with each, the same as with normal dependencies.
|
||||
|
||||
@@ -114,7 +114,7 @@ And, in turn, `dependency_b` needs the value from `dependency_a` (here named `de
|
||||
{!> ../../../docs_src/dependencies/tutorial008.py!}
|
||||
```
|
||||
|
||||
The same way, you could have dependencies with `yield` and `return` mixed.
|
||||
The same way, you could have some dependencies with `yield` and some other dependencies with `return`, and have some of those depend on some of the others.
|
||||
|
||||
And you could have a single dependency that requires several other dependencies with `yield`, etc.
|
||||
|
||||
@@ -131,24 +131,38 @@ You can have any combinations of dependencies that you want.
|
||||
|
||||
You saw that you can use dependencies with `yield` and have `try` blocks that catch exceptions.
|
||||
|
||||
It might be tempting to raise an `HTTPException` or similar in the exit code, after the `yield`. But **it won't work**.
|
||||
|
||||
The exit code in dependencies with `yield` is executed *after* the response is sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} will have already run. There's nothing catching exceptions thrown by your dependencies in the exit code (after the `yield`).
|
||||
|
||||
So, if you raise an `HTTPException` after the `yield`, the default (or any custom) exception handler that catches `HTTPException`s and returns an HTTP 400 response won't be there to catch that exception anymore.
|
||||
|
||||
This is what allows anything set in the dependency (e.g. a DB session) to, for example, be used by background tasks.
|
||||
|
||||
Background tasks are run *after* the response has been sent. So there's no way to raise an `HTTPException` because there's not even a way to change the response that is *already sent*.
|
||||
|
||||
But if a background task creates a DB error, at least you can rollback or cleanly close the session in the dependency with `yield`, and maybe log the error or report it to a remote tracking system.
|
||||
|
||||
If you have some code that you know could raise an exception, do the most normal/"Pythonic" thing and add a `try` block in that section of the code.
|
||||
|
||||
If you have custom exceptions that you would like to handle *before* returning the response and possibly modifying the response, maybe even raising an `HTTPException`, create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
|
||||
The same way, you could raise an `HTTPException` or similar in the exit code, after the `yield`.
|
||||
|
||||
!!! tip
|
||||
You can still raise exceptions including `HTTPException` *before* the `yield`. But not after.
|
||||
|
||||
This is a somewhat advanced technique, and in most of the cases you won't really need it, as you can raise exceptions (including `HTTPException`) from inside of the rest of your application code, for example, in the *path operation function*.
|
||||
|
||||
But it's there for you if you need it. 🤓
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="18-22 31"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
|
||||
```Python hl_lines="17-21 30"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Prefer to use the `Annotated` version if possible.
|
||||
|
||||
```Python hl_lines="16-20 29"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b.py!}
|
||||
```
|
||||
|
||||
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}.
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -161,34 +175,30 @@ participant dep as Dep with yield
|
||||
participant operation as Path Operation
|
||||
participant tasks as Background tasks
|
||||
|
||||
Note over client,tasks: Can raise exception for dependency, handled after response is sent
|
||||
Note over client,operation: Can raise HTTPException and can change the response
|
||||
Note over client,operation: Can raise exceptions, including HTTPException
|
||||
client ->> dep: Start request
|
||||
Note over dep: Run code up to yield
|
||||
opt raise
|
||||
dep -->> handler: Raise HTTPException
|
||||
opt raise Exception
|
||||
dep -->> handler: Raise Exception
|
||||
handler -->> client: HTTP error response
|
||||
dep -->> dep: Raise other exception
|
||||
end
|
||||
dep ->> operation: Run dependency, e.g. DB session
|
||||
opt raise
|
||||
operation -->> dep: Raise HTTPException
|
||||
dep -->> handler: Auto forward exception
|
||||
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
|
||||
operation -->> dep: Raise other exception
|
||||
dep -->> handler: Auto forward exception
|
||||
end
|
||||
|
||||
operation ->> client: Return response to client
|
||||
Note over client,operation: Response is already sent, can't change it anymore
|
||||
opt Tasks
|
||||
operation -->> tasks: Send background tasks
|
||||
end
|
||||
opt Raise other exception
|
||||
tasks -->> dep: Raise other exception
|
||||
end
|
||||
Note over dep: After yield
|
||||
opt Handle other exception
|
||||
dep -->> dep: Handle exception, can't change response. E.g. close DB session.
|
||||
tasks -->> tasks: Handle exceptions in the background task code
|
||||
end
|
||||
```
|
||||
|
||||
@@ -198,10 +208,33 @@ participant tasks as Background tasks
|
||||
After one of those responses is sent, no other response can be sent.
|
||||
|
||||
!!! tip
|
||||
This diagram shows `HTTPException`, but you could also raise any other exception for which you create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
|
||||
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.
|
||||
|
||||
## Dependencies with `yield`, `HTTPException` 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.
|
||||
|
||||
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.
|
||||
|
||||
Nevertheless, as this would mean waiting for the response to travel through the network while unnecessarily holding a resource in a dependency with yield (for example a database connection), this was changed in FastAPI 0.106.0.
|
||||
|
||||
!!! tip
|
||||
|
||||
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
|
||||
|
||||
So, this way you will probably have cleaner code.
|
||||
|
||||
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`.
|
||||
|
||||
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.
|
||||
|
||||
## Context Managers
|
||||
|
||||
### What are "Context Managers"
|
||||
@@ -216,11 +249,11 @@ with open("./somefile.txt") as f:
|
||||
print(contents)
|
||||
```
|
||||
|
||||
Underneath, the `open("./somefile.txt")` creates an object that is a called a "Context Manager".
|
||||
Underneath, the `open("./somefile.txt")` creates an object that is called a "Context Manager".
|
||||
|
||||
When the `with` block finishes, it makes sure to close the file, even if there were exceptions.
|
||||
|
||||
When you create a dependency with `yield`, **FastAPI** will internally convert it to a context manager, and combine it with some other related tools.
|
||||
When you create a dependency with `yield`, **FastAPI** will internally create a context manager for it, and combine it with some other related tools.
|
||||
|
||||
### Using context managers in dependencies with `yield`
|
||||
|
||||
|
||||
@@ -287,9 +287,9 @@ Other common terms for this same idea of "dependency injection" are:
|
||||
|
||||
## **FastAPI** plug-ins
|
||||
|
||||
Integrations and "plug-in"s can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your *path operation functions*.
|
||||
Integrations and "plug-ins" can be built using the **Dependency Injection** system. But in fact, there is actually **no need to create "plug-ins"**, as by using dependencies it's possible to declare an infinite number of integrations and interactions that become available to your *path operation functions*.
|
||||
|
||||
And dependencies can be created in a very simple and intuitive way that allow you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, *literally*.
|
||||
And dependencies can be created in a very simple and intuitive way that allows you to just import the Python packages you need, and integrate them with your API functions in a couple of lines of code, *literally*.
|
||||
|
||||
You will see examples of this in the next chapters, about relational and NoSQL databases, security, etc.
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ Here's a general idea of how the models could look like with their password fiel
|
||||
{!> ../../../docs_src/extra_models/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
|
||||
|
||||
The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
|
||||
|
||||
### About `**user_in.dict()`
|
||||
|
||||
#### Pydantic's `.dict()`
|
||||
|
||||
@@ -377,6 +377,11 @@ So, if you send a request to that *path operation* for the item with ID `foo`, t
|
||||
}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
|
||||
|
||||
The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
|
||||
|
||||
!!! info
|
||||
FastAPI uses Pydantic model's `.dict()` with <a href="https://pydantic-docs.helpmanual.io/usage/exporting_models/#modeldict" class="external-link" target="_blank">its `exclude_unset` parameter</a> to achieve this.
|
||||
|
||||
|
||||
@@ -451,6 +451,11 @@ The steps are:
|
||||
{!../../../docs_src/sql_databases/sql_app/crud.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 the method was called `.dict()`, it was deprecated (but still supported) in Pydantic v2, and renamed to `.model_dump()`.
|
||||
|
||||
The examples here use `.dict()` for compatibility with Pydantic v1, but you should use `.model_dump()` instead if you can use Pydantic v2.
|
||||
|
||||
!!! tip
|
||||
The SQLAlchemy model for `User` contains a `hashed_password` that should contain a secure hashed version of the password.
|
||||
|
||||
@@ -624,7 +629,7 @@ def read_user(user_id: int, db: Session = Depends(get_db)):
|
||||
```
|
||||
|
||||
!!! info
|
||||
If you need to connect to your relational database asynchronously, see [Async SQL (Relational) Databases](../advanced/async-sql-databases.md){.internal-link target=_blank}.
|
||||
If you need to connect to your relational database asynchronously, see [Async SQL (Relational) Databases](../how-to/async-sql-encode-databases.md){.internal-link target=_blank}.
|
||||
|
||||
!!! note "Very Technical Details"
|
||||
If you are curious and have a deep technical knowledge, you can check the very technical details of how this `async def` vs `def` is handled in the [Async](../async.md#very-technical-details){.internal-link target=_blank} docs.
|
||||
|
||||
@@ -58,15 +58,18 @@ plugins:
|
||||
python:
|
||||
options:
|
||||
extensions:
|
||||
- griffe_typingdoc
|
||||
- griffe_typingdoc
|
||||
show_root_heading: true
|
||||
show_if_no_docstring: true
|
||||
preload_modules: [httpx, starlette]
|
||||
preload_modules:
|
||||
- httpx
|
||||
- starlette
|
||||
inherited_members: true
|
||||
members_order: source
|
||||
separate_signature: true
|
||||
unwrap_annotated: true
|
||||
filters: ["!^_"]
|
||||
filters:
|
||||
- '!^_'
|
||||
merge_init_into_class: true
|
||||
docstring_section_style: spacy
|
||||
signature_crossrefs: true
|
||||
@@ -264,25 +267,25 @@ extra:
|
||||
- link: /
|
||||
name: en - English
|
||||
- link: /de/
|
||||
name: de
|
||||
- link: /em/
|
||||
name: 😉
|
||||
name: de - Deutsch
|
||||
- link: /es/
|
||||
name: es - español
|
||||
- link: /fa/
|
||||
name: fa
|
||||
name: fa - فارسی
|
||||
- link: /fr/
|
||||
name: fr - français
|
||||
- link: /he/
|
||||
name: he
|
||||
name: he - עברית
|
||||
- link: /hu/
|
||||
name: hu - magyar
|
||||
- link: /id/
|
||||
name: id
|
||||
name: id - Bahasa Indonesia
|
||||
- link: /ja/
|
||||
name: ja - 日本語
|
||||
- link: /ko/
|
||||
name: ko - 한국어
|
||||
- link: /pl/
|
||||
name: pl
|
||||
name: pl - Polski
|
||||
- link: /pt/
|
||||
name: pt - português
|
||||
- link: /ru/
|
||||
@@ -290,15 +293,17 @@ extra:
|
||||
- link: /tr/
|
||||
name: tr - Türkçe
|
||||
- link: /uk/
|
||||
name: uk
|
||||
name: uk - українська мова
|
||||
- link: /ur/
|
||||
name: ur
|
||||
name: ur - اردو
|
||||
- link: /vi/
|
||||
name: vi - Tiếng Việt
|
||||
- link: /yo/
|
||||
name: yo - Yorùbá
|
||||
- link: /zh/
|
||||
name: zh - 汉语
|
||||
- link: /em/
|
||||
name: 😉
|
||||
extra_css:
|
||||
- css/termynal.css
|
||||
- css/custom.css
|
||||
|
||||
3
docs/es/docs/about/index.md
Normal file
3
docs/es/docs/about/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Acerca de
|
||||
|
||||
Acerca de FastAPI, su diseño, inspiración y más. 🤓
|
||||
3
docs/es/docs/help/index.md
Normal file
3
docs/es/docs/help/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Ayuda
|
||||
|
||||
Ayuda y recibe ayuda, contribuye, involúcrate. 🤝
|
||||
5
docs/es/docs/learn/index.md
Normal file
5
docs/es/docs/learn/index.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Aprender
|
||||
|
||||
Aquí están las secciones introductorias y los tutoriales para aprender **FastAPI**.
|
||||
|
||||
Podrías considerar esto como un **libro**, un **curso**, la forma **oficial** y recomendada de aprender FastAPI. 😎
|
||||
3
docs/es/docs/resources/index.md
Normal file
3
docs/es/docs/resources/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Recursos
|
||||
|
||||
Recursos adicionales, enlaces externos, artículos y más. ✈️
|
||||
206
docs/fa/docs/features.md
Normal file
206
docs/fa/docs/features.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# ویژگی ها
|
||||
|
||||
## ویژگی های FastAPI
|
||||
|
||||
**FastAPI** موارد زیر را به شما ارائه میدهد:
|
||||
|
||||
### برپایه استاندارد های باز
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> برای ساخت API, شامل مشخص سازی <abbr title="که علاوه بر path, به عنوان endpoint و route نیز شناخته میشود">path</abbr> <abbr title="که به عنوان متودهای HTTP یعنی POST,GET,PUT,DELETE و ... شناخته میشوند">operation</abbr> ها, <abbr title="parameters">پارامترها</abbr>, body request ها, امنیت و غیره.
|
||||
* مستندسازی خودکار data model با <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (همانطور که OpenAPI خود نیز مبتنی بر JSON Schema است).
|
||||
* طراحی شده بر اساس استاندارد هایی که پس از یک مطالعه دقیق بدست آمده اند بجای طرحی ناپخته و بدون فکر.
|
||||
* همچنین به شما اجازه میدهد تا از تولید خودکار client code در بسیاری از زبان ها استفاده کنید.
|
||||
|
||||
### مستندات خودکار
|
||||
|
||||
مستندات API تعاملی و ایجاد رابط کاربری وب. از آنجایی که این فریم ورک برپایه OpenAPI میباشد، آپشن های متعددی وجود دارد که ۲ مورد بصورت پیش فرض گنجانده شده اند.
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>، با <abbr title="interactive exploration">کاوش تعاملی</abbr>، API خود را مستقیما از طریق مرورگر صدازده و تست کنید.
|
||||
|
||||

|
||||
|
||||
* مستندات API جایگزین با <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
|
||||
|
||||

|
||||
|
||||
### فقط پایتون مدرن
|
||||
|
||||
همه اینها برپایه type declaration های **پایتون ۳.۶** استاندارد (به لطف Pydantic) میباشند. سینتکس جدیدی درکار نیست. تنها پایتون مدرن استاندارد.
|
||||
|
||||
اگر به یک یادآوری ۲ دقیقه ای در مورد نحوه استفاده از تایپ های پایتون دارید (حتی اگر از FastAPI استفاده نمیکنید) این آموزش کوتاه را بررسی کنید: [Python Types](python-types.md){.internal-link target=\_blank}.
|
||||
|
||||
شما پایتون استاندارد را با استفاده از تایپ ها مینویسید:
|
||||
|
||||
```Python
|
||||
from datetime import date
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
# Declare a variable as a str
|
||||
# and get editor support inside the function
|
||||
def main(user_id: str):
|
||||
return user_id
|
||||
|
||||
|
||||
# A Pydantic model
|
||||
class User(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
joined: date
|
||||
```
|
||||
|
||||
که سپس میتوان به این شکل از آن استفاده کرد:
|
||||
|
||||
```Python
|
||||
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
|
||||
|
||||
second_user_data = {
|
||||
"id": 4,
|
||||
"name": "Mary",
|
||||
"joined": "2018-11-30",
|
||||
}
|
||||
|
||||
my_second_user: User = User(**second_user_data)
|
||||
```
|
||||
|
||||
!!! info
|
||||
`**second_user_data` یعنی:
|
||||
|
||||
کلید ها و مقادیر دیکشنری `second_user_data` را مستقیما به عنوان ارگومان های key-value بفرست، که معادل است با : `User(id=4, name="Mary", joined="2018-11-30")`
|
||||
|
||||
### پشتیبانی ویرایشگر
|
||||
|
||||
تمام فریم ورک به گونه ای طراحی شده که استفاده از آن آسان و شهودی باشد، تمام تصمیمات حتی قبل از شروع توسعه بر روی چندین ویرایشگر آزمایش شده اند، تا از بهترین تجربه توسعه اطمینان حاصل شود.
|
||||
|
||||
در آخرین نظرسنجی توسعه دهندگان پایتون کاملا مشخص بود که <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">بیشترین ویژگی مورد استفاده از "<abbr title="autocompletion">تکمیل خودکار</abbr>" است</a>.
|
||||
|
||||
تمام فریم ورک **FastAPI** برپایه ای برای براورده کردن این نیاز نیز ایجاد گشته است. تکمیل خودکار در همه جا کار میکند.
|
||||
|
||||
شما به ندرت نیاز به بازگشت به مستندات را خواهید داشت.
|
||||
|
||||
ببینید که چگونه ویرایشگر شما ممکن است به شما کمک کند:
|
||||
|
||||
* در <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
|
||||
|
||||

|
||||
|
||||
* در <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
|
||||
|
||||

|
||||
|
||||
شما پیشنهاد های تکمیل خودکاری را خواهید گرفت که حتی ممکن است قبلا آن را غیرممکن تصور میکردید. به عنوان مثال کلید `price` در داخل بدنه JSON (که میتوانست تودرتو نیز باشد) که از یک درخواست آمده است.
|
||||
|
||||
دیگر خبری از تایپ کلید اشتباهی، برگشتن به مستندات یا پایین بالا رفتن برای فهمیدن اینکه شما از `username` یا `user_name` استفاده کرده اید نیست.
|
||||
|
||||
### مختصر
|
||||
|
||||
FastAPI **پیش فرض** های معقولی برای همه چیز دارد، با قابلیت تنظیمات اختیاری در همه جا. تمام پارامترها را میتوانید برای انجام انچه نیاز دارید و برای تعریف API مورد نیاز خود به خوبی تنظیم کنید.
|
||||
|
||||
اما به طور پیش فرض، همه چیز **کار میکند**.
|
||||
|
||||
### اعتبارسنجی
|
||||
|
||||
* اعتبارسنجی برای بیشتر (یا همه؟) **data type** های پایتون، شامل:
|
||||
|
||||
* JSON objects (`dict`)
|
||||
* آرایه های (`list`) JSON با قابلیت مشخص سازی تایپ ایتم های درون لیست.
|
||||
* فیلد های رشته (`str`)، به همراه مشخص سازی حداقل و حداکثر طول رشته.
|
||||
* اعداد (`int`,`float`) با حداقل و حداکثر مقدار و غیره.
|
||||
|
||||
* اعتبارسنجی برای تایپ های عجیب تر، مثل:
|
||||
* URL.
|
||||
* Email.
|
||||
* UUID.
|
||||
* و غیره.
|
||||
|
||||
تمام اعتبارسنجی ها توسط کتابخانه اثبات شده و قدرتمند **Pydantic** انجام میشود.
|
||||
|
||||
### <abbr title="Security and authentication">امنیت و احراز هویت</abbr>
|
||||
|
||||
امنیت و احرازهویت بدون هیچگونه ارتباط و مصالحه ای با پایگاه های داده یا مدل های داده ایجاد شده اند.
|
||||
|
||||
تمام طرح های امنیتی در OpenAPI تعریف شده اند، از جمله:
|
||||
|
||||
* .
|
||||
* **OAuth2** (همچنین با **JWT tokens**). آموزش را در [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=\_blank} مشاهده کنید.
|
||||
* کلید های API:
|
||||
* <abbr title="سرصفحه ها">Headers</abbr>
|
||||
* <abbr title="پارامترهای پرسمان">Query parameters</abbr>
|
||||
* <abbr title="کوکی ها">Cookies</abbr>، و غیره.
|
||||
|
||||
به علاوه تمام ویژگی های امنیتی از **Statlette** (شامل **<abbr title="کوکی های جلسه">session cookies</abbr>**)
|
||||
|
||||
همه اینها به عنوان ابزارها و اجزای قابل استفاده ای ساخته شده اند که به راحتی با سیستم های شما، مخازن داده، پایگاه های داده رابطه ای و NoSQL و غیره ادغام میشوند.
|
||||
|
||||
### <abbr title="تزریق وابستگی">Dependency Injection</abbr>
|
||||
|
||||
FastAPI شامل یک سیستم <abbr title='همچنین به عنوان "components", "resources", "services" و "providers" شناخته میشود'><strong>Dependency Injection</strong></abbr> بسیار آسان اما بسیار قدرتمند است.
|
||||
|
||||
* حتی وابستگی ها نیز میتوانند وابستگی هایی داشته باشند و یک سلسله مراتب یا **"گرافی" از وابستگی ها** ایجاد کنند.
|
||||
|
||||
* همه چیز توسط فریم ورک **به طور خودکار اداره میشود**
|
||||
|
||||
* همه وابستگی ها میتوانند به داده های request ها نیاز داشته باشند و مستندات خودکار و محدودیت های <abbr title="عملیات مسیر">path operation</abbr> را **افزایش** دهند.
|
||||
|
||||
* با قابلیت **اعتبارسنجی خودکار** حتی برای path operation parameter های تعریف شده در وابستگی ها.
|
||||
|
||||
* پشتیبانی از سیستم های پیچیده احرازهویت کاربر، **اتصالات پایگاه داده** و غیره.
|
||||
|
||||
* بدون هیچ ارتباطی با دیتابیس ها، فرانت اند و غیره. اما ادغام آسان و راحت با همه آنها.
|
||||
|
||||
### پلاگین های نامحدود
|
||||
|
||||
یا به عبارت دیگر، هیچ نیازی به آنها نیست، کد موردنیاز خود را وارد و استفاده کنید.
|
||||
|
||||
هر یکپارچه سازی به گونه ای طراحی شده است که استفاده از آن بسیار ساده باشد (با وابستگی ها) که میتوانید با استفاده از همان ساختار و روشی که برای _path operation_ های خود استفاده کرده اید تنها در ۲ خط کد "پلاگین" برنامه خودتان را ایجاد کنید.
|
||||
|
||||
### تست شده
|
||||
|
||||
* 100% <abbr title="مقدار کدی که به طور خودکار تست شده است">پوشش تست</abbr>.
|
||||
|
||||
* 100% کد بر اساس <abbr title="حاشیه نویسی تایپ های پایتون (Python type annotations)، با استفاده از آن ویرایشگر و ابزارهای خارجی شما می توانند پشتیبانی بهتری از شما ارائه دهند">type annotate ها</abbr>.
|
||||
|
||||
* استفاده شده در اپلیکیشن های تولید
|
||||
|
||||
## ویژگی های Starlette
|
||||
|
||||
**FastAPI** کاملا (و براساس) با <a href="https://www.starlette.io/" class="external-link" target="_blank"><strong>Starlette</strong></a> سازگار است. بنابراین، هرکد اضافی Starlette که دارید، نیز کار خواهد کرد.
|
||||
|
||||
`FastAPI` در واقع یک زیرکلاس از `Starlette` است. بنابراین اگر از قبل Starlette را میشناسید یا با آن کار کرده اید، بیشتر قابلیت ها به همین روش کار خواهد کرد.
|
||||
|
||||
با **FastAPI** شما تمام ویژگی های **Starlette** را خواهید داشت (زیرا FastAPI یک نسخه و نمونه به تمام معنا از Starlette است):
|
||||
|
||||
* عملکرد به طورجدی چشمگیر. <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">این یکی از سریعترین فریم ورک های موجود در پایتون است که همتراز با **نود جی اس** و **گو**</a> است.
|
||||
* پشتیبانی از **WebSocket**.
|
||||
* <abbr title="In-process background tasks">تسک های درجریان در پس زمینه</abbr>.
|
||||
* <abbr title="Startup and shutdown events">رویداد های راه اندازی و متوفق شدن<abbr>.
|
||||
* تست کلاینت ساخته شده به روی HTTPX.
|
||||
* **CORS**, GZip, فایل های استاتیک, <abbr title="Streaming responses">پاسخ های جریانی</abbr>.
|
||||
* پشتیبانی از **نشست ها و کوکی ها**.
|
||||
* 100% پوشش با تست.
|
||||
* 100% کد براساس type annotate ها.
|
||||
|
||||
## ویژگی های Pydantic
|
||||
|
||||
**FastAPI** کاملا (و براساس) با <a href="https://pydantic-docs.helpmanual.io" class="external-link" target="_blank"><strong>Pydantic</strong></a> سازگار است. بنابراین هرکد Pydantic اضافی که داشته باشید، نیز کار خواهد کرد.
|
||||
|
||||
از جمله کتابخانه های خارجی نیز مبتنی بر Pydantic میتوان به <abbr title="Object-Relational Mapper">ORM</abbr> و <abbr title="Object-Document Mapper">ODM</abbr> ها برای دیتابیس ها اشاره کرد.
|
||||
|
||||
این همچنین به این معناست که در خیلی از موارد میتوانید همان ابجکتی که از request میگیرید را **مستقیما به دیتابیس** بفرستید زیرا همه چیز به طور خودکار تأیید میشود.
|
||||
|
||||
همین امر برعکس نیز صدق میکند، در بسیاری از موارد شما میتوانید ابجکتی را که از پایگاه داده دریافت میکنید را **مستقیماً به کاربر** ارسال کنید.
|
||||
|
||||
با FastAPI شما تمام ویژگی های Pydantic را دراختیار دارید (زیرا FastAPI برای تمام بخش مدیریت دیتا بر اساس Pydantic عمل میکند):
|
||||
|
||||
* **خبری از گیج شدن نیست**:
|
||||
* هیچ <abbr title="micro-language">زبان خردی</abbr> برای یادگیری تعریف طرحواره های جدید وجود ندارد.
|
||||
* اگر تایپ های پایتون را میشناسید، نحوه استفاده از Pydantic را نیز میدانید.
|
||||
* به خوبی با **<abbr title="همان Integrated Development Environment, شبیه به ویرایشگر کد">IDE</abbr>/<abbr title="برنامه ای که خطاهای کد را بررسی می کند">linter</abbr>/مغز** شما عمل میکند:
|
||||
* به این دلیل که ساختار داده Pydantic فقط نمونه هایی از کلاس هایی هستند که شما تعریف میکنید، تکمیل خودکار، mypy، linting و مشاهده شما باید به درستی با داده های معتبر شما کار کنند.
|
||||
* اعتبار سنجی **ساختارهای پیچیده**:
|
||||
* استفاده از مدل های سلسله مراتبی Pydantic, `List` و `Dict` کتابخانه `typing` پایتون و غیره.
|
||||
* و اعتبارسنج ها اجازه میدهند که طرحواره های داده پیچیده به طور واضح و آسان تعریف، بررسی و بر پایه JSON مستند شوند.
|
||||
* شما میتوانید ابجکت های عمیقا تودرتو JSON را که همگی تایید شده و annotated شده اند را داشته باشید.
|
||||
* **قابل توسعه**:
|
||||
* Pydantic اجازه میدهد تا data type های سفارشی تعریف شوند یا میتوانید اعتبارسنجی را با روش هایی به روی مدل ها با <abbr title="دکوریتور های اعتبارسنج">validator decorator</abbr> گسترش دهید.
|
||||
* 100% پوشش با تست.
|
||||
469
docs/hu/docs/index.md
Normal file
469
docs/hu/docs/index.md
Normal file
@@ -0,0 +1,469 @@
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI keretrendszer, nagy teljesítmény, könnyen tanulható, gyorsan kódolható, productionre kész</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Dokumentáció**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Forrás kód**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
A FastAPI egy modern, gyors (nagy teljesítményű), webes keretrendszer API-ok építéséhez Python 3.8+-al, a Python szabványos típusjelöléseire építve.
|
||||
|
||||
|
||||
Kulcs funkciók:
|
||||
|
||||
* **Gyors**: Nagyon nagy teljesítmény, a **NodeJS**-el és a **Go**-val egyenrangú (a Starlettenek és a Pydantic-nek köszönhetően). [Az egyik leggyorsabb Python keretrendszer](#performance).
|
||||
* **Gyorsan kódolható**: A funkciók fejlesztési sebességét 200-300 százalékkal megnöveli. *
|
||||
* **Kevesebb hiba**: Körülbelül 40%-al csökkenti az emberi (fejlesztői) hibák számát. *
|
||||
* **Intuitív**: Kiváló szerkesztő támogatás. <abbr title="más néven auto-complete, autocompletion, IntelliSense">Kiegészítés</abbr> mindenhol. Kevesebb hibakereséssel töltött idő.
|
||||
* **Egyszerű**: Egyszerű tanulásra és használatra tervezve. Kevesebb dokumentáció olvasással töltött idő.
|
||||
* **Rövid**: Kód duplikáció minimalizálása. Több funkció minden paraméter deklarálásával. Kevesebb hiba.
|
||||
* **Robosztus**: Production ready kód. Automatikus interaktív dokumentáció val.
|
||||
* **Szabvány alapú**: Az API-ok nyílt szabványaira alapuló (és azokkal teljesen kompatibilis): <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (korábban Swagger néven ismert) és a <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* Egy production alkalmazásokat építő belső fejlesztői csapat tesztjein alapuló becslés. </small>
|
||||
|
||||
## Szponzorok
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">További szponzorok</a>
|
||||
|
||||
## Vélemények
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_If anyone is looking to build a production Python API, I would highly recommend **FastAPI**. It is **beautifully designed**, **simple to use** and **highly scalable**, it has become a **key component** in our API first development strategy and is driving many automations and services such as our Virtual TAC Engineer._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, a CLI-ok FastAPI-ja
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
Ha egy olyan CLI alkalmazást fejlesztesz amit a parancssorban kell használni webes API helyett, tekintsd meg: <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** a FastAPI kistestvére. A **CLI-k FastAPI-ja**. ⌨️ 🚀
|
||||
|
||||
## Követelmények
|
||||
|
||||
Python 3.8+
|
||||
|
||||
A FastAPI óriások vállán áll:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> a webes részekhez.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> az adat részekhez.
|
||||
|
||||
## Telepítés
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
A production-höz egy ASGI szerverre is szükség lesz, mint például az <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> vagy a <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Példa
|
||||
|
||||
### Hozd létre
|
||||
|
||||
* Hozz létre a `main.py` fájlt a következő tartalommal:
|
||||
|
||||
```Python
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Vagy használd az <code>async def</code>-et...</summary>
|
||||
|
||||
Ha a kódod `async` / `await`-et, használ `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Megjegyzés**:
|
||||
|
||||
Ha nem tudod, tekintsd meg a _"Sietsz?"_ szekciót <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` és `await`-ről dokumentációba</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Futtasd le
|
||||
|
||||
Indítsd el a szervert a következő paranccsal:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>A parancsról <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
A `uvicorn main:app` parancs a következőre utal:
|
||||
|
||||
* `main`: fájl `main.py` (a Python "modul").
|
||||
* `app`: a `main.py`-ban a `app = FastAPI()` sorral létrehozott objektum.
|
||||
* `--reload`: kód változtatás esetén újra indítja a szervert. Csak fejlesztés közben használandó.
|
||||
|
||||
</details>
|
||||
|
||||
### Ellenőrizd
|
||||
|
||||
Nyisd meg a böngésződ a következő címen: <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
A következő JSON választ fogod látni:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
Máris létrehoztál egy API-t ami:
|
||||
|
||||
* HTTP kéréseket fogad a `/` és `/items/{item_id}` _útvonalakon_.
|
||||
* Mindkét _útvonal_ a `GET` <em>műveletet</em> használja (másik elnevezés: HTTP _metódus_).
|
||||
* A `/items/{item_id}` _útvonalnak_ van egy _path paramétere_, az `item_id`, aminek `int` típusúnak kell lennie.
|
||||
* A `/items/{item_id}` _útvonalnak_ még van egy opcionális, `str` típusú _query paramétere_ is, a `q`.
|
||||
|
||||
### Interaktív API dokumentáció
|
||||
|
||||
Most nyisd meg a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> címet.
|
||||
|
||||
Az automatikus interaktív API dokumentációt fogod látni (amit a <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>-al hozunk létre):
|
||||
|
||||

|
||||
|
||||
### Alternatív API dokumentáció
|
||||
|
||||
És most menj el a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> címre.
|
||||
|
||||
Az alternatív automatikus dokumentációt fogod látni. (lásd <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Példa frissítése
|
||||
|
||||
Módosítsuk a `main.py` fájlt, hogy `PUT` kérések esetén tudjon body-t fogadni.
|
||||
|
||||
Deklaráld a body-t standard Python típusokkal, a Pydantic-nak köszönhetően.
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Union[bool, None] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
A szerver automatikusan újraindul (mert hozzáadtuk a --reload paramétert a fenti `uvicorn` parancshoz).
|
||||
|
||||
### Interaktív API dokumentáció frissítése
|
||||
|
||||
Most menj el a <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> címre.
|
||||
|
||||
* Az interaktív API dokumentáció automatikusan frissült így már benne van az új body.
|
||||
|
||||

|
||||
|
||||
* Kattints rá a "Try it out" gombra, ennek segítségével kitöltheted a paramétereket és közvetlen használhatod az API-t:
|
||||
|
||||

|
||||
|
||||
* Ezután kattints az "Execute" gompra, a felhasználói felület kommunikálni fog az API-oddal. Elküldi a paramétereket és a visszakapott választ megmutatja a képernyődön.
|
||||
|
||||

|
||||
|
||||
### Alternatív API dokumentáció frissítés
|
||||
|
||||
Most menj el a <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> címre.
|
||||
|
||||
* Az alternatív dokumentáció szintúgy tükrözni fogja az új kérési paraméter és body-t.
|
||||
|
||||

|
||||
|
||||
### Összefoglalás
|
||||
|
||||
Összegzésül, deklarálod **egyszer** a paraméterek, body, stb típusát funkciós paraméterekként.
|
||||
|
||||
Ezt standard modern Python típusokkal csinálod.
|
||||
|
||||
Nem kell új szintaxist, vagy specifikus könyvtár mert metódósait, stb. megtanulnod.
|
||||
|
||||
Csak standard **Python 3.8+**.
|
||||
|
||||
Például egy `int`-nek:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
Egy komplexebb `Item` modellnek:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
... És csupán egy deklarációval megkapod a:
|
||||
|
||||
* Szerkesztő támogatást, beleértve:
|
||||
* Szövegkiegészítés.
|
||||
* Típus ellenőrzés.
|
||||
* Adatok validációja:
|
||||
* Automatikus és érthető hibák amikor az adatok hibásak.
|
||||
* Validáció mélyen ágyazott objektumok esetén is.
|
||||
* Bemeneti adatok<abbr title="also known as: serialization, parsing, marshalling"> átváltása</abbr> : a hálózatról érkező Python adatokká és típusokká. Adatok olvasása következő forrásokból:
|
||||
* JSON.
|
||||
* Cím paraméterek.
|
||||
* Query paraméterek.
|
||||
* Cookie-k.
|
||||
* Header-ök.
|
||||
* Formok.
|
||||
* Fájlok.
|
||||
* Kimeneti adatok <abbr title=" más néven: serialization, parsing, marshalling">átváltása</abbr>: Python adatok is típusokról hálózati adatokká:
|
||||
* válts át Python típusokat (`str`, `int`, `float`, `bool`, `list`, etc).
|
||||
* `datetime` csak objektumokat.
|
||||
* `UUID` objektumokat.
|
||||
* Adatbázis modelleket.
|
||||
* ...És sok mást.
|
||||
* Automatikus interaktív dokumentáció, beleértve két alternatív dokumentációt is:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Visszatérve az előző kód példához. A **FastAPI**:
|
||||
|
||||
* Validálja hogy van egy `item_id` mező a `GET` és `PUT` kérésekben.
|
||||
* Validálja hogy az `item_id` `int` típusú a `GET` és `PUT` kérésekben.
|
||||
* Ha nem akkor látni fogunk egy tiszta hibát ezzel kapcsolatban.
|
||||
* ellenőrzi hogyha van egy opcionális query paraméter `q` névvel (azaz `http://127.0.0.1:8000/items/foo?q=somequery`) `GET` kérések esetén.
|
||||
* Mivel a `q` paraméter `= None`-al van deklarálva, ezért opcionális.
|
||||
* `None` nélkül ez a mező kötelező lenne (mint például a body `PUT` kérések esetén).
|
||||
* a `/items/{item_id}` címre érkező `PUT` kérések esetén, a JSON-t a következőképpen olvassa be:
|
||||
* Ellenőrzi hogy létezik a kötelező `name` nevű attribútum és `string`.
|
||||
* Ellenőrzi hogy létezik a kötelező `price` nevű attribútum és `float`.
|
||||
* Ellenőrzi hogy létezik a `is_offer` nevű opcionális paraméter, ami ha létezik akkor `bool`
|
||||
* Ez ágyazott JSON objektumokkal is működik
|
||||
* JSONről való automatikus konvertálás.
|
||||
* dokumentáljuk mindent OpenAPI-al amit használható:
|
||||
* Interaktív dokumentációs rendszerekkel.
|
||||
* Automatikus kliens kód generáló a rendszerekkel, több nyelven.
|
||||
* Hozzá tartozik kettő interaktív dokumentációs web felület.
|
||||
|
||||
---
|
||||
|
||||
Eddig csak a felszínt kapargattuk, de a lényeg hogy most már könnyebben érthető hogyan működik.
|
||||
|
||||
Próbáld kicserélni a következő sorban:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...ezt:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...erre:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
... És figyeld meg hogy a szerkesztő automatikusan tudni fogja a típusokat és kiegészíti azokat:
|
||||
|
||||

|
||||
|
||||
Teljesebb példákért és funkciókért tekintsd meg a <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a> -t.
|
||||
|
||||
**Spoiler veszély**: a Tutorial - User Guidehoz tartozik:
|
||||
|
||||
* **Paraméterek** deklarációja különböző helyekről: **header-ök**, **cookie-k**, **form mezők** és **fájlok**.
|
||||
* Hogyan állíts be **validációs feltételeket** mint a `maximum_length` vagy a `regex`.
|
||||
* Nagyon hatékony és erős **<abbr title="also known as components, resources, providers, services, injectables">Függőség Injekció</abbr>** rendszerek.
|
||||
* Biztonság és autentikáció beleértve, **OAuth2**, **JWT tokens** és **HTTP Basic** támogatást.
|
||||
* Több haladó (de ugyanannyira könnyű) technika **mélyen ágyazott JSON modellek deklarációjára** (Pydantic-nek köszönhetően).
|
||||
* **GraphQL** integráció <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a>-vel és más könyvtárakkal.
|
||||
* több extra funkció (Starlette-nek köszönhetően) pl.:
|
||||
* **WebSockets**
|
||||
* rendkívül könnyű tesztek HTTPX és `pytest` alapokra építve
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...és több.
|
||||
|
||||
## Teljesítmény
|
||||
|
||||
A független TechEmpower benchmarkok szerint az Uvicorn alatt futó **FastAPI** alkalmazások az <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">egyik leggyorsabb Python keretrendszerek közé tartoznak</a>, éppen lemaradva a Starlette és az Uvicorn (melyeket a FastAPI belsőleg használ) mögött.(*)
|
||||
|
||||
Ezeknek a további megértéséhez: <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Opcionális követelmények
|
||||
|
||||
Pydantic által használt:
|
||||
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - e-mail validációkra.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - Beállítások követésére.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - Extra típusok Pydantic-hoz.
|
||||
|
||||
Starlette által használt:
|
||||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Követelmény ha a `TestClient`-et akarod használni.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Követelmény ha az alap template konfigurációt akarod használni.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Követelmény ha <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>-ot akarsz támogatni, `request.form()`-al.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Követelmény `SessionMiddleware` támogatáshoz.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Követelmény a Starlette `SchemaGenerator`-ának támogatásához (valószínűleg erre nincs szükség FastAPI használása esetén).
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Követelmény ha `UJSONResponse`-t akarsz használni.
|
||||
|
||||
FastAPI / Starlette által használt
|
||||
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - Szerverekhez amíg betöltik és szolgáltatják az applikációdat.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Követelmény ha `ORJSONResponse`-t akarsz használni.
|
||||
|
||||
Ezeket mind telepítheted a `pip install "fastapi[all]"` paranccsal.
|
||||
|
||||
## Licensz
|
||||
Ez a projekt az MIT license, licensz alatt fut
|
||||
1
docs/hu/mkdocs.yml
Normal file
1
docs/hu/mkdocs.yml
Normal file
@@ -0,0 +1 @@
|
||||
INHERIT: ../en/mkdocs.yml
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
---
|
||||
|
||||
FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.6 以降でAPI を構築するための、モダンで、高速(高パフォーマンス)な、Web フレームワークです。
|
||||
FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.8 以降でAPI を構築するための、モダンで、高速(高パフォーマンス)な、Web フレームワークです。
|
||||
|
||||
主な特徴:
|
||||
|
||||
@@ -317,7 +317,7 @@ def update_item(item_id: int, item: Item):
|
||||
|
||||
新しい構文や特定のライブラリのメソッドやクラスなどを覚える必要はありません。
|
||||
|
||||
単なる標準的な**3.6 以降の Python**です。
|
||||
単なる標準的な**3.8 以降の Python**です。
|
||||
|
||||
例えば、`int`の場合:
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
---
|
||||
|
||||
FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트에 기초한 Python3.6+의 API를 빌드하기 위한 웹 프레임워크입니다.
|
||||
FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트에 기초한 Python3.8+의 API를 빌드하기 위한 웹 프레임워크입니다.
|
||||
|
||||
주요 특징으로:
|
||||
|
||||
@@ -323,7 +323,7 @@ def update_item(item_id: int, item: Item):
|
||||
|
||||
새로운 문법, 특정 라이브러리의 메소드나 클래스 등을 배울 필요가 없습니다.
|
||||
|
||||
그저 표준 **Python 3.6+**입니다.
|
||||
그저 표준 **Python 3.8+** 입니다.
|
||||
|
||||
예를 들어, `int`에 대해선:
|
||||
|
||||
|
||||
182
docs/language_names.yml
Normal file
182
docs/language_names.yml
Normal file
@@ -0,0 +1,182 @@
|
||||
aa: Afaraf
|
||||
ab: аҧсуа бызшәа
|
||||
ae: avesta
|
||||
af: Afrikaans
|
||||
ak: Akan
|
||||
am: አማርኛ
|
||||
an: aragonés
|
||||
ar: اللغة العربية
|
||||
as: অসমীয়া
|
||||
av: авар мацӀ
|
||||
ay: aymar aru
|
||||
az: azərbaycan dili
|
||||
ba: башҡорт теле
|
||||
be: беларуская мова
|
||||
bg: български език
|
||||
bh: भोजपुरी
|
||||
bi: Bislama
|
||||
bm: bamanankan
|
||||
bn: বাংলা
|
||||
bo: བོད་ཡིག
|
||||
br: brezhoneg
|
||||
bs: bosanski jezik
|
||||
ca: Català
|
||||
ce: нохчийн мотт
|
||||
ch: Chamoru
|
||||
co: corsu
|
||||
cr: ᓀᐦᐃᔭᐍᐏᐣ
|
||||
cs: čeština
|
||||
cu: ѩзыкъ словѣньскъ
|
||||
cv: чӑваш чӗлхи
|
||||
cy: Cymraeg
|
||||
da: dansk
|
||||
de: Deutsch
|
||||
dv: Dhivehi
|
||||
dz: རྫོང་ཁ
|
||||
ee: Eʋegbe
|
||||
el: Ελληνικά
|
||||
en: English
|
||||
eo: Esperanto
|
||||
es: español
|
||||
et: eesti
|
||||
eu: euskara
|
||||
fa: فارسی
|
||||
ff: Fulfulde
|
||||
fi: suomi
|
||||
fj: Vakaviti
|
||||
fo: føroyskt
|
||||
fr: français
|
||||
fy: Frysk
|
||||
ga: Gaeilge
|
||||
gd: Gàidhlig
|
||||
gl: galego
|
||||
gu: ગુજરાતી
|
||||
gv: Gaelg
|
||||
ha: هَوُسَ
|
||||
he: עברית
|
||||
hi: हिन्दी
|
||||
ho: Hiri Motu
|
||||
hr: Hrvatski
|
||||
ht: Kreyòl ayisyen
|
||||
hu: magyar
|
||||
hy: Հայերեն
|
||||
hz: Otjiherero
|
||||
ia: Interlingua
|
||||
id: Bahasa Indonesia
|
||||
ie: Interlingue
|
||||
ig: Asụsụ Igbo
|
||||
ii: ꆈꌠ꒿ Nuosuhxop
|
||||
ik: Iñupiaq
|
||||
io: Ido
|
||||
is: Íslenska
|
||||
it: italiano
|
||||
iu: ᐃᓄᒃᑎᑐᑦ
|
||||
ja: 日本語
|
||||
jv: basa Jawa
|
||||
ka: ქართული
|
||||
kg: Kikongo
|
||||
ki: Gĩkũyũ
|
||||
kj: Kuanyama
|
||||
kk: қазақ тілі
|
||||
kl: kalaallisut
|
||||
km: ខេមរភាសា
|
||||
kn: ಕನ್ನಡ
|
||||
ko: 한국어
|
||||
kr: Kanuri
|
||||
ks: कश्मीरी
|
||||
ku: Kurdî
|
||||
kv: коми кыв
|
||||
kw: Kernewek
|
||||
ky: Кыргызча
|
||||
la: latine
|
||||
lb: Lëtzebuergesch
|
||||
lg: Luganda
|
||||
li: Limburgs
|
||||
ln: Lingála
|
||||
lo: ພາສາ
|
||||
lt: lietuvių kalba
|
||||
lu: Tshiluba
|
||||
lv: latviešu valoda
|
||||
mg: fiteny malagasy
|
||||
mh: Kajin M̧ajeļ
|
||||
mi: te reo Māori
|
||||
mk: македонски јазик
|
||||
ml: മലയാളം
|
||||
mn: Монгол хэл
|
||||
mr: मराठी
|
||||
ms: Bahasa Malaysia
|
||||
mt: Malti
|
||||
my: ဗမာစာ
|
||||
na: Ekakairũ Naoero
|
||||
nb: Norsk bokmål
|
||||
nd: isiNdebele
|
||||
ne: नेपाली
|
||||
ng: Owambo
|
||||
nl: Nederlands
|
||||
nn: Norsk nynorsk
|
||||
'no': Norsk
|
||||
nr: isiNdebele
|
||||
nv: Diné bizaad
|
||||
ny: chiCheŵa
|
||||
oc: occitan
|
||||
oj: ᐊᓂᔑᓈᐯᒧᐎᓐ
|
||||
om: Afaan Oromoo
|
||||
or: ଓଡ଼ିଆ
|
||||
os: ирон æвзаг
|
||||
pa: ਪੰਜਾਬੀ
|
||||
pi: पाऴि
|
||||
pl: Polski
|
||||
ps: پښتو
|
||||
pt: português
|
||||
qu: Runa Simi
|
||||
rm: rumantsch grischun
|
||||
rn: Ikirundi
|
||||
ro: Română
|
||||
ru: русский язык
|
||||
rw: Ikinyarwanda
|
||||
sa: संस्कृतम्
|
||||
sc: sardu
|
||||
sd: सिन्धी
|
||||
se: Davvisámegiella
|
||||
sg: yângâ tî sängö
|
||||
si: සිංහල
|
||||
sk: slovenčina
|
||||
sl: slovenščina
|
||||
sn: chiShona
|
||||
so: Soomaaliga
|
||||
sq: shqip
|
||||
sr: српски језик
|
||||
ss: SiSwati
|
||||
st: Sesotho
|
||||
su: Basa Sunda
|
||||
sv: svenska
|
||||
sw: Kiswahili
|
||||
ta: தமிழ்
|
||||
te: తెలుగు
|
||||
tg: тоҷикӣ
|
||||
th: ไทย
|
||||
ti: ትግርኛ
|
||||
tk: Türkmen
|
||||
tl: Wikang Tagalog
|
||||
tn: Setswana
|
||||
to: faka Tonga
|
||||
tr: Türkçe
|
||||
ts: Xitsonga
|
||||
tt: татар теле
|
||||
tw: Twi
|
||||
ty: Reo Tahiti
|
||||
ug: ئۇيغۇرچە
|
||||
uk: українська мова
|
||||
ur: اردو
|
||||
uz: Ўзбек
|
||||
ve: Tshivenḓa
|
||||
vi: Tiếng Việt
|
||||
vo: Volapük
|
||||
wa: walon
|
||||
wo: Wollof
|
||||
xh: isiXhosa
|
||||
yi: ייִדיש
|
||||
yo: Yorùbá
|
||||
za: Saɯ cueŋƅ
|
||||
zh: 汉语
|
||||
zu: isiZulu
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
---
|
||||
|
||||
FastAPI to nowoczesny, wydajny framework webowy do budowania API z użyciem Pythona 3.6+ bazujący na standardowym typowaniu Pythona.
|
||||
FastAPI to nowoczesny, wydajny framework webowy do budowania API z użyciem Pythona 3.8+ bazujący na standardowym typowaniu Pythona.
|
||||
|
||||
Kluczowe cechy:
|
||||
|
||||
|
||||
5
docs/ru/docs/learn/index.md
Normal file
5
docs/ru/docs/learn/index.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Обучение
|
||||
|
||||
Здесь представлены вводные разделы и учебные пособия для изучения **FastAPI**.
|
||||
|
||||
Вы можете считать это **книгой**, **курсом**, **официальным** и рекомендуемым способом изучения FastAPI. 😎
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
В этом примере сообщения будут записаны в `log.txt` *после* того, как ответ сервера был отправлен.
|
||||
|
||||
Если бы в запросе была очередь `q`, она бы первой записалась в `log.txt` фоновой задачей (потому что вызывается в зависимости `get_query`).
|
||||
Если бы в запрос был передан query-параметр `q`, он бы первыми записался в `log.txt` фоновой задачей (потому что вызывается в зависимости `get_query`).
|
||||
|
||||
После другая фоновая задача, которая была сгенерирована в функции, запишет сообщение из параметра `email`.
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ my_list: List[str]
|
||||
|
||||
И в Python есть специальный тип данных для множеств уникальных элементов - `set`.
|
||||
|
||||
Тогда мы может обьявить поле `tags` как множество строк:
|
||||
Тогда мы можем обьявить поле `tags` как множество строк:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ $ python myapp.py
|
||||
|
||||
</div>
|
||||
|
||||
но не вызывался, когда другой файл импортирует это, например::
|
||||
но не вызывался, когда другой файл импортирует это, например:
|
||||
|
||||
```Python
|
||||
from myapp import app
|
||||
|
||||
314
docs/ru/docs/tutorial/request-files.md
Normal file
314
docs/ru/docs/tutorial/request-files.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# Загрузка файлов
|
||||
|
||||
Используя класс `File`, мы можем позволить клиентам загружать файлы.
|
||||
|
||||
!!! info "Дополнительная информация"
|
||||
Чтобы получать загруженные файлы, сначала установите <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Например: `pip install python-multipart`.
|
||||
|
||||
Это связано с тем, что загружаемые файлы передаются как данные формы.
|
||||
|
||||
## Импорт `File`
|
||||
|
||||
Импортируйте `File` и `UploadFile` из модуля `fastapi`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Определите параметры `File`
|
||||
|
||||
Создайте параметры `File` так же, как вы это делаете для `Body` или `Form`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! info "Дополнительная информация"
|
||||
`File` - это класс, который наследуется непосредственно от `Form`.
|
||||
|
||||
Но помните, что когда вы импортируете `Query`, `Path`, `File` и другие из `fastapi`, на самом деле это функции, которые возвращают специальные классы.
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Для объявления тела файла необходимо использовать `File`, поскольку в противном случае параметры будут интерпретироваться как параметры запроса или параметры тела (JSON).
|
||||
|
||||
Файлы будут загружены как данные формы.
|
||||
|
||||
Если вы объявите тип параметра у *функции операции пути* как `bytes`, то **FastAPI** прочитает файл за вас, и вы получите его содержимое в виде `bytes`.
|
||||
|
||||
Следует иметь в виду, что все содержимое будет храниться в памяти. Это хорошо подходит для небольших файлов.
|
||||
|
||||
Однако возможны случаи, когда использование `UploadFile` может оказаться полезным.
|
||||
|
||||
## Загрузка файла с помощью `UploadFile`
|
||||
|
||||
Определите параметр файла с типом `UploadFile`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
Использование `UploadFile` имеет ряд преимуществ перед `bytes`:
|
||||
|
||||
* Использовать `File()` в значении параметра по умолчанию не обязательно.
|
||||
* При этом используется "буферный" файл:
|
||||
* Файл, хранящийся в памяти до максимального предела размера, после преодоления которого он будет храниться на диске.
|
||||
* Это означает, что он будет хорошо работать с большими файлами, такими как изображения, видео, большие бинарные файлы и т.д., не потребляя при этом всю память.
|
||||
* Из загруженного файла можно получить метаданные.
|
||||
* Он реализует <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> `async` интерфейс.
|
||||
* Он предоставляет реальный объект Python <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> который вы можете передать непосредственно другим библиотекам, которые ожидают файл в качестве объекта.
|
||||
|
||||
### `UploadFile`
|
||||
|
||||
`UploadFile` имеет следующие атрибуты:
|
||||
|
||||
* `filename`: Строка `str` с исходным именем файла, который был загружен (например, `myimage.jpg`).
|
||||
* `content_type`: Строка `str` с типом содержимого (MIME type / media type) (например, `image/jpeg`).
|
||||
* `file`: <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> (a <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> объект). Это фактический файл Python, который можно передавать непосредственно другим функциям или библиотекам, ожидающим файл в качестве объекта.
|
||||
|
||||
`UploadFile` имеет следующие методы `async`. Все они вызывают соответствующие файловые методы (используя внутренний SpooledTemporaryFile).
|
||||
|
||||
* `write(data)`: Записать данные `data` (`str` или `bytes`) в файл.
|
||||
* `read(size)`: Прочитать количество `size` (`int`) байт/символов из файла.
|
||||
* `seek(offset)`: Перейти к байту на позиции `offset` (`int`) в файле.
|
||||
* Наример, `await myfile.seek(0)` перейдет к началу файла.
|
||||
* Это особенно удобно, если вы один раз выполнили команду `await myfile.read()`, а затем вам нужно прочитать содержимое файла еще раз.
|
||||
* `close()`: Закрыть файл.
|
||||
|
||||
Поскольку все эти методы являются `async` методами, вам следует использовать "await" вместе с ними.
|
||||
|
||||
Например, внутри `async` *функции операции пути* можно получить содержимое с помощью:
|
||||
|
||||
```Python
|
||||
contents = await myfile.read()
|
||||
```
|
||||
|
||||
Если вы находитесь внутри обычной `def` *функции операции пути*, можно получить прямой доступ к файлу `UploadFile.file`, например:
|
||||
|
||||
```Python
|
||||
contents = myfile.file.read()
|
||||
```
|
||||
|
||||
!!! note "Технические детали `async`"
|
||||
При использовании методов `async` **FastAPI** запускает файловые методы в пуле потоков и ожидает их.
|
||||
|
||||
!!! note "Технические детали Starlette"
|
||||
**FastAPI** наследует `UploadFile` непосредственно из **Starlette**, но добавляет некоторые детали для совместимости с **Pydantic** и другими частями FastAPI.
|
||||
|
||||
## Про данные формы ("Form Data")
|
||||
|
||||
Способ, которым HTML-формы (`<form></form>`) отправляют данные на сервер, обычно использует "специальную" кодировку для этих данных, отличную от JSON.
|
||||
|
||||
**FastAPI** позаботится о том, чтобы считать эти данные из нужного места, а не из JSON.
|
||||
|
||||
!!! note "Технические детали"
|
||||
Данные из форм обычно кодируются с использованием "media type" `application/x-www-form-urlencoded` когда он не включает файлы.
|
||||
|
||||
Но когда форма включает файлы, она кодируется как multipart/form-data. Если вы используете `File`, **FastAPI** будет знать, что ему нужно получить файлы из нужной части тела.
|
||||
|
||||
Если вы хотите узнать больше об этих кодировках и полях форм, перейдите по ссылке <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a>.
|
||||
|
||||
!!! warning "Внимание"
|
||||
В операции *функции операции пути* можно объявить несколько параметров `File` и `Form`, но нельзя также объявлять поля `Body`, которые предполагается получить в виде JSON, поскольку тело запроса будет закодировано с помощью `multipart/form-data`, а не `application/json`.
|
||||
|
||||
Это не является ограничением **FastAPI**, это часть протокола HTTP.
|
||||
|
||||
## Необязательная загрузка файлов
|
||||
|
||||
Вы можете сделать загрузку файла необязательной, используя стандартные аннотации типов и установив значение по умолчанию `None`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="10 18"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="7 15"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02.py!}
|
||||
```
|
||||
|
||||
## `UploadFile` с дополнительными метаданными
|
||||
|
||||
Вы также можете использовать `File()` вместе с `UploadFile`, например, для установки дополнительных метаданных:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="9 15"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="8 14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="7 13"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03.py!}
|
||||
```
|
||||
|
||||
## Загрузка нескольких файлов
|
||||
|
||||
Можно одновременно загружать несколько файлов.
|
||||
|
||||
Они будут связаны с одним и тем же "полем формы", отправляемым с помощью данных формы.
|
||||
|
||||
Для этого необходимо объявить список `bytes` или `UploadFile`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/request_files/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002.py!}
|
||||
```
|
||||
|
||||
Вы получите, как и было объявлено, список `list` из `bytes` или `UploadFile`.
|
||||
|
||||
!!! note "Technical Details"
|
||||
Можно также использовать `from starlette.responses import HTMLResponse`.
|
||||
|
||||
**FastAPI** предоставляет тот же `starlette.responses`, что и `fastapi.responses`, просто для удобства разработчика. Однако большинство доступных ответов поступает непосредственно из Starlette.
|
||||
|
||||
### Загрузка нескольких файлов с дополнительными метаданными
|
||||
|
||||
Так же, как и раньше, вы можете использовать `File()` для задания дополнительных параметров, даже для `UploadFile`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="11 18-20"
|
||||
{!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="12 19-21"
|
||||
{!> ../../../docs_src/request_files/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="9 16"
|
||||
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="11 18"
|
||||
{!> ../../../docs_src/request_files/tutorial003.py!}
|
||||
```
|
||||
|
||||
## Резюме
|
||||
|
||||
Используйте `File`, `bytes` и `UploadFile` для работы с файлами, которые будут загружаться и передаваться в виде данных формы.
|
||||
69
docs/ru/docs/tutorial/request-forms-and-files.md
Normal file
69
docs/ru/docs/tutorial/request-forms-and-files.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Файлы и формы в запросе
|
||||
|
||||
Вы можете определять файлы и поля формы одновременно, используя `File` и `Form`.
|
||||
|
||||
!!! info "Дополнительная информация"
|
||||
Чтобы получать загруженные файлы и/или данные форм, сначала установите <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Например: `pip install python-multipart`.
|
||||
|
||||
## Импортируйте `File` и `Form`
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
## Определите параметры `File` и `Form`
|
||||
|
||||
Создайте параметры файла и формы таким же образом, как для `Body` или `Query`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
|
||||
```Python hl_lines="10-12"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+"
|
||||
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.6+ без Annotated"
|
||||
|
||||
!!! tip "Подсказка"
|
||||
Предпочтительнее использовать версию с аннотацией, если это возможно.
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
Файлы и поля формы будут загружены в виде данных формы, и вы получите файлы и поля формы.
|
||||
|
||||
Вы можете объявить некоторые файлы как `bytes`, а некоторые - как `UploadFile`.
|
||||
|
||||
!!! warning "Внимание"
|
||||
Вы можете объявить несколько параметров `File` и `Form` в операции *path*, но вы не можете также объявить поля `Body`, которые вы ожидаете получить в виде JSON, так как запрос будет иметь тело, закодированное с помощью `multipart/form-data` вместо `application/json`.
|
||||
|
||||
Это не ограничение **Fast API**, это часть протокола HTTP.
|
||||
|
||||
## Резюме
|
||||
|
||||
Используйте `File` и `Form` вместе, когда необходимо получить данные и файлы в одном запросе.
|
||||
33
docs/tr/docs/external-links.md
Normal file
33
docs/tr/docs/external-links.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Harici Bağlantılar ve Makaleler
|
||||
|
||||
**FastAPI** sürekli büyüyen harika bir topluluğa sahiptir.
|
||||
|
||||
**FastAPI** ile alakalı birçok yazı, makale, araç ve proje bulunmaktadır.
|
||||
|
||||
Bunlardan bazılarının tamamlanmamış bir listesi aşağıda bulunmaktadır.
|
||||
|
||||
!!! tip "İpucu"
|
||||
Eğer **FastAPI** ile alakalı henüz burada listelenmemiş bir makale, proje, araç veya başka bir şeyiniz varsa, bunu eklediğiniz bir <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request</a> oluşturabilirsiniz.
|
||||
|
||||
{% 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 %}
|
||||
|
||||
## Projeler
|
||||
|
||||
`fastapi` konulu en son GitHub projeleri:
|
||||
|
||||
<div class="github-topic-projects">
|
||||
</div>
|
||||
@@ -2,45 +2,47 @@
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>FastAPI framework, yüksek performanslı, öğrenmesi kolay, geliştirmesi hızlı, kullanıma sunulmaya hazır.</em>
|
||||
<em>FastAPI framework, yüksek performanslı, öğrenmesi oldukça kolay, kodlaması hızlı, kullanıma hazır</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg" alt="Test">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/codecov/c/github/tiangolo/fastapi?color=%2334D058" alt="Coverage">
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**dokümantasyon**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
**Dokümantasyon**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Kaynak kodu**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
**Kaynak Kod**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI, Python 3.8+'nın standart type hintlerine dayanan modern ve hızlı (yüksek performanslı) API'lar oluşturmak için kullanılabilecek web framework'ü.
|
||||
FastAPI, Python <abbr title="Python 3.8 ve üzeri">3.8+</abbr>'nin standart <abbr title="Tip Belirteçleri: Type Hints">tip belirteçleri</abbr>ne dayalı, modern ve hızlı (yüksek performanslı) API'lar oluşturmak için kullanılabilecek web framework'tür.
|
||||
|
||||
Ana özellikleri:
|
||||
Temel özellikleri şunlardır:
|
||||
|
||||
* **Hızlı**: çok yüksek performanslı, **NodeJS** ve **Go** ile eşdeğer seviyede performans sağlıyor, (Starlette ve Pydantic sayesinde.) [Python'un en hızlı frameworklerinden bir tanesi.](#performans).
|
||||
* **Kodlaması hızlı**: Yeni özellikler geliştirmek neredeyse %200 - %300 daha hızlı. *
|
||||
* **Daha az bug**: Geliştirici (insan) kaynaklı hatalar neredeyse %40 azaltıldı. *
|
||||
* **Sezgileri güçlü**: Editor (otomatik-tamamlama) desteği harika. <abbr title="Otomatik tamamlama-IntelliSense">Otomatik tamamlama</abbr> her yerde. Debuglamak ile daha az zaman harcayacaksınız.
|
||||
* **Kolay**: Öğrenmesi ve kullanması kolay olacak şekilde. Doküman okumak için harcayacağınız süre azaltıldı.
|
||||
* **Kısa**: Kod tekrarını minimuma indirdik. Fonksiyon parametrelerinin tiplerini belirtmede farklı yollar sunarak karşılaşacağınız bug'ları azalttık.
|
||||
* **Güçlü**: Otomatik dokümantasyon ile beraber, kullanıma hazır kod yaz.
|
||||
* **Hızlı**: Çok yüksek performanslı, **NodeJS** ve **Go** ile eşit düzeyde (Starlette ve Pydantic sayesinde). [En hızlı Python framework'lerinden bir tanesidir](#performans).
|
||||
* **Kodlaması Hızlı**: Geliştirme hızını yaklaşık %200 ile %300 aralığında arttırır. *
|
||||
* **Daha az hata**: İnsan (geliştirici) kaynaklı hataları yaklaşık %40 azaltır. *
|
||||
* **Sezgisel**: Muhteşem bir editör desteği. Her yerde <abbr title="Otomatik Tamamlama: auto-complete, autocompletion, IntelliSense">otomatik tamamlama</abbr>. Hata ayıklama ile daha az zaman harcayacaksınız.
|
||||
* **Kolay**: Öğrenmesi ve kullanması kolay olacak şekilde tasarlandı. Doküman okuma ile daha az zaman harcayacaksınız.
|
||||
* **Kısa**: Kod tekrarı minimize edildi. Her parametre tanımlamasında birden fazla özellik ve daha az hatayla karşılaşacaksınız.
|
||||
* **Güçlü**: Otomatik ve etkileşimli dokümantasyon ile birlikte, kullanıma hazır kod elde edebilirsiniz.
|
||||
* **Standard öncelikli**: API'lar için açık standartlara dayalı (ve tamamen uyumlu); <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (eski adıyla Swagger) ve <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
* **Standartlar belirli**: Tamamiyle API'ların açık standartlara bağlı ve (tam uyumlululuk içerisinde); <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (eski adıyla Swagger) ve <a href="http://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
<small>* ilgili kanılar, dahili geliştirme ekibinin geliştirdikleri ürünlere yaptıkları testlere dayanmaktadır.</small>
|
||||
|
||||
<small>* Bahsi geçen rakamsal ifadeler tamamiyle, geliştirme takımının kendi sundukları ürünü geliştirirken yaptıkları testlere dayanmakta.</small>
|
||||
|
||||
## Sponsors
|
||||
## Sponsorlar
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
@@ -55,63 +57,61 @@ Ana özellikleri:
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
<a href="https://fastapi.tiangolo.com/tr/fastapi-people/#sponsors" class="external-link" target="_blank">Diğer Sponsorlar</a>
|
||||
|
||||
## Görüşler
|
||||
|
||||
|
||||
"_[...] Bugünlerde **FastAPI**'ı çok fazla kullanıyorum [...] Aslına bakarsanız **Microsoft'taki Machine Learning servislerimizin** hepsinde kullanmayı düşünüyorum. FastAPI ile geliştirdiğimiz servislerin bazıları çoktan **Windows**'un ana ürünlerine ve **Office** ürünlerine entegre edilmeye başlandı bile._"
|
||||
"_[...] Bugünlerde **FastAPI**'ı çok fazla kullanıyorum. [...] Aslında bunu ekibimin **Microsoft'taki Machine Learning servislerinin** tamamında kullanmayı planlıyorum. Bunlardan bazıları **Windows**'un ana ürünlerine ve **Office** ürünlerine entegre ediliyor._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
"_**FastAPI**'ı **tahminlerimiz**'i sorgulanabilir hale getirmek için **REST** mimarisı ile beraber server üzerinde kullanmaya başladık._"
|
||||
|
||||
"_**FastAPI**'ı **tahminlerimiz**'i sorgulanabilir hale getirecek bir **REST** sunucu oluşturmak için benimsedik/kullanmaya başladık._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
"_**Netflix** **kriz yönetiminde** orkestrasyon yapabilmek için geliştirdiği yeni framework'ü **Dispatch**'in, açık kaynak versiyonunu paylaşmaktan gurur duyuyor. [**FastAPI** ile yapıldı.]_"
|
||||
"_**Netflix**, **kriz yönetiminde** orkestrasyon yapabilmek için geliştirdiği yeni framework'ü **Dispatch**'in, açık kaynak sürümünü paylaşmaktan gurur duyuyor. [**FastAPI** ile yapıldı.]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
|
||||
"_**FastAPI** için ayın üzerindeymişcesine heyecanlıyım. Çok eğlenceli!_"
|
||||
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Dürüst olmak gerekirse, geliştirdiğin şey bir çok açıdan çok sağlam ve parlak gözüküyor. Açıkcası benim **Hug**'ı tasarlarken yapmaya çalıştığım şey buydu - bunu birisinin başardığını görmek gerçekten çok ilham verici._"
|
||||
"_Dürüst olmak gerekirse, inşa ettiğiniz şey gerçekten sağlam ve profesyonel görünüyor. Birçok açıdan **Hug**'ın olmasını istediğim şey tam da bu - böyle bir şeyi inşa eden birini görmek gerçekten ilham verici._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a>'ın Yaratıcısı</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="http://www.hug.rest/" target="_blank">Hug</a>'ın Yaratıcısı</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Eğer REST API geliştirmek için **modern bir framework** öğrenme arayışında isen, **FastAPI**'a bir göz at [...] Hızlı, kullanımı ve öğrenmesi kolay. [...]_"
|
||||
|
||||
"_Biz **API** servislerimizi **FastAPI**'a geçirdik [...] Sizin de beğeneceğinizi düşünüyoruz. [...]_"
|
||||
|
||||
"_Eğer REST API geliştirmek için **modern bir framework** öğrenme arayışında isen, **FastAPI**'a bir göz at [...] Hızlı, kullanımı ve öğrenmesi kolay. [...]_"
|
||||
|
||||
"_**API** servislerimizi **FastAPI**'a taşıdık [...] Sizin de beğeneceğinizi düşünüyoruz. [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> kurucuları - <a href="https://spacy.io" target="_blank">spaCy</a> yaratıcıları</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, komut satırı uygulamalarının FastAPI'ı
|
||||
"_Python ile kullanıma hazır bir API oluşturmak isteyen herhangi biri için, **FastAPI**'ı şiddetle tavsiye ederim. **Harika tasarlanmış**, **kullanımı kolay** ve **yüksek ölçeklenebilir**, API odaklı geliştirme stratejimizin **ana bileşeni** haline geldi ve Virtual TAC Engineer gibi birçok otomasyon ve servisi yönetiyor._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## Komut Satırı Uygulamalarının FastAPI'ı: **Typer**
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
Eğer API yerine <abbr title="Command Line Interface">komut satırı uygulaması</abbr> geliştiriyor isen <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>'a bir göz at.
|
||||
Eğer API yerine, terminalde kullanılmak üzere bir <abbr title="Komut Satırı: Command Line Interface">komut satırı uygulaması</abbr> geliştiriyorsanız <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>'a göz atabilirsiniz.
|
||||
|
||||
**Typer** kısaca FastAPI'ın küçük kız kardeşi. Komut satırı uygulamalarının **FastAPI'ı** olması hedeflendi. ⌨️ 🚀
|
||||
**Typer** kısaca FastAPI'ın küçük kardeşi. Ve hedefi komut satırı uygulamalarının **FastAPI'ı** olmak. ⌨️ 🚀
|
||||
|
||||
## Gereksinimler
|
||||
|
||||
@@ -122,7 +122,7 @@ FastAPI iki devin omuzları üstünde duruyor:
|
||||
* Web tarafı için <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>.
|
||||
* Data tarafı için <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a>.
|
||||
|
||||
## Yükleme
|
||||
## Kurulum
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -134,7 +134,7 @@ $ pip install fastapi
|
||||
|
||||
</div>
|
||||
|
||||
Uygulamanı kullanılabilir hale getirmek için <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> ya da <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a> gibi bir ASGI serverına ihtiyacın olacak.
|
||||
Uygulamamızı kullanılabilir hale getirmek için <a href="http://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> ya da <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a> gibi bir ASGI sunucusuna ihtiyacımız olacak.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -148,9 +148,9 @@ $ pip install "uvicorn[standard]"
|
||||
|
||||
## Örnek
|
||||
|
||||
### Şimdi dene
|
||||
### Kodu Oluşturalım
|
||||
|
||||
* `main.py` adında bir dosya oluştur :
|
||||
* `main.py` adında bir dosya oluşturup içine şu kodu yapıştıralım:
|
||||
|
||||
```Python
|
||||
from typing import Union
|
||||
@@ -173,9 +173,9 @@ def read_item(item_id: int, q: Union[str, None] = None):
|
||||
<details markdown="1">
|
||||
<summary>Ya da <code>async def</code>...</summary>
|
||||
|
||||
Eğer kodunda `async` / `await` var ise, `async def` kullan:
|
||||
Eğer kodunuzda `async` / `await` varsa, `async def` kullanalım:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
@@ -195,13 +195,13 @@ async def read_item(item_id: int, q: Union[str, None] = None):
|
||||
|
||||
**Not**:
|
||||
|
||||
Eğer ne olduğunu bilmiyor isen _"Acelen mi var?"_ kısmını oku <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` ve `await`</a>.
|
||||
Eğer bu konu hakkında bilginiz yoksa <a href="https://fastapi.tiangolo.com/tr/async/#in-a-hurry" target="_blank">`async` ve `await`</a> dokümantasyonundaki _"Aceleniz mi var?"_ kısmını kontrol edebilirsiniz.
|
||||
|
||||
</details>
|
||||
|
||||
### Çalıştır
|
||||
### Kodu Çalıştıralım
|
||||
|
||||
Serverı aşağıdaki komut ile çalıştır:
|
||||
Sunucuyu aşağıdaki komutla çalıştıralım:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -218,56 +218,56 @@ INFO: Application startup complete.
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Çalıştırdığımız <code>uvicorn main:app --reload</code> hakkında...</summary>
|
||||
<summary><code>uvicorn main:app --reload</code> komutuyla ilgili...</summary>
|
||||
|
||||
`uvicorn main:app` şunları ifade ediyor:
|
||||
`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 oluşturduğumuz `app = FastAPI()` 'a denk geliyor.
|
||||
* `--reload`: ise kodda herhangi bir değişiklik yaptığımızda serverın yapılan değişiklerileri algılayıp, değişiklikleri siz herhangi bir şey yapmadan uygulamasını sağlıyor.
|
||||
* `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.
|
||||
|
||||
</details>
|
||||
|
||||
### Dokümantasyonu kontrol et
|
||||
### Şimdi de Kontrol Edelim
|
||||
|
||||
Browserını aç ve şu linke git <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
Tarayıcımızda şu bağlantıyı açalım <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
Bir JSON yanıtı göreceksin:
|
||||
Aşağıdaki gibi bir JSON yanıtıyla karşılaşacağız:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
Az önce oluşturduğun API:
|
||||
Az önce oluşturduğumuz API:
|
||||
|
||||
* `/` ve `/items/{item_id}` adreslerine HTTP talebi alabilir hale geldi.
|
||||
* İki _adresde_ `GET` <em>operasyonlarını</em> (HTTP _metodları_ olarakta bilinen) yapabilir hale geldi.
|
||||
* `/items/{item_id}` _adresi_ ayrıca bir `item_id` _adres parametresine_ sahip ve bu bir `int` olmak zorunda.
|
||||
* `/items/{item_id}` _adresi_ opsiyonel bir `str` _sorgu paramtersine_ sahip bu da `q`.
|
||||
* `/` ve `/items/{item_id}` <abbr title="Adres / Yol: Path ">_yollarına_</abbr> HTTP isteği alabilir.
|
||||
* İki _yolda_ `GET` <em>operasyonlarını</em> (HTTP _metodları_ olarak da bilinen) kabul ediyor.
|
||||
* `/items/{item_id}` _yolu_ `item_id` adında bir _yol parametresine_ sahip ve bu parametre `int` değer almak zorundadır.
|
||||
* `/items/{item_id}` _yolu_ `q` adında bir _yol parametresine_ sahip ve bu parametre opsiyonel olmakla birlikte, `str` değer almak zorundadır.
|
||||
|
||||
### İnteraktif API dokümantasyonu
|
||||
### 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> adresine git.
|
||||
Ş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.
|
||||
|
||||
Senin için 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öreceksin:
|
||||
<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
|
||||
### 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 git.
|
||||
Ş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.
|
||||
|
||||
Senin için alternatif olarak (<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> tarafından sağlanan) bir API dokümantasyonu daha göreceksin:
|
||||
<a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a> tarafından sağlanan otomatik dokümantasyonu göreceğiz:
|
||||
|
||||

|
||||
|
||||
## Örnek bir değişiklik
|
||||
## Örneği Güncelleyelim
|
||||
|
||||
Şimdi `main.py` dosyasını değiştirelim ve body ile `PUT` talebi alabilir hale getirelim.
|
||||
Şimdi `main.py` dosyasını, `PUT` isteğiyle birlikte bir gövde alacak şekilde değiştirelim.
|
||||
|
||||
Şimdi Pydantic sayesinde, Python'un standart tiplerini kullanarak bir body tanımlayacağız.
|
||||
<abbr title="Gövde: Body">Gövde</abbr>yi Pydantic sayesinde standart python tiplerini kullanarak tanımlayalım.
|
||||
|
||||
```Python hl_lines="4 9 10 11 12 25 26 27"
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
@@ -297,41 +297,41 @@ def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
Server otomatik olarak yeniden başlamalı (çünkü yukarıda `uvicorn`'u çalıştırırken `--reload` parametresini kullandık.).
|
||||
Sunucu otomatik olarak yeniden başlamış olmalı (çünkü yukarıda `uvicorn` komutuyla birlikte `--reload` parametresini kullandık).
|
||||
|
||||
### İnteraktif API dokümantasyonu'nda değiştirme yapmak
|
||||
### Etkileşimli API Dokümantasyonundaki Değişimi Görelim
|
||||
|
||||
Ş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ına tekrar git.
|
||||
Ş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ına tekrar gidelim.
|
||||
|
||||
* İnteraktif API dokümantasyonu, yeni body ile beraber çoktan yenilenmiş olması lazım:
|
||||
* Etkileşimli API dokümantasyonu, yeni gövdede dahil olmak üzere otomatik olarak güncellenmiş olacak:
|
||||
|
||||

|
||||
|
||||
* "Try it out"a tıkla, bu senin API parametleri üzerinde deneme yapabilmene izin veriyor:
|
||||
* "Try it out" butonuna tıklayalım, bu işlem API parametleri üzerinde değişiklik yapmamıza ve doğrudan API ile etkileşime geçmemize imkan sağlayacak:
|
||||
|
||||

|
||||
|
||||
* Şimdi "Execute" butonuna tıkla, kullanıcı arayüzü otomatik olarak API'ın ile bağlantı kurarak ona bu parametreleri gönderecek ve sonucu karşına getirecek.
|
||||
* Şimdi "Execute" butonuna tıklayalım, kullanıcı arayüzü API'ımız ile bağlantı kurup parametreleri gönderecek ve sonucu ekranımıza getirecek:
|
||||
|
||||

|
||||
|
||||
### Alternatif API dokümantasyonunda değiştirmek
|
||||
### Alternatif API Dokümantasyonundaki Değişimi Görelim
|
||||
|
||||
Şimdi ise <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> adresine git.
|
||||
Şimdi ise <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ına tekrar gidelim.
|
||||
|
||||
* Alternatif dokümantasyonda koddaki değişimler ile beraber kendini yeni query ve body ile güncelledi.
|
||||
* Alternatif dokümantasyonda yaptığımız değişiklikler ile birlikte yeni sorgu parametresi ve gövde bilgisi ile güncelemiş olacak:
|
||||
|
||||

|
||||
|
||||
### Özet
|
||||
|
||||
Özetleyecek olursak, URL, sorgu veya request body'deki parametrelerini fonksiyon parametresi olarak kullanıyorsun. Bu parametrelerin veri tiplerini bir kere belirtmen yeterli.
|
||||
Özetlemek gerekirse, parametrelerin, gövdenin, vb. veri tiplerini fonksiyon parametreleri olarak **bir kere** tanımlıyoruz.
|
||||
|
||||
Type-hinting işlemini Python dilindeki standart veri tipleri ile yapabilirsin
|
||||
Bu işlemi standart modern Python tipleriyle yapıyoruz.
|
||||
|
||||
Yeni bir syntax'e alışmana gerek yok, metodlar ve classlar zaten spesifik kütüphanelere ait.
|
||||
Yeni bir sözdizimi yapısını, bir kütüphane özel metod veya sınıfları öğrenmeye gerek yoktur.
|
||||
|
||||
Sadece standart **Python 3.8+**.
|
||||
Hepsi sadece **Python 3.8+** standartlarına dayalıdır.
|
||||
|
||||
Örnek olarak, `int` tanımlamak için:
|
||||
|
||||
@@ -339,64 +339,64 @@ Sadece standart **Python 3.8+**.
|
||||
item_id: int
|
||||
```
|
||||
|
||||
ya da daha kompleks `Item` tipi:
|
||||
ya da daha kompleks herhangi bir python modelini tanımlayabiliriz, örneğin `Item` modeli için:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...sadece kısa bir parametre tipi belirtmekle beraber, sahip olacakların:
|
||||
...ve sadece kısa bir parametre tipi belirterek elde ettiklerimiz:
|
||||
|
||||
* Editör desteği dahil olmak üzere:
|
||||
* Editör desteğiyle birlikte:
|
||||
* Otomatik tamamlama.
|
||||
* Tip sorguları.
|
||||
* Datanın tipe uyumunun sorgulanması:
|
||||
* Eğer data geçersiz ise, otomatik olarak hataları ayıklar.
|
||||
* Çok derin JSON objelerinde bile veri tipi sorgusu yapar.
|
||||
* Gelen verinin <abbr title="parsing, serializing, marshalling olarakta biliniyor">dönüşümünü</abbr> aşağıdaki veri tiplerini kullanarak gerçekleştirebiliyor.
|
||||
* Tip kontrolü.
|
||||
* Veri Doğrulama:
|
||||
* Veri geçerli değilse, otomatik olarak açıklayıcı hatalar gösterir.
|
||||
* Çok <abbr title="Derin / İç içe: Nested">derin</abbr> JSON nesnelerinde bile doğrulama yapar.
|
||||
* Gelen verinin <abbr title="Dönüşüm: serialization, parsing, marshalling olarak da biliniyor">dönüşümünü</abbr> aşağıdaki veri tiplerini kullanarak gerçekleştirir:
|
||||
* JSON.
|
||||
* Path parametreleri.
|
||||
* Query parametreleri.
|
||||
* Cookies.
|
||||
* Yol parametreleri.
|
||||
* Sorgu parametreleri.
|
||||
* Çerezler.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Files.
|
||||
* Giden verinin <abbr title="also known as: serialization, parsing, marshalling">dönüşümünü</abbr> aşağıdaki veri tiplerini kullanarak gerçekleştirebiliyor (JSON olarak):
|
||||
* Python tiplerinin (`str`, `int`, `float`, `bool`, `list`, vs) çevirisi.
|
||||
* `datetime` objesi.
|
||||
* `UUID` objesi.
|
||||
* Formlar.
|
||||
* Dosyalar.
|
||||
* Giden verinin <abbr title="Dönüşüm: serialization, parsing, marshalling olarak da biliniyor">dönüşümünü</abbr> aşağıdaki veri tiplerini kullanarak gerçekleştirir (JSON olarak):
|
||||
* Python tiplerinin (`str`, `int`, `float`, `bool`, `list`, vb) dönüşümü.
|
||||
* `datetime` nesnesi.
|
||||
* `UUID` nesnesi.
|
||||
* Veritabanı modelleri.
|
||||
* ve daha fazlası...
|
||||
* 2 alternatif kullanıcı arayüzü dahil olmak üzere, otomatik interaktif API dokümanu:
|
||||
* ve çok daha fazlası...
|
||||
* 2 alternatif kullanıcı arayüzü dahil olmak üzere, otomatik etkileşimli API dokümantasyonu sağlar:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Az önceki kod örneğine geri dönelim, **FastAPI**'ın yapacaklarına bir bakış atalım:
|
||||
Az önceki örneğe geri dönelim, **FastAPI**'ın yapacaklarına bir bakış atalım:
|
||||
|
||||
* `item_id`'nin `GET` ve `PUT` talepleri içinde olup olmadığının doğruluğunu kontol edecek.
|
||||
* `item_id`'nin tipinin `int` olduğunu `GET` ve `PUT` talepleri içinde olup olmadığının doğruluğunu kontol edecek.
|
||||
* Eğer `GET` ve `PUT` içinde yok ise ve `int` değil ise, sebebini belirten bir hata mesajı gösterecek
|
||||
* Opsiyonel bir `q` parametresinin `GET` talebi için (`http://127.0.0.1:8000/items/foo?q=somequery` içinde) olup olmadığını kontrol edecek
|
||||
* `item_id`'nin `GET` ve `PUT` istekleri için, yolda olup olmadığının kontol edecek.
|
||||
* `item_id`'nin `GET` ve `PUT` istekleri için, tipinin `int` olduğunu doğrulayacak.
|
||||
* Eğer değilse, sebebini belirten bir hata mesajı gösterecek.
|
||||
* Opsiyonel bir `q` parametresinin `GET` isteği içinde (`http://127.0.0.1:8000/items/foo?q=somequery` gibi) olup olmadığını kontrol edecek
|
||||
* `q` parametresini `= None` ile oluşturduğumuz için, opsiyonel bir parametre olacak.
|
||||
* Eğer `None` olmasa zorunlu bir parametre olacak idi (bu yüzden body'de `PUT` parametresi var).
|
||||
* `PUT` talebi için `/items/{item_id}`'nin body'sini, JSON olarak okuyor:
|
||||
* `name` adında bir parametetre olup olmadığını ve var ise onun `str` olup olmadığını kontol ediyor.
|
||||
* `price` adında bir parametetre olup olmadığını ve var ise onun `float` olup olmadığını kontol ediyor.
|
||||
* `is_offer` adında bir parametetre olup olmadığını ve var ise onun `bool` olup olmadığını kontol ediyor.
|
||||
* Bunların hepsini en derin JSON modellerinde bile yapacaktır.
|
||||
* Bütün veri tiplerini otomatik olarak JSON'a çeviriyor veya tam tersi.
|
||||
* Her şeyi dokümanlayıp, çeşitli yerlerde:
|
||||
* İnteraktif dokümantasyon sistemleri.
|
||||
* Otomatik alıcı kodu üretim sistemlerinde ve çeşitli dillerde.
|
||||
* İki ayrı web arayüzüyle direkt olarak interaktif bir dokümantasyon sunuyor.
|
||||
* Eğer `None` olmasa zorunlu bir parametre olacaktı (`PUT` metodunun gövdesinde olduğu gibi).
|
||||
* `PUT` isteği için `/items/{item_id}`'nin gövdesini, JSON olarak doğrulayıp okuyacak:
|
||||
* `name` adında zorunlu bir parametre olup olmadığını ve varsa tipinin `str` olup olmadığını kontol edecek.
|
||||
* `price` adında zorunlu bir parametre olup olmadığını ve varsa tipinin `float` olup olmadığını kontol edecek.
|
||||
* `is_offer` adında opsiyonel bir parametre olup olmadığını ve varsa tipinin `float` olup olmadığını kontol edecek.
|
||||
* Bunların hepsi en derin JSON nesnelerinde bile çalışacak.
|
||||
* Verilerin JSON'a ve JSON'ın python nesnesine dönüşümü otomatik olarak yapılacak.
|
||||
* Her şeyi OpenAPI ile uyumlu bir şekilde otomatik olarak dokümanlayacak ve bunlarda aşağıdaki gibi kullanılabilecek:
|
||||
* Etkileşimli dokümantasyon sistemleri.
|
||||
* Bir çok programlama dili için otomatik istemci kodu üretim sistemleri.
|
||||
* İki ayrı etkileşimli dokümantasyon arayüzünü doğrudan sağlayacak.
|
||||
|
||||
---
|
||||
|
||||
Henüz yüzeysel bir bakış attık, fakat sen çoktan çalışma mantığını anladın.
|
||||
Daha yeni başladık ama çalışma mantığını çoktan anlamış oldunuz.
|
||||
|
||||
Şimdi aşağıdaki satırı değiştirmeyi dene:
|
||||
Şimdi aşağıdaki satırı değiştirmeyi deneyin:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
@@ -414,22 +414,22 @@ Henüz yüzeysel bir bakış attık, fakat sen çoktan çalışma mantığını
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...şimdi editör desteğinin nasıl veri tiplerini bildiğini ve otomatik tamamladığını gör:
|
||||
...ve editörünün veri tiplerini bildiğini ve otomatik tamamladığını göreceksiniz:
|
||||
|
||||

|
||||
|
||||
Daha fazla örnek ve özellik için <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a> sayfasını git.
|
||||
Daha fazal özellik içeren, daha eksiksiz bir örnek için <a href="https://fastapi.tiangolo.com/tr/tutorial/">Öğretici - Kullanıcı Rehberi</a> sayfasını ziyaret edebilirsin.
|
||||
|
||||
**Spoiler**: Öğretici - Kullanıcı rehberi şunları içeriyor:
|
||||
**Spoiler**: Öğretici - Kullanıcı rehberi şunları içerir:
|
||||
|
||||
* **Parameterlerini** nasıl **headers**, **cookies**, **form fields** ve **files** olarak deklare edebileceğini.
|
||||
* `maximum_length` ya da `regex` gibi şeylerle nasıl **doğrulama** yapabileceğini.
|
||||
* Çok güçlü ve kullanımı kolay **<abbr title="also known as components, resources, providers, services, injectables">Zorunluluk Entegrasyonu</abbr>** oluşturmayı.
|
||||
* Güvenlik ve kimlik doğrulama, **JWT tokenleri**'yle beraber **OAuth2** desteği, ve **HTTP Basic** doğrulaması.
|
||||
* İleri seviye fakat ona göre oldukça basit olan **derince oluşturulmuş JSON modelleri** (Pydantic sayesinde).
|
||||
* **Parameterlerin**, **headers**, **çerezler**, **form alanları** ve **dosyalar** olarak tanımlanması.
|
||||
* `maximum_length` ya da `regex` gibi **doğrulama kısıtlamalarının** nasıl yapılabileceği.
|
||||
* Çok güçlü ve kullanımı kolay **<abbr title="Bağımlılık Enjeksiyonu: components, resources, providers, services, injectables olarak da biliniyor.">Bağımlılık Enjeksiyonu</abbr>** sistemi oluşturmayı.
|
||||
* Güvenlik ve kimlik doğrulama, **JWT tokenleri** ile **OAuth2** desteği, ve **HTTP Basic** doğrulaması.
|
||||
* İleri seviye fakat bir o kadarda basit olan **çok derin JSON modelleri** (Pydantic sayesinde).
|
||||
* **GraphQL** entegrasyonu: <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> ve diğer kütüphaneleri kullanarak.
|
||||
* Diğer ekstra özellikler (Starlette sayesinde):
|
||||
* **WebSockets**
|
||||
* **GraphQL**
|
||||
* **WebSocketler**
|
||||
* HTTPX ve `pytest` sayesinde aşırı kolay testler.
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
@@ -437,33 +437,34 @@ Daha fazla örnek ve özellik için <a href="https://fastapi.tiangolo.com/tutori
|
||||
|
||||
## Performans
|
||||
|
||||
Bağımsız TechEmpower kıyaslamaları gösteriyor ki, Uvicorn'la beraber çalışan **FastAPI** uygulamaları <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">Python'un en hızlı frameworklerinden birisi </a>, sadece Starlette ve Uvicorn'dan daha yavaş ki FastAPI bunların üzerine kurulu.
|
||||
Bağımsız TechEmpower kıyaslamaları gösteriyor ki, Uvicorn ile çalıştırılan **FastAPI** uygulamaları <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">en hızlı Python framework'lerinden birisi</a>, sadece Starlette ve Uvicorn'dan yavaş, ki FastAPI bunların üzerine kurulu bir kütüphanedir.
|
||||
|
||||
Daha fazla bilgi için, bu bölüme bir göz at <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
Daha fazla bilgi için, bu bölüme bir göz at <a href="https://fastapi.tiangolo.com/tr/benchmarks/" class="internal-link" target="_blank">Kıyaslamalar</a>.
|
||||
|
||||
## Opsiyonel gereksinimler
|
||||
## Opsiyonel Gereksinimler
|
||||
|
||||
Pydantic tarafında kullanılan:
|
||||
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - email doğrulaması için.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - ayar yönetimi için.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - Pydantic ile birlikte kullanılabilecek ek tipler için.
|
||||
|
||||
Starlette tarafında kullanılan:
|
||||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Eğer `TestClient` kullanmak istiyorsan gerekli.
|
||||
* <a href="http://jinja.pocoo.org" target="_blank"><code>jinja2</code></a> - Eğer kendine ait template konfigürasyonu oluşturmak istiyorsan gerekli
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Form kullanmak istiyorsan gerekli <abbr title="HTTP bağlantısından gelen stringi Python objesine çevirmek için">("dönüşümü")</abbr>.
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Eğer `TestClient` yapısını kullanacaksanız gereklidir.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Eğer varsayılan template konfigürasyonunu kullanacaksanız gereklidir.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Eğer `request.form()` ile form <abbr title="HTTP isteği ile gelen string veriyi Python nesnesine çevirme.">dönüşümü</abbr> desteğini kullanacaksanız gereklidir.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - `SessionMiddleware` desteği için gerekli.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - `SchemaGenerator` desteği için gerekli (Muhtemelen FastAPI kullanırken ihtiyacınız olmaz).
|
||||
* <a href="https://graphene-python.org/" target="_blank"><code>graphene</code></a> - `GraphQLApp` desteği için gerekli.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - `UJSONResponse` kullanmak istiyorsan gerekli.
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - `UJSONResponse` kullanacaksanız gerekli.
|
||||
|
||||
Hem FastAPI hem de Starlette tarafından kullanılan:
|
||||
|
||||
* <a href="http://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - oluşturduğumuz uygulamayı bir web sunucusuna servis etmek için gerekli
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - `ORJSONResponse` kullanmak istiyor isen gerekli.
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - oluşturduğumuz uygulamayı servis edecek web sunucusu görevini üstlenir.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - `ORJSONResponse` kullanacaksanız gereklidir.
|
||||
|
||||
Bunların hepsini `pip install fastapi[all]` ile yükleyebilirsin.
|
||||
|
||||
## Lisans
|
||||
|
||||
Bu proje, MIT lisansı şartlarına göre lisanslanmıştır.
|
||||
Bu proje, MIT lisansı şartları altında lisanslanmıştır.
|
||||
|
||||
5
docs/tr/docs/newsletter.md
Normal file
5
docs/tr/docs/newsletter.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# FastAPI ve Arkadaşları Bülteni
|
||||
|
||||
<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>
|
||||
465
docs/uk/docs/index.md
Normal file
465
docs/uk/docs/index.md
Normal file
@@ -0,0 +1,465 @@
|
||||
<p align="center">
|
||||
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<em>Готовий до продакшину, високопродуктивний, простий у вивченні та швидкий для написання коду фреймворк</em>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/tiangolo/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
|
||||
<img src="https://github.com/tiangolo/fastapi/workflows/Test/badge.svg?event=push&branch=master" alt="Test">
|
||||
</a>
|
||||
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/tiangolo/fastapi" target="_blank">
|
||||
<img src="https://coverage-badge.samuelcolvin.workers.dev/tiangolo/fastapi.svg" alt="Coverage">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
|
||||
</a>
|
||||
<a href="https://pypi.org/project/fastapi" target="_blank">
|
||||
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
**Документація**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
|
||||
|
||||
**Програмний код**: <a href="https://github.com/tiangolo/fastapi" target="_blank">https://github.com/tiangolo/fastapi</a>
|
||||
|
||||
---
|
||||
|
||||
FastAPI - це сучасний, швидкий (високопродуктивний), вебфреймворк для створення API за допомогою Python 3.8+,в основі якого лежить стандартна анотація типів Python.
|
||||
|
||||
Ключові особливості:
|
||||
|
||||
* **Швидкий**: Дуже висока продуктивність, на рівні з **NodeJS** та **Go** (завдяки Starlette та Pydantic). [Один із найшвидших фреймворків](#performance).
|
||||
|
||||
* **Швидке написання коду**: Пришвидшує розробку функціоналу приблизно на 200%-300%. *
|
||||
* **Менше помилок**: Зменшить кількість помилок спричинених людиною (розробником) на 40%. *
|
||||
* **Інтуїтивний**: Чудова підтримка редакторами коду. <abbr title="Також відоме як auto-complete, autocompletion, IntelliSense.">Доповнення</abbr> всюди. Зменште час на налагодження.
|
||||
* **Простий**: Спроектований, для легкого використання та навчання. Знадобиться менше часу на читання документації.
|
||||
* **Короткий**: Зведе до мінімуму дублювання коду. Кожен оголошений параметр може виконувати кілька функцій.
|
||||
* **Надійний**: Ви матимете стабільний код готовий до продакшину з автоматичною інтерактивною документацією.
|
||||
* **Стандартизований**: Оснований та повністю сумісний з відкритими стандартами для API: <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (попередньо відомий як Swagger) та <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
|
||||
|
||||
<small>* оцінка на основі тестів внутрішньої команди розробників, створення продуктових застосунків.</small>
|
||||
|
||||
## Спонсори
|
||||
|
||||
<!-- sponsors -->
|
||||
|
||||
{% if sponsors %}
|
||||
{% for sponsor in sponsors.gold -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor -%}
|
||||
{%- for sponsor in sponsors.silver -%}
|
||||
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<!-- /sponsors -->
|
||||
|
||||
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Other sponsors</a>
|
||||
|
||||
## Враження
|
||||
|
||||
"_[...] I'm using **FastAPI** a ton these days. [...] I'm actually planning to use it for all of my team's **ML services at Microsoft**. Some of them are getting integrated into the core **Windows** product and some **Office** products._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/tiangolo/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_We adopted the **FastAPI** library to spawn a **REST** server that can be queried to obtain **predictions**. [for Ludwig]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_**Netflix** is pleased to announce the open-source release of our **crisis management** orchestration framework: **Dispatch**! [built with **FastAPI**]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_I’m over the moon excited about **FastAPI**. It’s so fun!_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://twitter.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted **Hug** to be - it's really inspiring to see someone build that._"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - <strong><a href="https://www.hug.rest/" target="_blank">Hug</a> creator</strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
"_If you're looking to learn one **modern framework** for building REST APIs, check out **FastAPI** [...] It's fast, easy to use and easy to learn [...]_"
|
||||
|
||||
"_We've switched over to **FastAPI** for our **APIs** [...] I think you'll like it [...]_"
|
||||
|
||||
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://twitter.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://twitter.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
|
||||
|
||||
---
|
||||
|
||||
## **Typer**, FastAPI CLI
|
||||
|
||||
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
|
||||
|
||||
Створюючи <abbr title="Command Line Interface">CLI</abbr> застосунок для використання в терміналі, замість веб-API зверніть увагу на <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
|
||||
|
||||
**Typer** є молодшим братом FastAPI. І це **FastAPI для CLI**. ⌨️ 🚀
|
||||
|
||||
## Вимоги
|
||||
|
||||
Python 3.8+
|
||||
|
||||
FastAPI стоїть на плечах гігантів:
|
||||
|
||||
* <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a> для web частини.
|
||||
* <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic</a> для частини даних.
|
||||
|
||||
## Вставновлення
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install fastapi
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
Вам також знадобиться сервер ASGI для продакшину, наприклад <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> або <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install uvicorn[standard]
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## Приклад
|
||||
|
||||
### Створіть
|
||||
|
||||
* Створіть файл `main.py` з:
|
||||
|
||||
```Python
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Або використайте <code>async def</code>...</summary>
|
||||
|
||||
Якщо ваш код використовує `async` / `await`, скористайтеся `async def`:
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
async def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
```
|
||||
|
||||
**Примітка**:
|
||||
|
||||
Стикнувшись з проблемами, не зайвим буде ознайомитися з розділом _"In a hurry?"_ про <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` та `await` у документації</a>.
|
||||
|
||||
</details>
|
||||
|
||||
### Запустіть
|
||||
|
||||
Запустіть server з:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
INFO: Started reloader process [28720]
|
||||
INFO: Started server process [28722]
|
||||
INFO: Waiting for application startup.
|
||||
INFO: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Про команди <code>uvicorn main:app --reload</code>...</summary>
|
||||
|
||||
Команда `uvicorn main:app` посилається на:
|
||||
|
||||
* `main`: файл `main.py` ("Модуль" Python).
|
||||
* `app`: об’єкт створений усередині `main.py` рядком `app = FastAPI()`.
|
||||
* `--reload`: перезапускає сервер після зміни коду. Використовуйте виключно для розробки.
|
||||
|
||||
</details>
|
||||
|
||||
### Перевірте
|
||||
|
||||
Відкрийте браузер та введіть адресу <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
|
||||
|
||||
Ви побачите у відповідь подібний JSON:
|
||||
|
||||
```JSON
|
||||
{"item_id": 5, "q": "somequery"}
|
||||
```
|
||||
|
||||
Ви вже створили API, який:
|
||||
|
||||
* Отримує HTTP запити за _шляхами_ `/` та `/items/{item_id}`.
|
||||
* Обидва _шляхи_ приймають `GET` <em>операції</em> (також відомі як HTTP _методи_).
|
||||
* _Шлях_ `/items/{item_id}` містить _параметр шляху_ `item_id` який має бути типу `int`.
|
||||
* _Шлях_ `/items/{item_id}` містить необовʼязковий `str` _параметр запиту_ `q`.
|
||||
|
||||
### Інтерактивні документації API
|
||||
|
||||
Перейдемо сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
Ви побачите автоматичну інтерактивну API документацію (створену завдяки <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
|
||||
|
||||

|
||||
|
||||
### Альтернативні документації API
|
||||
|
||||
Тепер перейдемо сюди <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
Ви побачите альтернативну автоматичну документацію (створену завдяки <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
|
||||
|
||||

|
||||
|
||||
## Приклад оновлення
|
||||
|
||||
Тепер модифікуйте файл `main.py`, щоб отримати вміст запиту `PUT`.
|
||||
|
||||
Оголошуйте вміст запиту за допомогою стандартних типів Python завдяки Pydantic.
|
||||
|
||||
```Python hl_lines="4 9-12 25-27"
|
||||
from typing import Union
|
||||
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
is_offer: Union[bool, None] = None
|
||||
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"Hello": "World"}
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def read_item(item_id: int, q: Union[str, None] = None):
|
||||
return {"item_id": item_id, "q": q}
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
def update_item(item_id: int, item: Item):
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
Сервер повинен автоматично перезавантажуватися (тому що Ви додали `--reload` до `uvicorn` команди вище).
|
||||
|
||||
### Оновлення інтерактивної API документації
|
||||
|
||||
Тепер перейдемо сюди <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
|
||||
|
||||
* Інтерактивна документація API буде автоматично оновлена, включаючи новий вміст:
|
||||
|
||||

|
||||
|
||||
* Натисніть кнопку "Try it out", це дозволить вам заповнити параметри та безпосередньо взаємодіяти з API:
|
||||
|
||||

|
||||
|
||||
* Потім натисніть кнопку "Execute", інтерфейс користувача зв'яжеться з вашим API, надішле параметри, у відповідь отримає результати та покаже їх на екрані:
|
||||
|
||||

|
||||
|
||||
### Оновлення альтернативної API документації
|
||||
|
||||
Зараз перейдемо <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
|
||||
|
||||
* Альтернативна документація також показуватиме новий параметр і вміст запиту:
|
||||
|
||||

|
||||
|
||||
### Підсумки
|
||||
|
||||
Таким чином, Ви **один раз** оголошуєте типи параметрів, тіла тощо, як параметри функції.
|
||||
|
||||
Ви робите це за допомогою стандартних сучасних типів Python.
|
||||
|
||||
Вам не потрібно вивчати новий синтаксис, методи чи класи конкретної бібліотеки тощо.
|
||||
|
||||
Використовуючи стандартний **Python 3.8+**.
|
||||
|
||||
Наприклад, для `int`:
|
||||
|
||||
```Python
|
||||
item_id: int
|
||||
```
|
||||
|
||||
або для більш складної моделі `Item`:
|
||||
|
||||
```Python
|
||||
item: Item
|
||||
```
|
||||
|
||||
...і з цим єдиним оголошенням Ви отримуєте:
|
||||
|
||||
* Підтримку редактора, включаючи:
|
||||
* Варіанти заповнення.
|
||||
* Перевірку типів.
|
||||
* Перевірку даних:
|
||||
* Автоматичні та зрозумілі помилки, у разі некоректних даних.
|
||||
* Перевірка навіть для JSON з високим рівнем вкладеності.
|
||||
* <abbr title="також відомий як: serialization, parsing, marshalling">Перетворення</abbr> вхідних даних: з мережі до даних і типів Python. Читання з:
|
||||
* JSON.
|
||||
* Параметрів шляху.
|
||||
* Параметрів запиту.
|
||||
* Cookies.
|
||||
* Headers.
|
||||
* Forms.
|
||||
* Файлів.
|
||||
* <abbr title="також відомий як: serialization, parsing, marshalling">Перетворення</abbr> вихідних даних: з типів і даних Python до мережевих даних (як JSON):
|
||||
* Конвертація Python типів (`str`, `int`, `float`, `bool`, `list`, тощо).
|
||||
* `datetime` об'єкти.
|
||||
* `UUID` об'єкти.
|
||||
* Моделі бази даних.
|
||||
* ...та багато іншого.
|
||||
* Автоматичну інтерактивну документацію API, включаючи 2 альтернативні інтерфейси користувача:
|
||||
* Swagger UI.
|
||||
* ReDoc.
|
||||
|
||||
---
|
||||
|
||||
Повертаючись до попереднього прикладу коду, **FastAPI**:
|
||||
|
||||
* Підтвердить наявність `item_id` у шляху для запитів `GET` та `PUT`.
|
||||
* Підтвердить, що `item_id` має тип `int` для запитів `GET` and `PUT`.
|
||||
* Якщо це не так, клієнт побачить корисну, зрозумілу помилку.
|
||||
* Перевірить, чи є необов'язковий параметр запиту з назвою `q` (а саме `http://127.0.0.1:8000/items/foo?q=somequery`) для запитів `GET`.
|
||||
* Оскільки параметр `q` оголошено як `= None`, він необов'язковий.
|
||||
* За відсутності `None` він був би обов'язковим (як і вміст у випадку з `PUT`).
|
||||
* Для запитів `PUT` із `/items/{item_id}`, читає вміст як JSON:
|
||||
* Перевірить, чи має обов'язковий атрибут `name` тип `str`.
|
||||
* Перевірить, чи має обов'язковий атрибут `price` тип `float`.
|
||||
* Перевірить, чи існує необов'язковий атрибут `is_offer` та чи має він тип `bool`.
|
||||
* Усе це також працюватиме для глибоко вкладених об'єктів JSON.
|
||||
* Автоматично конвертує із та в JSON.
|
||||
* Документує все за допомогою OpenAPI, який може бути використано в:
|
||||
* Інтерактивних системах документації.
|
||||
* Системах автоматичної генерації клієнтського коду для багатьох мов.
|
||||
* Надає безпосередньо 2 вебінтерфейси інтерактивної документації.
|
||||
|
||||
---
|
||||
|
||||
Ми лише трішки доторкнулися до коду, але Ви вже маєте уявлення про те, як все працює.
|
||||
|
||||
Спробуйте змінити рядок:
|
||||
|
||||
```Python
|
||||
return {"item_name": item.name, "item_id": item_id}
|
||||
```
|
||||
|
||||
...із:
|
||||
|
||||
```Python
|
||||
... "item_name": item.name ...
|
||||
```
|
||||
|
||||
...на:
|
||||
|
||||
```Python
|
||||
... "item_price": item.price ...
|
||||
```
|
||||
|
||||
...і побачите, як ваш редактор автоматично заповнюватиме атрибути та знатиме їхні типи:
|
||||
|
||||

|
||||
|
||||
Для більш повного ознайомлення з додатковими функціями, перегляньте <a href="https://fastapi.tiangolo.com/tutorial/">Туторіал - Посібник Користувача</a>.
|
||||
|
||||
**Spoiler alert**: туторіал - посібник користувача містить:
|
||||
|
||||
* Оголошення **параметрів** з інших місць як: **headers**, **cookies**, **form fields** та **files**.
|
||||
* Як встановити **перевірку обмежень** як `maximum_length` або `regex`.
|
||||
* Дуже потужна і проста у використанні система **<abbr title="також відома як: components, resources, providers, services, injectables">Ін'єкція Залежностей</abbr>**.
|
||||
* Безпека та автентифікація, включаючи підтримку **OAuth2** з **JWT tokens** та **HTTP Basic** автентифікацію.
|
||||
* Досконаліші (але однаково прості) техніки для оголошення **глибоко вкладених моделей JSON** (завдяки Pydantic).
|
||||
* Багато додаткових функцій (завдяки Starlette) як-от:
|
||||
* **WebSockets**
|
||||
* надзвичайно прості тести на основі HTTPX та `pytest`
|
||||
* **CORS**
|
||||
* **Cookie Sessions**
|
||||
* ...та більше.
|
||||
|
||||
## Продуктивність
|
||||
|
||||
Незалежні тести TechEmpower показують що застосунки **FastAPI**, які працюють під керуванням Uvicorn <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">є одними з найшвидших серед доступних фреймворків в Python</a>, поступаючись лише Starlette та Uvicorn (які внутрішньо використовуються в FastAPI). (*)
|
||||
|
||||
Щоб дізнатися більше про це, перегляньте розділ <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
|
||||
|
||||
## Необов'язкові залежності
|
||||
|
||||
Pydantic використовує:
|
||||
|
||||
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email_validator</code></a> - для валідації електронної пошти.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/pydantic_settings/" target="_blank"><code>pydantic-settings</code></a> - для управління налаштуваннями.
|
||||
* <a href="https://docs.pydantic.dev/latest/usage/types/extra_types/extra_types/" target="_blank"><code>pydantic-extra-types</code></a> - для додаткових типів, що можуть бути використані з Pydantic.
|
||||
|
||||
|
||||
Starlette використовує:
|
||||
|
||||
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Необхідно, якщо Ви хочете використовувати `TestClient`.
|
||||
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Необхідно, якщо Ви хочете використовувати шаблони як конфігурацію за замовчуванням.
|
||||
* <a href="https://andrew-d.github.io/python-multipart/" target="_blank"><code>python-multipart</code></a> - Необхідно, якщо Ви хочете підтримувати <abbr title="перетворення рядка, який надходить із запиту HTTP, на дані Python">"розбір"</abbr> форми за допомогою `request.form()`.
|
||||
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Необхідно для підтримки `SessionMiddleware`.
|
||||
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Необхідно для підтримки Starlette `SchemaGenerator` (ймовірно, вам це не потрібно з FastAPI).
|
||||
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Необхідно, якщо Ви хочете використовувати `UJSONResponse`.
|
||||
|
||||
FastAPI / Starlette використовують:
|
||||
|
||||
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - для сервера, який завантажує та обслуговує вашу програму.
|
||||
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Необхідно, якщо Ви хочете використовувати `ORJSONResponse`.
|
||||
|
||||
Ви можете встановити все це за допомогою `pip install fastapi[all]`.
|
||||
|
||||
## Ліцензія
|
||||
|
||||
Цей проєкт ліцензовано згідно з умовами ліцензії MIT.
|
||||
116
docs/uk/docs/tutorial/body-fields.md
Normal file
116
docs/uk/docs/tutorial/body-fields.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Тіло - Поля
|
||||
|
||||
Так само як ви можете визначати додаткову валідацію та метадані у параметрах *функції обробки шляху* за допомогою `Query`, `Path` та `Body`, ви можете визначати валідацію та метадані всередині моделей Pydantic за допомогою `Field` від Pydantic.
|
||||
|
||||
## Імпорт `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+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Варто користуватись `Annotated` версією, якщо це можливо.
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Варто користуватись `Annotated` версією, якщо це можливо.
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! warning
|
||||
Зверніть увагу, що `Field` імпортується прямо з `pydantic`, а не з `fastapi`, як всі інші (`Query`, `Path`, `Body` тощо).
|
||||
|
||||
## Оголошення атрибутів моделі
|
||||
|
||||
Ви можете використовувати `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+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Варто користуватись `Annotated` версією, якщо це можливо..
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ non-Annotated"
|
||||
|
||||
!!! tip
|
||||
Варто користуватись `Annotated` версією, якщо це можливо..
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
`Field` працює так само, як `Query`, `Path` і `Body`, у нього такі самі параметри тощо.
|
||||
|
||||
!!! note "Технічні деталі"
|
||||
Насправді, `Query`, `Path` та інші, що ви побачите далі, створюють об'єкти підкласів загального класу `Param`, котрий сам є підкласом класу `FieldInfo` з Pydantic.
|
||||
|
||||
І `Field` від Pydantic також повертає екземпляр `FieldInfo`.
|
||||
|
||||
`Body` також безпосередньо повертає об'єкти підкласу `FieldInfo`. І є інші підкласи, які ви побачите пізніше, що є підкласами класу Body.
|
||||
|
||||
Пам'ятайте, що коли ви імпортуєте 'Query', 'Path' та інше з 'fastapi', вони фактично є функціями, які повертають спеціальні класи.
|
||||
|
||||
!!! tip
|
||||
Зверніть увагу, що кожен атрибут моделі із типом, значенням за замовчуванням та `Field` має ту саму структуру, що й параметр *функції обробки шляху*, з `Field` замість `Path`, `Query` і `Body`.
|
||||
|
||||
## Додавання додаткової інформації
|
||||
|
||||
Ви можете визначити додаткову інформацію у `Field`, `Query`, `Body` тощо. І вона буде включена у згенеровану JSON схему.
|
||||
|
||||
Ви дізнаєтеся більше про додавання додаткової інформації пізніше у документації, коли вивчатимете визначення прикладів.
|
||||
|
||||
!!! warning
|
||||
Додаткові ключі, передані в `Field`, також будуть присутні у згенерованій схемі OpenAPI для вашого додатка.
|
||||
Оскільки ці ключі не обов'язково можуть бути частиною специфікації OpenAPI, деякі інструменти OpenAPI, наприклад, [OpenAPI валідатор](https://validator.swagger.io/), можуть не працювати з вашою згенерованою схемою.
|
||||
|
||||
## Підсумок
|
||||
|
||||
Ви можете використовувати `Field` з Pydantic для визначення додаткових перевірок та метаданих для атрибутів моделі.
|
||||
|
||||
Ви також можете використовувати додаткові іменовані аргументи для передачі додаткових метаданих JSON схеми.
|
||||
219
docs/zh/docs/advanced/additional-responses.md
Normal file
219
docs/zh/docs/advanced/additional-responses.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# OPENAPI 中的其他响应
|
||||
|
||||
您可以声明附加响应,包括附加状态代码、媒体类型、描述等。
|
||||
|
||||
这些额外的响应将包含在OpenAPI模式中,因此它们也将出现在API文档中。
|
||||
|
||||
但是对于那些额外的响应,你必须确保你直接返回一个像 `JSONResponse` 一样的 `Response` ,并包含你的状态代码和内容。
|
||||
|
||||
## `model`附加响应
|
||||
您可以向路径操作装饰器传递参数 `responses` 。
|
||||
|
||||
它接收一个 `dict`,键是每个响应的状态代码(如`200`),值是包含每个响应信息的其他 `dict`。
|
||||
|
||||
每个响应字典都可以有一个关键模型,其中包含一个 `Pydantic` 模型,就像 `response_model` 一样。
|
||||
|
||||
**FastAPI**将采用该模型,生成其`JSON Schema`并将其包含在`OpenAPI`中的正确位置。
|
||||
|
||||
例如,要声明另一个具有状态码 `404` 和`Pydantic`模型 `Message` 的响应,可以写:
|
||||
```Python hl_lines="18 22"
|
||||
{!../../../docs_src/additional_responses/tutorial001.py!}
|
||||
```
|
||||
|
||||
|
||||
!!! Note
|
||||
请记住,您必须直接返回 `JSONResponse` 。
|
||||
|
||||
!!! Info
|
||||
`model` 密钥不是OpenAPI的一部分。
|
||||
**FastAPI**将从那里获取`Pydantic`模型,生成` JSON Schema` ,并将其放在正确的位置。
|
||||
- 正确的位置是:
|
||||
- 在键 `content` 中,其具有另一个`JSON`对象( `dict` )作为值,该`JSON`对象包含:
|
||||
- 媒体类型的密钥,例如 `application/json` ,它包含另一个`JSON`对象作为值,该对象包含:
|
||||
- 一个键` schema` ,它的值是来自模型的`JSON Schema`,正确的位置在这里。
|
||||
- **FastAPI**在这里添加了对OpenAPI中另一个地方的全局JSON模式的引用,而不是直接包含它。这样,其他应用程序和客户端可以直接使用这些JSON模式,提供更好的代码生成工具等。
|
||||
|
||||
|
||||
**在OpenAPI中为该路径操作生成的响应将是:**
|
||||
|
||||
```json hl_lines="3-12"
|
||||
{
|
||||
"responses": {
|
||||
"404": {
|
||||
"description": "Additional Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Message"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Item"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
**模式被引用到OpenAPI模式中的另一个位置:**
|
||||
```json hl_lines="4-16"
|
||||
{
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Message": {
|
||||
"title": "Message",
|
||||
"required": [
|
||||
"message"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"title": "Message",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Item": {
|
||||
"title": "Item",
|
||||
"required": [
|
||||
"id",
|
||||
"value"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"title": "Id",
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"title": "Value",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ValidationError": {
|
||||
"title": "ValidationError",
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type"
|
||||
],
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"loc": {
|
||||
"title": "Location",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"msg": {
|
||||
"title": "Message",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"title": "Error Type",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"title": "HTTPValidationError",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"detail": {
|
||||
"title": "Detail",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
## 主响应的其他媒体类型
|
||||
|
||||
您可以使用相同的 `responses` 参数为相同的主响应添加不同的媒体类型。
|
||||
|
||||
例如,您可以添加一个额外的媒体类型` image/png` ,声明您的路径操作可以返回JSON对象(媒体类型 `application/json` )或PNG图像:
|
||||
|
||||
```Python hl_lines="19-24 28"
|
||||
{!../../../docs_src/additional_responses/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! Note
|
||||
- 请注意,您必须直接使用 `FileResponse` 返回图像。
|
||||
|
||||
!!! Info
|
||||
- 除非在 `responses` 参数中明确指定不同的媒体类型,否则**FastAPI**将假定响应与主响应类具有相同的媒体类型(默认为` application/json` )。
|
||||
- 但是如果您指定了一个自定义响应类,并将 `None `作为其媒体类型,**FastAPI**将使用 `application/json` 作为具有关联模型的任何其他响应。
|
||||
|
||||
## 组合信息
|
||||
您还可以联合接收来自多个位置的响应信息,包括 `response_model `、 `status_code` 和 `responses `参数。
|
||||
|
||||
您可以使用默认的状态码 `200` (或者您需要的自定义状态码)声明一个 `response_model `,然后直接在OpenAPI模式中在 `responses` 中声明相同响应的其他信息。
|
||||
|
||||
**FastAPI**将保留来自 `responses` 的附加信息,并将其与模型中的JSON Schema结合起来。
|
||||
|
||||
例如,您可以使用状态码 `404` 声明响应,该响应使用`Pydantic`模型并具有自定义的` description` 。
|
||||
|
||||
以及一个状态码为 `200` 的响应,它使用您的 `response_model` ,但包含自定义的 `example` :
|
||||
|
||||
```Python hl_lines="20-31"
|
||||
{!../../../docs_src/additional_responses/tutorial003.py!}
|
||||
```
|
||||
|
||||
所有这些都将被合并并包含在您的OpenAPI中,并在API文档中显示:
|
||||
|
||||
## 联合预定义响应和自定义响应
|
||||
|
||||
您可能希望有一些应用于许多路径操作的预定义响应,但是你想将不同的路径和自定义的相应组合在一块。
|
||||
对于这些情况,你可以使用Python的技术,将 `dict` 与 `**dict_to_unpack` 解包:
|
||||
```Python
|
||||
old_dict = {
|
||||
"old key": "old value",
|
||||
"second old key": "second old value",
|
||||
}
|
||||
new_dict = {**old_dict, "new key": "new value"}
|
||||
```
|
||||
|
||||
这里, new_dict 将包含来自 old_dict 的所有键值对加上新的键值对:
|
||||
```python
|
||||
{
|
||||
"old key": "old value",
|
||||
"second old key": "second old value",
|
||||
"new key": "new value",
|
||||
}
|
||||
```
|
||||
您可以使用该技术在路径操作中重用一些预定义的响应,并将它们与其他自定义响应相结合。
|
||||
**例如:**
|
||||
```Python hl_lines="13-17 26"
|
||||
{!../../../docs_src/additional_responses/tutorial004.py!}
|
||||
```
|
||||
## 有关OpenAPI响应的更多信息
|
||||
|
||||
要了解您可以在响应中包含哪些内容,您可以查看OpenAPI规范中的以下部分:
|
||||
+ [OpenAPI响应对象](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responsesObject),它包括 Response Object 。
|
||||
+ [OpenAPI响应对象](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responseObject),您可以直接在 `responses` 参数中的每个响应中包含任何内容。包括 `description` 、 `headers` 、 `content` (其中是声明不同的媒体类型和JSON Schemas)和 `links` 。
|
||||
17
docs/zh/docs/deployment/cloud.md
Normal file
17
docs/zh/docs/deployment/cloud.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# 在云上部署 FastAPI
|
||||
|
||||
您几乎可以使用**任何云服务商**来部署 FastAPI 应用程序。
|
||||
|
||||
在大多数情况下,主要的云服务商都有部署 FastAPI 的指南。
|
||||
|
||||
## 云服务商 - 赞助商
|
||||
|
||||
一些云服务商 ✨ [**赞助 FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨,这确保了FastAPI 及其**生态系统**持续健康地**发展**。
|
||||
|
||||
这表明了他们对 FastAPI 及其**社区**(您)的真正承诺,因为他们不仅想为您提供**良好的服务**,而且还想确保您拥有一个**良好且健康的框架**:FastAPI。 🙇
|
||||
|
||||
您可能想尝试他们的服务并阅读他们的指南:
|
||||
|
||||
* <a href="https://docs.platform.sh/languages/python.html?utm_source=fastapi-signup&utm_medium=banner&utm_campaign=FastAPI-signup-June-2023" class="external-link" target="_blank" >Platform.sh</a>
|
||||
* <a href="https://docs.porter.run/language-specific-guides/fastapi" class="external-link" target="_blank">Porter</a>
|
||||
* <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a>
|
||||
192
docs/zh/docs/deployment/https.md
Normal file
192
docs/zh/docs/deployment/https.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# 关于 HTTPS
|
||||
|
||||
人们很容易认为 HTTPS 仅仅是“启用”或“未启用”的东西。
|
||||
|
||||
但实际情况比这复杂得多。
|
||||
|
||||
!!!提示
|
||||
如果你很赶时间或不在乎,请继续阅读下一部分,下一部分会提供一个step-by-step的教程,告诉你怎么使用不同技术来把一切都配置好。
|
||||
|
||||
要从用户的视角**了解 HTTPS 的基础知识**,请查看 <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a>。
|
||||
|
||||
现在,从**开发人员的视角**,在了解 HTTPS 时需要记住以下几点:
|
||||
|
||||
* 要使用 HTTPS,**服务器**需要拥有由**第三方**生成的**"证书(certificate)"**。
|
||||
* 这些证书实际上是从第三方**获取**的,而不是“生成”的。
|
||||
* 证书有**生命周期**。
|
||||
* 它们会**过期**。
|
||||
* 然后它们需要**更新**,**再次从第三方获取**。
|
||||
* 连接的加密发生在 **TCP 层**。
|
||||
* 这是 HTTP 协议**下面的一层**。
|
||||
* 因此,**证书和加密**处理是在 **HTTP之前**完成的。
|
||||
* **TCP 不知道域名**。 仅仅知道 IP 地址。
|
||||
* 有关所请求的 **特定域名** 的信息位于 **HTTP 数据**中。
|
||||
* **HTTPS 证书**“证明”**某个域名**,但协议和加密发生在 TCP 层,在知道正在处理哪个域名**之前**。
|
||||
* **默认情况下**,这意味着你**每个 IP 地址只能拥有一个 HTTPS 证书**。
|
||||
* 无论你的服务器有多大,或者服务器上的每个应用程序有多小。
|
||||
* 不过,对此有一个**解决方案**。
|
||||
* **TLS** 协议(在 HTTP 之下的TCP 层处理加密的协议)有一个**扩展**,称为 **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="服务器名称指示">SNI</abbr></a>**。
|
||||
* SNI 扩展允许一台服务器(具有 **单个 IP 地址**)拥有 **多个 HTTPS 证书** 并提供 **多个 HTTPS 域名/应用程序**。
|
||||
* 为此,服务器上会有**单独**的一个组件(程序)侦听**公共 IP 地址**,这个组件必须拥有服务器中的**所有 HTTPS 证书**。
|
||||
* **获得安全连接后**,通信协议**仍然是HTTP**。
|
||||
* 内容是 **加密过的**,即使它们是通过 **HTTP 协议** 发送的。
|
||||
|
||||
通常的做法是在服务器上运行**一个程序/HTTP 服务器**并**管理所有 HTTPS 部分**:接收**加密的 HTTPS 请求**, 将 **解密的 HTTP 请求** 发送到在同一服务器中运行的实际 HTTP 应用程序(在本例中为 **FastAPI** 应用程序),从应用程序中获取 **HTTP 响应**, 使用适当的 **HTTPS 证书**对其进行加密并使用 **HTTPS** 将其发送回客户端。 此服务器通常被称为 **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS 终止代理(TLS Termination Proxy)</a>**。
|
||||
|
||||
你可以用作 TLS 终止代理的一些选项包括:
|
||||
|
||||
* Traefik(也可以处理证书更新)
|
||||
* Caddy(也可以处理证书更新)
|
||||
* Nginx
|
||||
* HAProxy
|
||||
|
||||
## Let's Encrypt
|
||||
|
||||
在 Let's Encrypt 之前,这些 **HTTPS 证书** 由受信任的第三方出售。
|
||||
|
||||
过去,获得这些证书的过程非常繁琐,需要大量的文书工作,而且证书非常昂贵。
|
||||
|
||||
但随后 **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>** 创建了。
|
||||
|
||||
它是 Linux 基金会的一个项目。 它以自动方式免费提供 **HTTPS 证书**。 这些证书可以使用所有符合标准的安全加密,并且有效期很短(大约 3 个月),因此**安全性实际上更好**,因为它们的生命周期缩短了。
|
||||
|
||||
域可以被安全地验证并自动生成证书。 这还允许自动更新这些证书。
|
||||
|
||||
我们的想法是自动获取和更新这些证书,以便你可以永远免费拥有**安全的 HTTPS**。
|
||||
|
||||
## 面向开发人员的 HTTPS
|
||||
|
||||
这里有一个 HTTPS API 看起来是什么样的示例,我们会分步说明,并且主要关注对开发人员重要的部分。
|
||||
|
||||
|
||||
### 域名
|
||||
|
||||
第一步我们要先**获取**一些**域名(Domain Name)**。 然后可以在 DNS 服务器(可能是你的同一家云服务商提供的)中配置它。
|
||||
|
||||
你可能拥有一个云服务器(虚拟机)或类似的东西,并且它会有一个<abbr title="That isn't Change">固定</abbr> **公共IP地址**。
|
||||
|
||||
在 DNS 服务器中,你可以配置一条记录(“A 记录”)以将 **你的域名** 指向你服务器的公共 **IP 地址**。
|
||||
|
||||
这个操作一般只需要在最开始执行一次。
|
||||
|
||||
!!! tip
|
||||
域名这部分发生在 HTTPS 之前,由于这一切都依赖于域名和 IP 地址,所以先在这里提一下。
|
||||
|
||||
### DNS
|
||||
|
||||
现在让我们关注真正的 HTTPS 部分。
|
||||
|
||||
首先,浏览器将通过 **DNS 服务器** 查询**域名的IP** 是什么,在本例中为 `someapp.example.com`。
|
||||
|
||||
DNS 服务器会告诉浏览器使用某个特定的 **IP 地址**。 这将是你在 DNS 服务器中为你的服务器配置的公共 IP 地址。
|
||||
|
||||
<img src="/img/deployment/https/https01.svg">
|
||||
|
||||
### TLS 握手开始
|
||||
|
||||
然后,浏览器将在**端口 443**(HTTPS 端口)上与该 IP 地址进行通信。
|
||||
|
||||
通信的第一部分只是建立客户端和服务器之间的连接并决定它们将使用的加密密钥等。
|
||||
|
||||
<img src="/img/deployment/https/https02.svg">
|
||||
|
||||
客户端和服务器之间建立 TLS 连接的过程称为 **TLS 握手**。
|
||||
|
||||
### 带有 SNI 扩展的 TLS
|
||||
|
||||
**服务器中只有一个进程**可以侦听特定 **IP 地址**的特定 **端口**。 可能有其他进程在同一 IP 地址的其他端口上侦听,但每个 IP 地址和端口组合只有一个进程。
|
||||
|
||||
TLS (HTTPS) 默认使用端口`443`。 这就是我们需要的端口。
|
||||
|
||||
由于只有一个进程可以监听此端口,因此监听端口的进程将是 **TLS 终止代理**。
|
||||
|
||||
TLS 终止代理可以访问一个或多个 **TLS 证书**(HTTPS 证书)。
|
||||
|
||||
使用上面讨论的 **SNI 扩展**,TLS 终止代理将检查应该用于此连接的可用 TLS (HTTPS) 证书,并使用与客户端期望的域名相匹配的证书。
|
||||
|
||||
在这种情况下,它将使用`someapp.example.com`的证书。
|
||||
|
||||
<img src="/img/deployment/https/https03.svg">
|
||||
|
||||
客户端已经**信任**生成该 TLS 证书的实体(在本例中为 Let's Encrypt,但我们稍后会看到),因此它可以**验证**该证书是否有效。
|
||||
|
||||
然后,通过使用证书,客户端和 TLS 终止代理 **决定如何加密** **TCP 通信** 的其余部分。 这就完成了 **TLS 握手** 部分。
|
||||
|
||||
此后,客户端和服务器就拥有了**加密的 TCP 连接**,这就是 TLS 提供的功能。 然后他们可以使用该连接来启动实际的 **HTTP 通信**。
|
||||
|
||||
这就是 **HTTPS**,它只是 **安全 TLS 连接** 内的普通 **HTTP**,而不是纯粹的(未加密的)TCP 连接。
|
||||
|
||||
!!! tip
|
||||
请注意,通信加密发生在 **TCP 层**,而不是 HTTP 层。
|
||||
|
||||
### HTTPS 请求
|
||||
|
||||
现在客户端和服务器(特别是浏览器和 TLS 终止代理)具有 **加密的 TCP 连接**,它们可以开始 **HTTP 通信**。
|
||||
|
||||
接下来,客户端发送一个 **HTTPS 请求**。 这其实只是一个通过 TLS 加密连接的 HTTP 请求。
|
||||
|
||||
<img src="/img/deployment/https/https04.svg">
|
||||
|
||||
### 解密请求
|
||||
|
||||
TLS 终止代理将使用协商好的加密算法**解密请求**,并将**(解密的)HTTP 请求**传输到运行应用程序的进程(例如运行 FastAPI 应用的 Uvicorn 进程)。
|
||||
|
||||
<img src="/img/deployment/https/https05.svg">
|
||||
|
||||
### HTTP 响应
|
||||
|
||||
应用程序将处理请求并向 TLS 终止代理发送**(未加密)HTTP 响应**。
|
||||
|
||||
<img src="/img/deployment/https/https06.svg">
|
||||
|
||||
### HTTPS 响应
|
||||
|
||||
然后,TLS 终止代理将使用之前协商的加密算法(以`someapp.example.com`的证书开头)对响应进行加密,并将其发送回浏览器。
|
||||
|
||||
接下来,浏览器将验证响应是否有效和是否使用了正确的加密密钥等。然后它会**解密响应**并处理它。
|
||||
|
||||
<img src="/img/deployment/https/https07.svg">
|
||||
|
||||
客户端(浏览器)将知道响应来自正确的服务器,因为它使用了他们之前使用 **HTTPS 证书** 协商出的加密算法。
|
||||
|
||||
### 多个应用程序
|
||||
|
||||
在同一台(或多台)服务器中,可能存在**多个应用程序**,例如其他 API 程序或数据库。
|
||||
|
||||
只有一个进程可以处理特定的 IP 和端口(在我们的示例中为 TLS 终止代理),但其他应用程序/进程也可以在服务器上运行,只要它们不尝试使用相同的 **公共 IP 和端口的组合**。
|
||||
|
||||
<img src="/img/deployment/https/https08.svg">
|
||||
|
||||
这样,TLS 终止代理就可以为多个应用程序处理**多个域名**的 HTTPS 和证书,然后在每种情况下将请求传输到正确的应用程序。
|
||||
|
||||
### 证书更新
|
||||
|
||||
在未来的某个时候,每个证书都会**过期**(大约在获得证书后 3 个月)。
|
||||
|
||||
然后,会有另一个程序(在某些情况下是另一个程序,在某些情况下可能是同一个 TLS 终止代理)与 Let's Encrypt 通信并更新证书。
|
||||
|
||||
<img src="/img/deployment/https/https.svg">
|
||||
|
||||
**TLS 证书** **与域名相关联**,而不是与 IP 地址相关联。
|
||||
|
||||
因此,要更新证书,更新程序需要向权威机构(Let's Encrypt)**证明**它确实**“拥有”并控制该域名**。
|
||||
|
||||
有多种方法可以做到这一点。 一些流行的方式是:
|
||||
|
||||
* **修改一些DNS记录**。
|
||||
* 为此,续订程序需要支持 DNS 提供商的 API,因此,要看你使用的 DNS 提供商是否提供这一功能。
|
||||
* **在与域名关联的公共 IP 地址上作为服务器运行**(至少在证书获取过程中)。
|
||||
* 正如我们上面所说,只有一个进程可以监听特定的 IP 和端口。
|
||||
* 这就是当同一个 TLS 终止代理还负责证书续订过程时它非常有用的原因之一。
|
||||
* 否则,你可能需要暂时停止 TLS 终止代理,启动续订程序以获取证书,然后使用 TLS 终止代理配置它们,然后重新启动 TLS 终止代理。 这并不理想,因为你的应用程序在 TLS 终止代理关闭期间将不可用。
|
||||
|
||||
通过拥有一个**单独的系统来使用 TLS 终止代理来处理 HTTPS**, 而不是直接将 TLS 证书与应用程序服务器一起使用 (例如 Uvicorn),你可以在
|
||||
更新证书的过程中同时保持提供服务。
|
||||
|
||||
## 回顾
|
||||
|
||||
拥有**HTTPS** 非常重要,并且在大多数情况下相当**关键**。 作为开发人员,你围绕 HTTPS 所做的大部分努力就是**理解这些概念**以及它们的工作原理。
|
||||
|
||||
一旦你了解了**面向开发人员的 HTTPS** 的基础知识,你就可以轻松组合和配置不同的工具,以帮助你以简单的方式管理一切。
|
||||
|
||||
在接下来的一些章节中,我将向你展示几个为 **FastAPI** 应用程序设置 **HTTPS** 的具体示例。 🔒
|
||||
21
docs/zh/docs/deployment/index.md
Normal file
21
docs/zh/docs/deployment/index.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 部署
|
||||
|
||||
部署 **FastAPI** 应用程序相对容易。
|
||||
|
||||
## 部署是什么意思
|
||||
|
||||
**部署**应用程序意味着执行必要的步骤以使其**可供用户使用**。
|
||||
|
||||
对于**Web API**来说,通常涉及将上传到**云服务器**中,搭配一个性能和稳定性都不错的**服务器程序**,以便你的**用户**可以高效地**访问**你的应用程序,而不会出现中断或其他问题。
|
||||
|
||||
这与**开发**阶段形成鲜明对比,在**开发**阶段,你不断更改代码、破坏代码、修复代码, 来回停止和重启服务器等。
|
||||
|
||||
## 部署策略
|
||||
|
||||
根据你的使用场景和使用的工具,有多种方法可以实现此目的。
|
||||
|
||||
你可以使用一些工具自行**部署服务器**,你也可以使用能为你完成部分工作的**云服务**,或其他可能的选项。
|
||||
|
||||
我将向你展示在部署 **FastAPI** 应用程序时你可能应该记住的一些主要概念(尽管其中大部分适用于任何其他类型的 Web 应用程序)。
|
||||
|
||||
在接下来的部分中,你将看到更多需要记住的细节以及一些技巧。 ✨
|
||||
148
docs/zh/docs/deployment/manually.md
Normal file
148
docs/zh/docs/deployment/manually.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# 手动运行服务器 - Uvicorn
|
||||
|
||||
在远程服务器计算机上运行 **FastAPI** 应用程序所需的主要东西是 ASGI 服务器程序,例如 **Uvicorn**。
|
||||
|
||||
有 3 个主要可选方案:
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>:高性能 ASGI 服务器。
|
||||
* <a href="https://pgjones.gitlab.io/hypercorn/" class="external-link" target="_blank">Hypercorn</a>:与 HTTP/2 和 Trio 等兼容的 ASGI 服务器。
|
||||
* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a>:为 Django Channels 构建的 ASGI 服务器。
|
||||
|
||||
## 服务器主机和服务器程序
|
||||
|
||||
关于名称,有一个小细节需要记住。 💡
|
||||
|
||||
“**服务器**”一词通常用于指远程/云计算机(物理机或虚拟机)以及在该计算机上运行的程序(例如 Uvicorn)。
|
||||
|
||||
请记住,当您一般读到“服务器”这个名词时,它可能指的是这两者之一。
|
||||
|
||||
当提到远程主机时,通常将其称为**服务器**,但也称为**机器**(machine)、**VM**(虚拟机)、**节点**。 这些都是指某种类型的远程计算机,通常运行 Linux,您可以在其中运行程序。
|
||||
|
||||
|
||||
## 安装服务器程序
|
||||
|
||||
您可以使用以下命令安装 ASGI 兼容服务器:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>,一个快如闪电 ASGI 服务器,基于 uvloop 和 httptools 构建。
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! tip
|
||||
通过添加`standard`,Uvicorn 将安装并使用一些推荐的额外依赖项。
|
||||
|
||||
其中包括`uvloop`,它是`asyncio`的高性能替代品,它提供了巨大的并发性能提升。
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
* <a href="https://gitlab.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>,一个也与 HTTP/2 兼容的 ASGI 服务器。
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...或任何其他 ASGI 服务器。
|
||||
|
||||
|
||||
## 运行服务器程序
|
||||
|
||||
您可以按照之前教程中的相同方式运行应用程序,但不使用`--reload`选项,例如:
|
||||
|
||||
=== "Uvicorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 80
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
=== "Hypercorn"
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
!!! warning
|
||||
如果您正在使用`--reload`选项,请记住删除它。
|
||||
|
||||
`--reload` 选项消耗更多资源,并且更不稳定。
|
||||
|
||||
它在**开发**期间有很大帮助,但您**不应该**在**生产环境**中使用它。
|
||||
|
||||
## Hypercorn with Trio
|
||||
|
||||
Starlette 和 **FastAPI** 基于 <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a>, 所以它们才能同时与 Python 的标准库 <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a> 和<a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a> 兼容。
|
||||
|
||||
尽管如此,Uvicorn 目前仅与 asyncio 兼容,并且通常使用 <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a >, 它是`asyncio`的高性能替代品。
|
||||
|
||||
但如果你想直接使用**Trio**,那么你可以使用**Hypercorn**,因为它支持它。 ✨
|
||||
|
||||
### 安装具有 Trio 的 Hypercorn
|
||||
|
||||
首先,您需要安装具有 Trio 支持的 Hypercorn:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "hypercorn[trio]"
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Run with Trio
|
||||
|
||||
然后你可以传递值`trio`给命令行选项`--worker-class`:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --worker-class trio
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
这将通过您的应用程序启动 Hypercorn,并使用 Trio 作为后端。
|
||||
|
||||
现在您可以在应用程序内部使用 Trio。 或者更好的是,您可以使用 AnyIO,使您的代码与 Trio 和 asyncio 兼容。 🎉
|
||||
|
||||
## 部署概念
|
||||
|
||||
这些示例运行服务器程序(例如 Uvicorn),启动**单个进程**,在所有 IP(`0.0.0.0`)上监听预定义端口(例如`80`)。
|
||||
|
||||
这是基本思路。 但您可能需要处理一些其他事情,例如:
|
||||
|
||||
* 安全性 - HTTPS
|
||||
* 启动时运行
|
||||
* 重新启动
|
||||
* Replication(运行的进程数)
|
||||
* 内存
|
||||
* 开始前的步骤
|
||||
|
||||
在接下来的章节中,我将向您详细介绍每个概念、如何思考它们,以及一些具体示例以及处理它们的策略。 🚀
|
||||
184
docs/zh/docs/deployment/server-workers.md
Normal file
184
docs/zh/docs/deployment/server-workers.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Server Workers - Gunicorn with Uvicorn
|
||||
|
||||
让我们回顾一下之前的部署概念:
|
||||
|
||||
* 安全性 - HTTPS
|
||||
* 启动时运行
|
||||
* 重新启动
|
||||
* **复制(运行的进程数)**
|
||||
* 内存
|
||||
* 启动前的先前步骤
|
||||
|
||||
到目前为止,通过文档中的所有教程,您可能已经在**单个进程**上运行了像 Uvicorn 这样的**服务器程序**。
|
||||
|
||||
部署应用程序时,您可能希望进行一些**进程复制**,以利用**多核**并能够处理更多请求。
|
||||
|
||||
正如您在上一章有关[部署概念](./concepts.md){.internal-link target=_blank}中看到的,您可以使用多种策略。
|
||||
|
||||
在这里我将向您展示如何将 <a href="https://gunicorn.org/" class="external-link" target="_blank">**Gunicorn**</a> 与 **Uvicorn worker 进程** 一起使用。
|
||||
|
||||
!!! info
|
||||
如果您正在使用容器,例如 Docker 或 Kubernetes,我将在下一章中告诉您更多相关信息:[容器中的 FastAPI - Docker](./docker.md){.internal-link target=_blank}。
|
||||
|
||||
特别是,当在 **Kubernetes** 上运行时,您可能**不想**使用 Gunicorn,而是运行 **每个容器一个 Uvicorn 进程**,但我将在本章后面告诉您这一点。
|
||||
|
||||
|
||||
|
||||
## Gunicorn with Uvicorn Workers
|
||||
|
||||
**Gunicorn**主要是一个使用**WSGI标准**的应用服务器。 这意味着 Gunicorn 可以为 Flask 和 Django 等应用程序提供服务。 Gunicorn 本身与 **FastAPI** 不兼容,因为 FastAPI 使用最新的 **<a href="https://asgi.readthedocs.io/en/latest/" class="external-link" target=" _blank">ASGI 标准</a>**。
|
||||
|
||||
但 Gunicorn 支持充当 **进程管理器** 并允许用户告诉它要使用哪个特定的 **worker类**。 然后 Gunicorn 将使用该类启动一个或多个 **worker进程**。
|
||||
|
||||
**Uvicorn** 有一个 Gunicorn 兼容的worker类。
|
||||
|
||||
使用这种组合,Gunicorn 将充当 **进程管理器**,监听 **端口** 和 **IP**。 它会将通信**传输**到运行**Uvicorn类**的worker进程。
|
||||
|
||||
然后与Gunicorn兼容的**Uvicorn worker**类将负责将Gunicorn发送的数据转换为ASGI标准以供FastAPI使用。
|
||||
|
||||
## 安装 Gunicorn 和 Uvicorn
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]" gunicorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
这将安装带有`standard`扩展包(以获得高性能)的 Uvicorn 和 Gunicorn。
|
||||
|
||||
## Run Gunicorn with Uvicorn Workers
|
||||
|
||||
接下来你可以通过以下命令运行Gunicorn:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:80
|
||||
|
||||
[19499] [INFO] Starting gunicorn 20.1.0
|
||||
[19499] [INFO] Listening at: http://0.0.0.0:80 (19499)
|
||||
[19499] [INFO] Using worker: uvicorn.workers.UvicornWorker
|
||||
[19511] [INFO] Booting worker with pid: 19511
|
||||
[19513] [INFO] Booting worker with pid: 19513
|
||||
[19514] [INFO] Booting worker with pid: 19514
|
||||
[19515] [INFO] Booting worker with pid: 19515
|
||||
[19511] [INFO] Started server process [19511]
|
||||
[19511] [INFO] Waiting for application startup.
|
||||
[19511] [INFO] Application startup complete.
|
||||
[19513] [INFO] Started server process [19513]
|
||||
[19513] [INFO] Waiting for application startup.
|
||||
[19513] [INFO] Application startup complete.
|
||||
[19514] [INFO] Started server process [19514]
|
||||
[19514] [INFO] Waiting for application startup.
|
||||
[19514] [INFO] Application startup complete.
|
||||
[19515] [INFO] Started server process [19515]
|
||||
[19515] [INFO] Waiting for application startup.
|
||||
[19515] [INFO] Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
让我们看看每个选项的含义:
|
||||
|
||||
* `main:app`:这与 Uvicorn 使用的语法相同,`main` 表示名为"`main`"的 Python 模块,因此是文件 `main.py`。 `app` 是 **FastAPI** 应用程序的变量名称。
|
||||
* 你可以想象 `main:app` 相当于一个 Python `import` 语句,例如:
|
||||
|
||||
```Python
|
||||
from main import app
|
||||
```
|
||||
|
||||
* 因此,`main:app` 中的冒号相当于 `from main import app` 中的 Python `import` 部分。
|
||||
|
||||
* `--workers`:要使用的worker进程数量,每个进程将运行一个 Uvicorn worker进程,在本例中为 4 个worker进程。
|
||||
|
||||
* `--worker-class`:在worker进程中使用的与 Gunicorn 兼容的工作类。
|
||||
* 这里我们传递了 Gunicorn 可以导入和使用的类:
|
||||
|
||||
```Python
|
||||
import uvicorn.workers.UvicornWorker
|
||||
```
|
||||
|
||||
* `--bind`:这告诉 Gunicorn 要监听的 IP 和端口,使用冒号 (`:`) 分隔 IP 和端口。
|
||||
* 如果您直接运行 Uvicorn,则可以使用`--host 0.0.0.0`和`--port 80`,而不是`--bind 0.0.0.0:80`(Gunicorn 选项)。
|
||||
|
||||
|
||||
在输出中,您可以看到它显示了每个进程的 **PID**(进程 ID)(它只是一个数字)。
|
||||
|
||||
你可以看到:
|
||||
|
||||
* Gunicorn **进程管理器** 以 PID `19499` 开头(在您的情况下,它将是一个不同的数字)。
|
||||
* 然后它开始`Listening at: http://0.0.0.0:80`。
|
||||
* 然后它检测到它必须使用 `uvicorn.workers.UvicornWorker` 处的worker类。
|
||||
* 然后它启动**4个worker**,每个都有自己的PID:`19511`、`19513`、`19514`和`19515`。
|
||||
|
||||
Gunicorn 还将负责管理**死进程**和**重新启动**新进程(如果需要保持worker数量)。 因此,这在一定程度上有助于上面列表中**重启**的概念。
|
||||
|
||||
尽管如此,您可能还希望有一些外部的东西,以确保在必要时**重新启动 Gunicorn**,并且**在启动时运行它**等。
|
||||
|
||||
## Uvicorn with Workers
|
||||
|
||||
Uvicorn 也有一个选项可以启动和运行多个 **worker进程**。
|
||||
|
||||
然而,到目前为止,Uvicorn 处理worker进程的能力比 Gunicorn 更有限。 因此,如果您想拥有这个级别(Python 级别)的进程管理器,那么最好尝试使用 Gunicorn 作为进程管理器。
|
||||
|
||||
无论如何,您都可以像这样运行它:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
|
||||
<font color="#A6E22E">INFO</font>: Uvicorn running on <b>http://0.0.0.0:8080</b> (Press CTRL+C to quit)
|
||||
<font color="#A6E22E">INFO</font>: Started parent process [<font color="#A1EFE4"><b>27365</b></font>]
|
||||
<font color="#A6E22E">INFO</font>: Started server process [<font color="#A1EFE4">27368</font>]
|
||||
<font color="#A6E22E">INFO</font>: Waiting for application startup.
|
||||
<font color="#A6E22E">INFO</font>: Application startup complete.
|
||||
<font color="#A6E22E">INFO</font>: Started server process [<font color="#A1EFE4">27369</font>]
|
||||
<font color="#A6E22E">INFO</font>: Waiting for application startup.
|
||||
<font color="#A6E22E">INFO</font>: Application startup complete.
|
||||
<font color="#A6E22E">INFO</font>: Started server process [<font color="#A1EFE4">27370</font>]
|
||||
<font color="#A6E22E">INFO</font>: Waiting for application startup.
|
||||
<font color="#A6E22E">INFO</font>: Application startup complete.
|
||||
<font color="#A6E22E">INFO</font>: Started server process [<font color="#A1EFE4">27367</font>]
|
||||
<font color="#A6E22E">INFO</font>: Waiting for application startup.
|
||||
<font color="#A6E22E">INFO</font>: Application startup complete.
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
这里唯一的新选项是 `--workers` 告诉 Uvicorn 启动 4 个工作进程。
|
||||
|
||||
您还可以看到它显示了每个进程的 **PID**,父进程(这是 **进程管理器**)的 PID 为`27365`,每个工作进程的 PID 为:`27368`、`27369`, `27370`和`27367`。
|
||||
|
||||
## 部署概念
|
||||
|
||||
在这里,您了解了如何使用 **Gunicorn**(或 Uvicorn)管理 **Uvicorn 工作进程**来**并行**应用程序的执行,利用 CPU 中的 **多核**,并 能够满足**更多请求**。
|
||||
|
||||
从上面的部署概念列表来看,使用worker主要有助于**复制**部分,并对**重新启动**有一点帮助,但您仍然需要照顾其他部分:
|
||||
|
||||
* **安全 - HTTPS**
|
||||
* **启动时运行**
|
||||
* ***重新启动***
|
||||
* 复制(运行的进程数)
|
||||
* **内存**
|
||||
* **启动之前的先前步骤**
|
||||
|
||||
## 容器和 Docker
|
||||
|
||||
在关于 [容器中的 FastAPI - Docker](./docker.md){.internal-link target=_blank} 的下一章中,我将介绍一些可用于处理其他 **部署概念** 的策略。
|
||||
|
||||
我还将向您展示 **官方 Docker 镜像**,其中包括 **Gunicorn 和 Uvicorn worker** 以及一些对简单情况有用的默认配置。
|
||||
|
||||
在那里,我还将向您展示如何 **从头开始构建自己的镜像** 以运行单个 Uvicorn 进程(没有 Gunicorn)。 这是一个简单的过程,并且可能是您在使用像 **Kubernetes** 这样的分布式容器管理系统时想要做的事情。
|
||||
|
||||
## 回顾
|
||||
|
||||
您可以使用**Gunicorn**(或Uvicorn)作为Uvicorn工作进程的进程管理器,以利用**多核CPU**,**并行运行多个进程**。
|
||||
|
||||
如果您要设置**自己的部署系统**,同时自己处理其他部署概念,则可以使用这些工具和想法。
|
||||
|
||||
请查看下一章,了解带有容器(例如 Docker 和 Kubernetes)的 **FastAPI**。 您将看到这些工具也有简单的方法来解决其他**部署概念**。 ✨
|
||||
5
docs/zh/docs/learn/index.md
Normal file
5
docs/zh/docs/learn/index.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# 学习
|
||||
|
||||
以下是学习 **FastAPI** 的介绍部分和教程。
|
||||
|
||||
您可以认为这是一本 **书**,一门 **课程**,是 **官方** 且推荐的学习FastAPI的方法。😎
|
||||
@@ -78,9 +78,23 @@ ORM 具有在代码和数据库表(“*关系型”)中的**对象**之间
|
||||
|
||||
现在让我们看看每个文件/模块的作用。
|
||||
|
||||
## 安装 SQLAlchemy
|
||||
|
||||
先下载`SQLAlchemy`所需要的依赖:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install sqlalchemy
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
## 创建 SQLAlchemy 部件
|
||||
|
||||
让我们涉及到文件`sql_app/database.py`。
|
||||
让我们转到文件`sql_app/database.py`。
|
||||
|
||||
### 导入 SQLAlchemy 部件
|
||||
|
||||
|
||||
@@ -33,6 +33,6 @@ async def create_item(item: Item, x_token: str = Header()):
|
||||
if x_token != fake_secret_token:
|
||||
raise HTTPException(status_code=400, detail="Invalid X-Token header")
|
||||
if item.id in fake_db:
|
||||
raise HTTPException(status_code=400, detail="Item already exists")
|
||||
raise HTTPException(status_code=409, detail="Item already exists")
|
||||
fake_db[item.id] = item
|
||||
return item
|
||||
|
||||
@@ -61,5 +61,5 @@ def test_create_existing_item():
|
||||
"description": "There goes my stealer",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert response.status_code == 409
|
||||
assert response.json() == {"detail": "Item already exists"}
|
||||
|
||||
@@ -31,6 +31,6 @@ async def create_item(item: Item, x_token: str = Header()):
|
||||
if x_token != fake_secret_token:
|
||||
raise HTTPException(status_code=400, detail="Invalid X-Token header")
|
||||
if item.id in fake_db:
|
||||
raise HTTPException(status_code=400, detail="Item already exists")
|
||||
raise HTTPException(status_code=409, detail="Item already exists")
|
||||
fake_db[item.id] = item
|
||||
return item
|
||||
|
||||
@@ -61,5 +61,5 @@ def test_create_existing_item():
|
||||
"description": "There goes my stealer",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
assert response.status_code == 409
|
||||
assert response.json() == {"detail": "Item already exists"}
|
||||
|
||||
@@ -15,5 +15,5 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
async def create_item(item_id: int, item: Item):
|
||||
async def update_item(item_id: int, item: Item):
|
||||
return {"item_id": item_id, **item.dict()}
|
||||
|
||||
@@ -13,5 +13,5 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
async def create_item(item_id: int, item: Item):
|
||||
async def update_item(item_id: int, item: Item):
|
||||
return {"item_id": item_id, **item.dict()}
|
||||
|
||||
@@ -15,7 +15,7 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
async def create_item(item_id: int, item: Item, q: Union[str, None] = None):
|
||||
async def update_item(item_id: int, item: Item, q: Union[str, None] = None):
|
||||
result = {"item_id": item_id, **item.dict()}
|
||||
if q:
|
||||
result.update({"q": q})
|
||||
|
||||
@@ -13,7 +13,7 @@ app = FastAPI()
|
||||
|
||||
|
||||
@app.put("/items/{item_id}")
|
||||
async def create_item(item_id: int, item: Item, q: str | None = None):
|
||||
async def update_item(item_id: int, item: Item, q: str | None = None):
|
||||
result = {"item_id": item_id, **item.dict()}
|
||||
if q:
|
||||
result.update({"q": q})
|
||||
|
||||
30
docs_src/dependencies/tutorial008b.py
Normal file
30
docs_src/dependencies/tutorial008b.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
data = {
|
||||
"plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
|
||||
"portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
|
||||
}
|
||||
|
||||
|
||||
class OwnerError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except OwnerError as e:
|
||||
raise HTTPException(status_code=400, detail=f"Owner error: {e}")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: str = Depends(get_username)):
|
||||
if item_id not in data:
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
item = data[item_id]
|
||||
if item["owner"] != username:
|
||||
raise OwnerError(username)
|
||||
return item
|
||||
31
docs_src/dependencies/tutorial008b_an.py
Normal file
31
docs_src/dependencies/tutorial008b_an.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
data = {
|
||||
"plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
|
||||
"portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
|
||||
}
|
||||
|
||||
|
||||
class OwnerError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except OwnerError as e:
|
||||
raise HTTPException(status_code=400, detail=f"Owner error: {e}")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id not in data:
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
item = data[item_id]
|
||||
if item["owner"] != username:
|
||||
raise OwnerError(username)
|
||||
return item
|
||||
32
docs_src/dependencies/tutorial008b_an_py39.py
Normal file
32
docs_src/dependencies/tutorial008b_an_py39.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
data = {
|
||||
"plumbus": {"description": "Freshly pickled plumbus", "owner": "Morty"},
|
||||
"portal-gun": {"description": "Gun to create portals", "owner": "Rick"},
|
||||
}
|
||||
|
||||
|
||||
class OwnerError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_username():
|
||||
try:
|
||||
yield "Rick"
|
||||
except OwnerError as e:
|
||||
raise HTTPException(status_code=400, detail=f"Owner error: {e}")
|
||||
|
||||
|
||||
@app.get("/items/{item_id}")
|
||||
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
|
||||
if item_id not in data:
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
item = data[item_id]
|
||||
if item["owner"] != username:
|
||||
raise OwnerError(username)
|
||||
return item
|
||||
29
docs_src/generate_clients/tutorial004.js
Normal file
29
docs_src/generate_clients/tutorial004.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import * as fs from "fs";
|
||||
|
||||
const filePath = "./openapi.json";
|
||||
|
||||
fs.readFile(filePath, (err, data) => {
|
||||
const openapiContent = JSON.parse(data);
|
||||
if (err) throw err;
|
||||
|
||||
const paths = openapiContent.paths;
|
||||
|
||||
Object.keys(paths).forEach((pathKey) => {
|
||||
const pathData = paths[pathKey];
|
||||
Object.keys(pathData).forEach((method) => {
|
||||
const operation = pathData[method];
|
||||
if (operation.tags && operation.tags.length > 0) {
|
||||
const tag = operation.tags[0];
|
||||
const operationId = operation.operationId;
|
||||
const toRemove = `${tag}-`;
|
||||
if (operationId.startsWith(toRemove)) {
|
||||
const newOperationId = operationId.substring(toRemove.length);
|
||||
operation.operationId = newOperationId;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
fs.writeFile(filePath, JSON.stringify(openapiContent, null, 2), (err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
@@ -78,9 +78,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
@@ -79,9 +79,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
@@ -78,9 +78,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Annotated, Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
@@ -78,9 +78,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
@@ -77,9 +77,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import List, Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
@@ -93,9 +93,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import List, Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
@@ -94,9 +94,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
@@ -93,9 +93,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Annotated, List, Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
@@ -93,9 +93,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
from fastapi.security import (
|
||||
@@ -92,9 +92,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: timedelta | None = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Security, status
|
||||
@@ -93,9 +93,9 @@ def authenticate_user(fake_db, username: str, password: str):
|
||||
def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None):
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
expire = datetime.now(timezone.utc) + expires_delta
|
||||
else:
|
||||
expire = datetime.utcnow() + timedelta(minutes=15)
|
||||
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
|
||||
to_encode.update({"exp": expire})
|
||||
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
return encoded_jwt
|
||||
|
||||
@@ -22,7 +22,7 @@ def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
|
||||
if not (is_correct_username and is_correct_password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect email or password",
|
||||
detail="Incorrect username or password",
|
||||
headers={"WWW-Authenticate": "Basic"},
|
||||
)
|
||||
return credentials.username
|
||||
|
||||
@@ -25,7 +25,7 @@ def get_current_username(
|
||||
if not (is_correct_username and is_correct_password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect email or password",
|
||||
detail="Incorrect username or password",
|
||||
headers={"WWW-Authenticate": "Basic"},
|
||||
)
|
||||
return credentials.username
|
||||
|
||||
@@ -25,7 +25,7 @@ def get_current_username(
|
||||
if not (is_correct_username and is_correct_password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect email or password",
|
||||
detail="Incorrect username or password",
|
||||
headers={"WWW-Authenticate": "Basic"},
|
||||
)
|
||||
return credentials.username
|
||||
|
||||
@@ -7,7 +7,7 @@ from .database import Base
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
id = Column(Integer, primary_key=True)
|
||||
email = Column(String, unique=True, index=True)
|
||||
hashed_password = Column(String)
|
||||
is_active = Column(Boolean, default=True)
|
||||
@@ -18,7 +18,7 @@ class User(Base):
|
||||
class Item(Base):
|
||||
__tablename__ = "items"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
id = Column(Integer, primary_key=True)
|
||||
title = Column(String, index=True)
|
||||
description = Column(String, index=True)
|
||||
owner_id = Column(Integer, ForeignKey("users.id"))
|
||||
|
||||
@@ -7,7 +7,7 @@ from .database import Base
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
id = Column(Integer, primary_key=True)
|
||||
email = Column(String, unique=True, index=True)
|
||||
hashed_password = Column(String)
|
||||
is_active = Column(Boolean, default=True)
|
||||
@@ -18,7 +18,7 @@ class User(Base):
|
||||
class Item(Base):
|
||||
__tablename__ = "items"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
id = Column(Integer, primary_key=True)
|
||||
title = Column(String, index=True)
|
||||
description = Column(String, index=True)
|
||||
owner_id = Column(Integer, ForeignKey("users.id"))
|
||||
|
||||
@@ -7,7 +7,7 @@ from .database import Base
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
id = Column(Integer, primary_key=True)
|
||||
email = Column(String, unique=True, index=True)
|
||||
hashed_password = Column(String)
|
||||
is_active = Column(Boolean, default=True)
|
||||
@@ -18,7 +18,7 @@ class User(Base):
|
||||
class Item(Base):
|
||||
__tablename__ = "items"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
id = Column(Integer, primary_key=True)
|
||||
title = Column(String, index=True)
|
||||
description = Column(String, index=True)
|
||||
owner_id = Column(Integer, ForeignKey("users.id"))
|
||||
|
||||
@@ -13,4 +13,6 @@ templates = Jinja2Templates(directory="templates")
|
||||
|
||||
@app.get("/items/{id}", response_class=HTMLResponse)
|
||||
async def read_item(request: Request, id: str):
|
||||
return templates.TemplateResponse("item.html", {"request": request, "id": id})
|
||||
return templates.TemplateResponse(
|
||||
request=request, name="item.html", context={"id": id}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
|
||||
|
||||
__version__ = "0.105.0"
|
||||
__version__ = "0.109.0"
|
||||
|
||||
from starlette import status as status
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ from fastapi.exception_handlers import (
|
||||
)
|
||||
from fastapi.exceptions import RequestValidationError, WebSocketRequestValidationError
|
||||
from fastapi.logger import logger
|
||||
from fastapi.middleware.asyncexitstack import AsyncExitStackMiddleware
|
||||
from fastapi.openapi.docs import (
|
||||
get_redoc_html,
|
||||
get_swagger_ui_html,
|
||||
@@ -37,8 +36,6 @@ from starlette.datastructures import State
|
||||
from starlette.exceptions import HTTPException
|
||||
from starlette.middleware import Middleware
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from starlette.middleware.errors import ServerErrorMiddleware
|
||||
from starlette.middleware.exceptions import ExceptionMiddleware
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import HTMLResponse, JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
@@ -966,55 +963,6 @@ class FastAPI(Starlette):
|
||||
self.middleware_stack: Union[ASGIApp, None] = None
|
||||
self.setup()
|
||||
|
||||
def build_middleware_stack(self) -> ASGIApp:
|
||||
# Duplicate/override from Starlette to add AsyncExitStackMiddleware
|
||||
# inside of ExceptionMiddleware, inside of custom user middlewares
|
||||
debug = self.debug
|
||||
error_handler = None
|
||||
exception_handlers = {}
|
||||
|
||||
for key, value in self.exception_handlers.items():
|
||||
if key in (500, Exception):
|
||||
error_handler = value
|
||||
else:
|
||||
exception_handlers[key] = value
|
||||
|
||||
middleware = (
|
||||
[Middleware(ServerErrorMiddleware, handler=error_handler, debug=debug)]
|
||||
+ self.user_middleware
|
||||
+ [
|
||||
Middleware(
|
||||
ExceptionMiddleware, handlers=exception_handlers, debug=debug
|
||||
),
|
||||
# Add FastAPI-specific AsyncExitStackMiddleware for dependencies with
|
||||
# contextvars.
|
||||
# This needs to happen after user middlewares because those create a
|
||||
# new contextvars context copy by using a new AnyIO task group.
|
||||
# The initial part of dependencies with 'yield' is executed in the
|
||||
# FastAPI code, inside all the middlewares. However, the teardown part
|
||||
# (after 'yield') is executed in the AsyncExitStack in this middleware.
|
||||
# If the AsyncExitStack lived outside of the custom middlewares and
|
||||
# contextvars were set in a dependency with 'yield' in that internal
|
||||
# contextvars context, the values would not be available in the
|
||||
# outer context of the AsyncExitStack.
|
||||
# By placing the middleware and the AsyncExitStack here, inside all
|
||||
# user middlewares, the code before and after 'yield' in dependencies
|
||||
# with 'yield' is executed in the same contextvars context. Thus, all values
|
||||
# set in contextvars before 'yield' are still available after 'yield,' as
|
||||
# expected.
|
||||
# Additionally, by having this AsyncExitStack here, after the
|
||||
# ExceptionMiddleware, dependencies can now catch handled exceptions,
|
||||
# e.g. HTTPException, to customize the teardown code (e.g. DB session
|
||||
# rollback).
|
||||
Middleware(AsyncExitStackMiddleware),
|
||||
]
|
||||
)
|
||||
|
||||
app = self.router
|
||||
for cls, options in reversed(middleware):
|
||||
app = cls(app=app, **options)
|
||||
return app
|
||||
|
||||
def openapi(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate the OpenAPI schema of the application. This is called by FastAPI
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from contextlib import AsyncExitStack as AsyncExitStack # noqa
|
||||
from contextlib import asynccontextmanager as asynccontextmanager
|
||||
from typing import AsyncGenerator, ContextManager, TypeVar
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import inspect
|
||||
from contextlib import contextmanager
|
||||
from contextlib import AsyncExitStack, contextmanager
|
||||
from copy import deepcopy
|
||||
from typing import (
|
||||
Any,
|
||||
@@ -46,7 +46,6 @@ from fastapi._compat import (
|
||||
)
|
||||
from fastapi.background import BackgroundTasks
|
||||
from fastapi.concurrency import (
|
||||
AsyncExitStack,
|
||||
asynccontextmanager,
|
||||
contextmanager_in_threadpool,
|
||||
)
|
||||
@@ -529,6 +528,7 @@ async def solve_dependencies(
|
||||
response: Optional[Response] = None,
|
||||
dependency_overrides_provider: Optional[Any] = None,
|
||||
dependency_cache: Optional[Dict[Tuple[Callable[..., Any], Tuple[str]], Any]] = None,
|
||||
async_exit_stack: AsyncExitStack,
|
||||
) -> Tuple[
|
||||
Dict[str, Any],
|
||||
List[Any],
|
||||
@@ -575,6 +575,7 @@ async def solve_dependencies(
|
||||
response=response,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
dependency_cache=dependency_cache,
|
||||
async_exit_stack=async_exit_stack,
|
||||
)
|
||||
(
|
||||
sub_values,
|
||||
@@ -590,10 +591,8 @@ async def solve_dependencies(
|
||||
if sub_dependant.use_cache and sub_dependant.cache_key in dependency_cache:
|
||||
solved = dependency_cache[sub_dependant.cache_key]
|
||||
elif is_gen_callable(call) or is_async_gen_callable(call):
|
||||
stack = request.scope.get("fastapi_astack")
|
||||
assert isinstance(stack, AsyncExitStack)
|
||||
solved = await solve_generator(
|
||||
call=call, stack=stack, sub_values=sub_values
|
||||
call=call, stack=async_exit_stack, sub_values=sub_values
|
||||
)
|
||||
elif is_coroutine_callable(call):
|
||||
solved = await call(**sub_values)
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi.concurrency import AsyncExitStack
|
||||
from starlette.types import ASGIApp, Receive, Scope, Send
|
||||
|
||||
|
||||
class AsyncExitStackMiddleware:
|
||||
def __init__(self, app: ASGIApp, context_name: str = "fastapi_astack") -> None:
|
||||
self.app = app
|
||||
self.context_name = context_name
|
||||
|
||||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||
dependency_exception: Optional[Exception] = None
|
||||
async with AsyncExitStack() as stack:
|
||||
scope[self.context_name] = stack
|
||||
try:
|
||||
await self.app(scope, receive, send)
|
||||
except Exception as e:
|
||||
dependency_exception = e
|
||||
raise e
|
||||
if dependency_exception:
|
||||
# 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
|
||||
raise dependency_exception
|
||||
@@ -216,95 +216,124 @@ def get_request_handler(
|
||||
actual_response_class = response_class
|
||||
|
||||
async def app(request: Request) -> Response:
|
||||
try:
|
||||
body: Any = None
|
||||
if body_field:
|
||||
if is_body_form:
|
||||
body = await request.form()
|
||||
stack = request.scope.get("fastapi_astack")
|
||||
assert isinstance(stack, AsyncExitStack)
|
||||
stack.push_async_callback(body.close)
|
||||
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
|
||||
try:
|
||||
body: Any = None
|
||||
if body_field:
|
||||
if is_body_form:
|
||||
body = await request.form()
|
||||
async_exit_stack.push_async_callback(body.close)
|
||||
else:
|
||||
body_bytes = await request.body()
|
||||
if body_bytes:
|
||||
json_body: Any = Undefined
|
||||
content_type_value = request.headers.get("content-type")
|
||||
if not content_type_value:
|
||||
json_body = await request.json()
|
||||
else:
|
||||
message = email.message.Message()
|
||||
message["content-type"] = content_type_value
|
||||
if message.get_content_maintype() == "application":
|
||||
subtype = message.get_content_subtype()
|
||||
if subtype == "json" or subtype.endswith("+json"):
|
||||
json_body = await request.json()
|
||||
if json_body != Undefined:
|
||||
body = json_body
|
||||
else:
|
||||
body = body_bytes
|
||||
except json.JSONDecodeError as e:
|
||||
validation_error = RequestValidationError(
|
||||
[
|
||||
{
|
||||
"type": "json_invalid",
|
||||
"loc": ("body", e.pos),
|
||||
"msg": "JSON decode error",
|
||||
"input": {},
|
||||
"ctx": {"error": e.msg},
|
||||
}
|
||||
],
|
||||
body=e.doc,
|
||||
)
|
||||
exception_to_reraise = validation_error
|
||||
raise validation_error from e
|
||||
except HTTPException as e:
|
||||
exception_to_reraise = e
|
||||
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:
|
||||
solved_result = await solve_dependencies(
|
||||
request=request,
|
||||
dependant=dependant,
|
||||
body=body,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
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 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:
|
||||
body_bytes = await request.body()
|
||||
if body_bytes:
|
||||
json_body: Any = Undefined
|
||||
content_type_value = request.headers.get("content-type")
|
||||
if not content_type_value:
|
||||
json_body = await request.json()
|
||||
else:
|
||||
message = email.message.Message()
|
||||
message["content-type"] = content_type_value
|
||||
if message.get_content_maintype() == "application":
|
||||
subtype = message.get_content_subtype()
|
||||
if subtype == "json" or subtype.endswith("+json"):
|
||||
json_body = await request.json()
|
||||
if json_body != Undefined:
|
||||
body = json_body
|
||||
else:
|
||||
body = body_bytes
|
||||
except json.JSONDecodeError as e:
|
||||
raise RequestValidationError(
|
||||
[
|
||||
{
|
||||
"type": "json_invalid",
|
||||
"loc": ("body", e.pos),
|
||||
"msg": "JSON decode error",
|
||||
"input": {},
|
||||
"ctx": {"error": e.msg},
|
||||
}
|
||||
],
|
||||
body=e.doc,
|
||||
) from e
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="There was an error parsing the body"
|
||||
) from e
|
||||
solved_result = await solve_dependencies(
|
||||
request=request,
|
||||
dependant=dependant,
|
||||
body=body,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
)
|
||||
values, errors, background_tasks, sub_response, _ = solved_result
|
||||
if errors:
|
||||
raise RequestValidationError(_normalize_errors(errors), body=body)
|
||||
else:
|
||||
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
|
||||
return raw_response
|
||||
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)
|
||||
return response
|
||||
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"
|
||||
return response
|
||||
|
||||
return app
|
||||
|
||||
@@ -313,16 +342,22 @@ def get_websocket_app(
|
||||
dependant: Dependant, dependency_overrides_provider: Optional[Any] = None
|
||||
) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:
|
||||
async def app(websocket: WebSocket) -> None:
|
||||
solved_result = await solve_dependencies(
|
||||
request=websocket,
|
||||
dependant=dependant,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
)
|
||||
values, errors, _, _2, _3 = solved_result
|
||||
if errors:
|
||||
raise WebSocketRequestValidationError(_normalize_errors(errors))
|
||||
assert dependant.call is not None, "dependant.call must be a function"
|
||||
await dependant.call(**values)
|
||||
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
|
||||
websocket.scope["fastapi_astack"] = async_exit_stack
|
||||
solved_result = await solve_dependencies(
|
||||
request=websocket,
|
||||
dependant=dependant,
|
||||
dependency_overrides_provider=dependency_overrides_provider,
|
||||
async_exit_stack=async_exit_stack,
|
||||
)
|
||||
values, errors, _, _2, _3 = solved_result
|
||||
if errors:
|
||||
raise WebSocketRequestValidationError(_normalize_errors(errors))
|
||||
assert dependant.call is not None, "dependant.call must be a function"
|
||||
await dependant.call(**values)
|
||||
|
||||
return app
|
||||
|
||||
@@ -4293,7 +4328,7 @@ class APIRouter(routing.Router):
|
||||
app = FastAPI()
|
||||
router = APIRouter()
|
||||
|
||||
@router.put("/items/{item_id}")
|
||||
@router.trace("/items/{item_id}")
|
||||
def trace_item(item_id: str):
|
||||
return None
|
||||
|
||||
|
||||
@@ -36,15 +36,14 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
|
||||
"Topic :: Internet :: WWW/HTTP",
|
||||
]
|
||||
dependencies = [
|
||||
"starlette>=0.27.0,<0.28.0",
|
||||
"starlette>=0.35.0,<0.36.0",
|
||||
"pydantic>=1.7.4,!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0",
|
||||
"typing-extensions>=4.8.0",
|
||||
# TODO: remove this pin after upgrading Starlette 0.31.1
|
||||
"anyio>=3.7.1,<4.0.0",
|
||||
]
|
||||
dynamic = ["version"]
|
||||
|
||||
@@ -84,6 +83,12 @@ module = "fastapi.tests.*"
|
||||
ignore_missing_imports = true
|
||||
check_untyped_defs = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "docs_src.*"
|
||||
disallow_incomplete_defs = false
|
||||
disallow_untyped_defs = false
|
||||
disallow_untyped_calls = false
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = [
|
||||
"--strict-config",
|
||||
@@ -107,6 +112,18 @@ filterwarnings = [
|
||||
"ignore::trio.TrioDeprecationWarning",
|
||||
# TODO remove pytest-cov
|
||||
'ignore::pytest.PytestDeprecationWarning:pytest_cov',
|
||||
# TODO: remove after upgrading SQLAlchemy to a version that includes the following changes
|
||||
# https://github.com/sqlalchemy/sqlalchemy/commit/59521abcc0676e936b31a523bd968fc157fef0c2
|
||||
'ignore:datetime\.datetime\.utcfromtimestamp\(\) is deprecated and scheduled for removal in a future version\..*:DeprecationWarning:sqlalchemy',
|
||||
# TODO: remove after upgrading python-jose to a version that explicitly supports Python 3.12
|
||||
# also, if it won't receive an update, consider replacing python-jose with some alternative
|
||||
# related issues:
|
||||
# - https://github.com/mpdavis/python-jose/issues/332
|
||||
# - https://github.com/mpdavis/python-jose/issues/334
|
||||
'ignore:datetime\.datetime\.utcnow\(\) is deprecated and scheduled for removal in a future version\..*:DeprecationWarning:jose',
|
||||
# TODO: remove after upgrading Starlette to a version including https://github.com/encode/starlette/pull/2406
|
||||
# Probably Starlette 0.36.0
|
||||
"ignore: The 'method' parameter is not used, and it will be removed.:DeprecationWarning:starlette",
|
||||
]
|
||||
|
||||
[tool.coverage.run]
|
||||
@@ -167,6 +184,9 @@ ignore = [
|
||||
"docs_src/security/tutorial005_an_py39.py" = ["B904"]
|
||||
"docs_src/security/tutorial005_py310.py" = ["B904"]
|
||||
"docs_src/security/tutorial005_py39.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008b.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008b_an.py" = ["B904"]
|
||||
"docs_src/dependencies/tutorial008b_an_py39.py" = ["B904"]
|
||||
|
||||
|
||||
[tool.ruff.isort]
|
||||
|
||||
@@ -274,22 +274,24 @@ def live(
|
||||
def update_config() -> None:
|
||||
config = get_en_config()
|
||||
languages = [{"en": "/"}]
|
||||
alternate: List[Dict[str, str]] = config["extra"].get("alternate", [])
|
||||
alternate_dict = {alt["link"]: alt["name"] for alt in alternate}
|
||||
new_alternate: List[Dict[str, str]] = []
|
||||
# Language names sourced from https://quickref.me/iso-639-1
|
||||
# Contributors may wish to update or change these, e.g. to fix capitalization.
|
||||
language_names_path = Path(__file__).parent / "../docs/language_names.yml"
|
||||
local_language_names: Dict[str, str] = mkdocs.utils.yaml_load(
|
||||
language_names_path.read_text(encoding="utf-8")
|
||||
)
|
||||
for lang_path in get_lang_paths():
|
||||
if lang_path.name == "en" or not lang_path.is_dir():
|
||||
if lang_path.name in {"en", "em"} or not lang_path.is_dir():
|
||||
continue
|
||||
name = lang_path.name
|
||||
languages.append({name: f"/{name}/"})
|
||||
code = lang_path.name
|
||||
languages.append({code: f"/{code}/"})
|
||||
for lang_dict in languages:
|
||||
name = list(lang_dict.keys())[0]
|
||||
url = lang_dict[name]
|
||||
if url not in alternate_dict:
|
||||
new_alternate.append({"link": url, "name": name})
|
||||
else:
|
||||
use_name = alternate_dict[url]
|
||||
new_alternate.append({"link": url, "name": use_name})
|
||||
code = list(lang_dict.keys())[0]
|
||||
url = lang_dict[code]
|
||||
use_name = f"{code} - {local_language_names[code]}"
|
||||
new_alternate.append({"link": url, "name": use_name})
|
||||
new_alternate.append({"link": "/em/", "name": "😉"})
|
||||
config["extra"]["alternate"] = new_alternate
|
||||
en_config_path.write_text(
|
||||
yaml.dump(config, sort_keys=False, width=200, allow_unicode=True),
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import json
|
||||
from typing import Dict
|
||||
|
||||
import pytest
|
||||
from fastapi import BackgroundTasks, Depends, FastAPI
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
app = FastAPI()
|
||||
@@ -200,6 +202,13 @@ async def get_sync_context_b_bg(
|
||||
return state
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
async def middleware(request, call_next):
|
||||
response: StreamingResponse = await call_next(request)
|
||||
response.headers["x-state"] = json.dumps(state.copy())
|
||||
return response
|
||||
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
@@ -274,9 +283,13 @@ def test_background_tasks():
|
||||
assert data["context_b"] == "started b"
|
||||
assert data["context_a"] == "started a"
|
||||
assert data["bg"] == "not set"
|
||||
middleware_state = json.loads(response.headers["x-state"])
|
||||
assert middleware_state["context_b"] == "finished b with a: started a"
|
||||
assert middleware_state["context_a"] == "finished a"
|
||||
assert middleware_state["bg"] == "not set"
|
||||
assert state["context_b"] == "finished b with a: started a"
|
||||
assert state["context_a"] == "finished a"
|
||||
assert state["bg"] == "bg set - b: started b - a: started a"
|
||||
assert state["bg"] == "bg set - b: finished b with a: started a - a: finished a"
|
||||
|
||||
|
||||
def test_sync_raise_raises():
|
||||
@@ -382,4 +395,7 @@ def test_sync_background_tasks():
|
||||
assert data["sync_bg"] == "not set"
|
||||
assert state["context_b"] == "finished b with a: started a"
|
||||
assert state["context_a"] == "finished a"
|
||||
assert state["sync_bg"] == "sync_bg set - b: started b - a: started a"
|
||||
assert (
|
||||
state["sync_bg"]
|
||||
== "sync_bg set - b: finished b with a: started a - a: finished a"
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user