mirror of https://github.com/tiangolo/fastapi.git
🔧 Update docs setup with latest configs and plugins (#11953)
This commit is contained in:
parent
af1a07052a
commit
0cd844d387
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
docs: ${{ steps.filter.outputs.docs }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# For pull requests it's not necessary to checkout the code but for master it is
|
||||
# For pull requests it's not necessary to checkout the code but for the main branch it is
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
|
|
@ -28,9 +28,12 @@ jobs:
|
|||
- docs/**
|
||||
- docs_src/**
|
||||
- requirements-docs.txt
|
||||
- requirements-docs-insiders.txt
|
||||
- pyproject.toml
|
||||
- mkdocs.yml
|
||||
- mkdocs.insiders.yml
|
||||
- mkdocs.maybe-insiders.yml
|
||||
- mkdocs.no-insiders.yml
|
||||
- .github/workflows/build-docs.yml
|
||||
- .github/workflows/deploy-docs.yml
|
||||
langs:
|
||||
|
|
@ -49,17 +52,16 @@ jobs:
|
|||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt', 'requirements-docs-tests.txt') }}-v07
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt', 'requirements-docs-insiders.txt', 'requirements-docs-tests.txt') }}-v08
|
||||
- name: Install docs extras
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-docs.txt
|
||||
# Install MkDocs Material Insiders here just to put it in the cache for the rest of the steps
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git
|
||||
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git
|
||||
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/mkdocstrings-python.git
|
||||
run: pip install -r requirements-docs-insiders.txt
|
||||
env:
|
||||
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
|
||||
- name: Verify Docs
|
||||
run: python ./scripts/docs.py verify-docs
|
||||
- name: Export Language Codes
|
||||
|
|
@ -90,16 +92,15 @@ jobs:
|
|||
id: cache
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt', 'requirements-docs-tests.txt') }}-v08
|
||||
key: ${{ runner.os }}-python-docs-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml', 'requirements-docs.txt', 'requirements-docs-insiders.txt', 'requirements-docs-tests.txt') }}-v08
|
||||
- name: Install docs extras
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: pip install -r requirements-docs.txt
|
||||
- name: Install Material for MkDocs Insiders
|
||||
if: ( github.event_name != 'pull_request' || github.secret_source == 'Actions' ) && steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/squidfunk/mkdocs-material-insiders.git
|
||||
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/griffe-typing-deprecated.git
|
||||
pip install git+https://${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}@github.com/pawamoy-insiders/mkdocstrings-python.git
|
||||
run: pip install -r requirements-docs-insiders.txt
|
||||
env:
|
||||
TOKEN: ${{ secrets.FASTAPI_MKDOCS_MATERIAL_INSIDERS }}
|
||||
- name: Update Languages
|
||||
run: python ./scripts/docs.py update-languages
|
||||
- uses: actions/cache@v4
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ Python-এ ঐচ্ছিক "টাইপ হিন্ট" (যা "টাই
|
|||
|
||||
তবে, আপনি যদি কখনো **FastAPI** ব্যবহার নাও করেন, তবুও এগুলি সম্পর্কে একটু শেখা আপনার উপকারে আসবে।
|
||||
|
||||
!!! Note
|
||||
যদি আপনি একজন Python বিশেষজ্ঞ হন, এবং টাইপ হিন্ট সম্পর্কে সবকিছু জানেন, তাহলে পরবর্তী অধ্যায়ে চলে যান।
|
||||
/// note
|
||||
|
||||
যদি আপনি একজন Python বিশেষজ্ঞ হন, এবং টাইপ হিন্ট সম্পর্কে সবকিছু জানেন, তাহলে পরবর্তী অধ্যায়ে চলে যান।
|
||||
|
||||
///
|
||||
|
||||
## প্রেরণা
|
||||
|
||||
|
|
@ -170,45 +173,55 @@ Python যত এগিয়ে যাচ্ছে, **নতুন সংস্
|
|||
|
||||
উদাহরণস্বরূপ, একটি ভেরিয়েবলকে `str`-এর একটি `list` হিসেবে সংজ্ঞায়িত করা যাক।
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (`:`) সিনট্যাক্স ব্যবহার করে।
|
||||
ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (`:`) সিনট্যাক্স ব্যবহার করে।
|
||||
|
||||
টাইপ হিসেবে, `list` ব্যবহার করুন।
|
||||
টাইপ হিসেবে, `list` ব্যবহার করুন।
|
||||
|
||||
যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে ব্যবহার করুন:
|
||||
যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে ব্যবহার করুন:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
`typing` থেকে `List` (বড় হাতের `L` দিয়ে) ইমপোর্ট করুন:
|
||||
//// tab | Python 3.8+
|
||||
|
||||
``` Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
`typing` থেকে `List` (বড় হাতের `L` দিয়ে) ইমপোর্ট করুন:
|
||||
|
||||
ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (`:`) সিনট্যাক্স ব্যবহার করে।
|
||||
``` Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
টাইপ হিসেবে, `typing` থেকে আপনার ইম্পোর্ট করা `List` ব্যবহার করুন।
|
||||
ভেরিয়েবলটি ঘোষণা করুন, একই কোলন (`:`) সিনট্যাক্স ব্যবহার করে।
|
||||
|
||||
যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে করুন:
|
||||
টাইপ হিসেবে, `typing` থেকে আপনার ইম্পোর্ট করা `List` ব্যবহার করুন।
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
যেহেতু লিস্ট এমন একটি টাইপ যা অভ্যন্তরীণ টাইপগুলি ধারণ করে, আপনি তাদের স্কোয়ার ব্রাকেটের ভিতরে করুন:
|
||||
|
||||
!!! Info
|
||||
স্কোয়ার ব্রাকেট এর ভিতরে ব্যবহৃত এইসব অভন্তরীন টাইপগুলোকে "ইন্টারনাল টাইপ" বলে।
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
এই উদাহরণে, এটি হচ্ছে `List`(অথবা পাইথন ৩.৯ বা তার উপরের সংস্করণের ক্ষেত্রে `list`) এ পাস করা টাইপ প্যারামিটার।
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
স্কোয়ার ব্রাকেট এর ভিতরে ব্যবহৃত এইসব অভন্তরীন টাইপগুলোকে "ইন্টারনাল টাইপ" বলে।
|
||||
|
||||
এই উদাহরণে, এটি হচ্ছে `List`(অথবা পাইথন ৩.৯ বা তার উপরের সংস্করণের ক্ষেত্রে `list`) এ পাস করা টাইপ প্যারামিটার।
|
||||
|
||||
///
|
||||
|
||||
এর অর্থ হচ্ছে: "ভেরিয়েবল `items` একটি `list`, এবং এই লিস্টের প্রতিটি আইটেম একটি `str`।"
|
||||
|
||||
!!! Tip
|
||||
যদি আপনি Python 3.9 বা তার উপরে ব্যবহার করেন, আপনার `typing` থেকে `List` আমদানি করতে হবে না, আপনি সাধারণ `list` ওই টাইপের পরিবর্তে ব্যবহার করতে পারেন।
|
||||
/// tip
|
||||
|
||||
যদি আপনি Python 3.9 বা তার উপরে ব্যবহার করেন, আপনার `typing` থেকে `List` আমদানি করতে হবে না, আপনি সাধারণ `list` ওই টাইপের পরিবর্তে ব্যবহার করতে পারেন।
|
||||
|
||||
///
|
||||
|
||||
এর মাধ্যমে, আপনার এডিটর লিস্ট থেকে আইটেম প্রসেস করার সময় সাপোর্ট প্রদান করতে পারবে:
|
||||
|
||||
|
|
@ -224,17 +237,21 @@ Python যত এগিয়ে যাচ্ছে, **নতুন সংস্
|
|||
|
||||
আপনি `tuple` এবং `set` ঘোষণা করার জন্য একই প্রক্রিয়া অনুসরণ করবেন:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
এর মানে হল:
|
||||
|
||||
|
|
@ -249,18 +266,21 @@ Python যত এগিয়ে যাচ্ছে, **নতুন সংস্
|
|||
|
||||
দ্বিতীয় টাইপ প্যারামিটারটি হল `dict`-এর মানগুলির জন্য:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
এর মানে হল:
|
||||
|
||||
|
|
@ -276,17 +296,21 @@ Python 3.6 এবং তার উপরের সংস্করণগুলি
|
|||
|
||||
Python 3.10-এ একটি **নতুন সিনট্যাক্স** আছে যেখানে আপনি সম্ভাব্য টাইপগুলিকে একটি <abbr title="উল্লম্ব বারালকে 'বিটওয়াইজ বা অপারেটর' বলা হয়, কিন্তু সেই অর্থ এখানে প্রাসঙ্গিক নয়">ভার্টিকাল বার (`|`)</abbr> দ্বারা পৃথক করতে পারেন।
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008b.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
উভয় ক্ষেত্রেই এর মানে হল যে `item` হতে পারে একটি `int` অথবা `str`।
|
||||
|
||||
|
|
@ -306,23 +330,29 @@ Python 3.6 এবং তার উপরের সংস্করণগুলি
|
|||
|
||||
এর মানে হল, Python 3.10-এ, আপনি টাইপগুলির ইউনিয়ন ঘোষণা করতে `Something | None` ব্যবহার করতে পারেন:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ বিকল্প"
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009b.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ বিকল্প
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
#### `Union` বা `Optional` ব্যবহার
|
||||
|
||||
|
|
@ -367,46 +397,53 @@ say_hi(name=None) # এটি কাজ করে, None বৈধ 🎉
|
|||
|
||||
স্কোয়ার ব্র্যাকেটে টাইপ প্যারামিটার নেওয়া এই টাইপগুলিকে **জেনেরিক টাইপ** বা **জেনেরিকস** বলা হয়, যেমন:
|
||||
|
||||
=== "Python 3.10+"
|
||||
আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):
|
||||
//// tab | Python 3.10+
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):
|
||||
|
||||
এবং Python 3.8 এর মতোই, `typing` মডিউল থেকে:
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
* `Union`
|
||||
* `Optional` (Python 3.8 এর মতোই)
|
||||
* ...এবং অন্যান্য।
|
||||
এবং Python 3.8 এর মতোই, `typing` মডিউল থেকে:
|
||||
|
||||
Python 3.10-এ, `Union` এবং `Optional` জেনেরিকস ব্যবহার করার বিকল্প হিসেবে, আপনি টাইপগুলির ইউনিয়ন ঘোষণা করতে <abbr title="উল্লম্ব বারালকে 'বিটওয়াইজ বা অপারেটর' বলা হয়, কিন্তু সেই অর্থ এখানে প্রাসঙ্গিক নয়">ভার্টিকাল বার (`|`)</abbr> ব্যবহার করতে পারেন, যা ওদের থেকে অনেক ভালো এবং সহজ।
|
||||
* `Union`
|
||||
* `Optional` (Python 3.8 এর মতোই)
|
||||
* ...এবং অন্যান্য।
|
||||
|
||||
=== "Python 3.9+"
|
||||
Python 3.10-এ, `Union` এবং `Optional` জেনেরিকস ব্যবহার করার বিকল্প হিসেবে, আপনি টাইপগুলির ইউনিয়ন ঘোষণা করতে <abbr title="উল্লম্ব বারালকে 'বিটওয়াইজ বা অপারেটর' বলা হয়, কিন্তু সেই অর্থ এখানে প্রাসঙ্গিক নয়">ভার্টিকাল বার (`|`)</abbr> ব্যবহার করতে পারেন, যা ওদের থেকে অনেক ভালো এবং সহজ।
|
||||
|
||||
আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):
|
||||
////
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
//// tab | Python 3.9+
|
||||
|
||||
এবং Python 3.8 এর মতোই, `typing` মডিউল থেকে:
|
||||
আপনি সেই একই বিল্টইন টাইপ জেনেরিক্স হিসেবে ব্যবহার করতে পারবেন(ভিতরে টাইপ সহ স্কয়ারে ব্রাকেট দিয়ে):
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...এবং অন্যান্য।
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
=== "Python 3.8+"
|
||||
এবং Python 3.8 এর মতোই, `typing` মডিউল থেকে:
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...এবং অন্যান্য।
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...এবং অন্যান্য।
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ...এবং অন্যান্য।
|
||||
|
||||
////
|
||||
|
||||
### ক্লাস হিসেবে টাইপস
|
||||
|
||||
|
|
@ -446,55 +483,71 @@ say_hi(name=None) # এটি কাজ করে, None বৈধ 🎉
|
|||
|
||||
অফিসিয়াল Pydantic ডক্স থেকে একটি উদাহরণ:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
|
||||
```
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! Info
|
||||
[Pydantic সম্পর্কে আরও জানতে, এর ডকুমেন্টেশন দেখুন](https://docs.pydantic.dev/)।
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
[Pydantic সম্পর্কে আরও জানতে, এর ডকুমেন্টেশন দেখুন](https://docs.pydantic.dev/)।
|
||||
|
||||
///
|
||||
|
||||
**FastAPI** মূলত Pydantic-এর উপর নির্মিত।
|
||||
|
||||
আপনি এই সমস্ত কিছুর অনেক বাস্তবসম্মত উদাহরণ পাবেন [টিউটোরিয়াল - ইউজার গাইডে](https://fastapi.tiangolo.com/tutorial/)।
|
||||
|
||||
!!! Tip
|
||||
যখন আপনি `Optional` বা `Union[Something, None]` ব্যবহার করেন এবং কোনো ডিফল্ট মান না থাকে, Pydantic-এর একটি বিশেষ আচরণ রয়েছে, আপনি Pydantic ডকুমেন্টেশনে [Required Optional fields](https://docs.pydantic.dev/latest/concepts/models/#required-optional-fields) সম্পর্কে আরও পড়তে পারেন।
|
||||
/// tip
|
||||
|
||||
যখন আপনি `Optional` বা `Union[Something, None]` ব্যবহার করেন এবং কোনো ডিফল্ট মান না থাকে, Pydantic-এর একটি বিশেষ আচরণ রয়েছে, আপনি Pydantic ডকুমেন্টেশনে [Required Optional fields](https://docs.pydantic.dev/latest/concepts/models/#required-optional-fields) সম্পর্কে আরও পড়তে পারেন।
|
||||
|
||||
///
|
||||
|
||||
## মেটাডাটা অ্যানোটেশন সহ টাইপ হিন্টস
|
||||
|
||||
Python-এ এমন একটি ফিচার আছে যা `Annotated` ব্যবহার করে এই টাইপ হিন্টগুলিতে **অতিরিক্ত মেটাডাটা** রাখতে দেয়।
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
Python 3.9-এ, `Annotated` স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্ত, তাই আপনি এটি `typing` থেকে ইমপোর্ট করতে পারেন।
|
||||
Python 3.9-এ, `Annotated` স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্ত, তাই আপনি এটি `typing` থেকে ইমপোর্ট করতে পারেন।
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
Python 3.9-এর নীচের সংস্করণগুলিতে, আপনি `Annotated`-কে `typing_extensions` থেকে ইমপোর্ট করেন।
|
||||
//// tab | Python 3.8+
|
||||
|
||||
এটি **FastAPI** এর সাথে ইতিমদ্ধে ইনস্টল হয়ে থাকবে।
|
||||
Python 3.9-এর নীচের সংস্করণগুলিতে, আপনি `Annotated`-কে `typing_extensions` থেকে ইমপোর্ট করেন।
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013.py!}
|
||||
```
|
||||
এটি **FastAPI** এর সাথে ইতিমদ্ধে ইনস্টল হয়ে থাকবে।
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Python নিজে এই `Annotated` দিয়ে কিছুই করে না। এবং এডিটর এবং অন্যান্য টুলগুলির জন্য, টাইপটি এখনও `str`।
|
||||
|
||||
|
|
@ -506,10 +559,13 @@ Python নিজে এই `Annotated` দিয়ে কিছুই করে
|
|||
|
||||
পরবর্তীতে আপনি দেখবেন এটি কতটা **শক্তিশালী** হতে পারে।
|
||||
|
||||
!!! Tip
|
||||
এটি **স্ট্যান্ডার্ড Python** হওয়ার মানে হল আপনি আপনার এডিটরে, আপনি যে টুলগুলি কোড বিশ্লেষণ এবং রিফ্যাক্টর করার জন্য ব্যবহার করেন তাতে **সেরা সম্ভাব্য ডেভেলপার এক্সপেরিয়েন্স** পাবেন। ✨
|
||||
/// tip
|
||||
|
||||
এবং এছাড়াও আপনার কোড অন্যান্য অনেক Python টুল এবং লাইব্রেরিগুলির সাথে খুব সামঞ্জস্যপূর্ণ হবে। 🚀
|
||||
এটি **স্ট্যান্ডার্ড Python** হওয়ার মানে হল আপনি আপনার এডিটরে, আপনি যে টুলগুলি কোড বিশ্লেষণ এবং রিফ্যাক্টর করার জন্য ব্যবহার করেন তাতে **সেরা সম্ভাব্য ডেভেলপার এক্সপেরিয়েন্স** পাবেন। ✨
|
||||
|
||||
এবং এছাড়াও আপনার কোড অন্যান্য অনেক Python টুল এবং লাইব্রেরিগুলির সাথে খুব সামঞ্জস্যপূর্ণ হবে। 🚀
|
||||
|
||||
///
|
||||
|
||||
## **FastAPI**-এ টাইপ হিন্টস
|
||||
|
||||
|
|
@ -533,5 +589,8 @@ Python নিজে এই `Annotated` দিয়ে কিছুই করে
|
|||
|
||||
গুরুত্বপূর্ণ বিষয় হল, আপনি যদি স্ট্যান্ডার্ড Python টাইপগুলি ব্যবহার করেন, তবে আরও বেশি ক্লাস, ডেকোরেটর ইত্যাদি যোগ না করেই একই স্থানে **FastAPI** আপনার অনেক কাজ করে দিবে।
|
||||
|
||||
!!! Info
|
||||
যদি আপনি টিউটোরিয়ালের সমস্ত বিষয় পড়ে ফেলে থাকেন এবং টাইপ সম্পর্কে আরও জানতে চান, তবে একটি ভালো রিসোর্স হল [mypy এর "cheat sheet"](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)। এই "cheat sheet" এ আপনি Python টাইপ হিন্ট সম্পর্কে বেসিক থেকে উন্নত লেভেলের ধারণা পেতে পারেন, যা আপনার কোডে টাইপ সেফটি এবং স্পষ্টতা বাড়াতে সাহায্য করবে।
|
||||
/// info
|
||||
|
||||
যদি আপনি টিউটোরিয়ালের সমস্ত বিষয় পড়ে ফেলে থাকেন এবং টাইপ সম্পর্কে আরও জানতে চান, তবে একটি ভালো রিসোর্স হল [mypy এর "cheat sheet"](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html)। এই "cheat sheet" এ আপনি Python টাইপ হিন্ট সম্পর্কে বেসিক থেকে উন্নত লেভেলের ধারণা পেতে পারেন, যা আপনার কোডে টাইপ সেফটি এবং স্পষ্টতা বাড়াতে সাহায্য করবে।
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
# Zusätzliche Responses in OpenAPI
|
||||
|
||||
!!! warning "Achtung"
|
||||
Dies ist ein eher fortgeschrittenes Thema.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Wenn Sie mit **FastAPI** beginnen, benötigen Sie dies möglicherweise nicht.
|
||||
Dies ist ein eher fortgeschrittenes Thema.
|
||||
|
||||
Wenn Sie mit **FastAPI** beginnen, benötigen Sie dies möglicherweise nicht.
|
||||
|
||||
///
|
||||
|
||||
Sie können zusätzliche Responses mit zusätzlichen Statuscodes, Medientypen, Beschreibungen, usw. deklarieren.
|
||||
|
||||
|
|
@ -27,20 +30,26 @@ Um beispielsweise eine weitere Response mit dem Statuscode `404` und einem Pydan
|
|||
{!../../../docs_src/additional_responses/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass Sie die `JSONResponse` direkt zurückgeben müssen.
|
||||
/// note | "Hinweis"
|
||||
|
||||
!!! info
|
||||
Der `model`-Schlüssel ist nicht Teil von OpenAPI.
|
||||
Beachten Sie, dass Sie die `JSONResponse` direkt zurückgeben müssen.
|
||||
|
||||
**FastAPI** nimmt das Pydantic-Modell von dort, generiert das JSON-Schema und fügt es an der richtigen Stelle ein.
|
||||
///
|
||||
|
||||
Die richtige Stelle ist:
|
||||
/// info
|
||||
|
||||
* Im Schlüssel `content`, der als Wert ein weiteres JSON-Objekt (`dict`) hat, welches Folgendes enthält:
|
||||
* Ein Schlüssel mit dem Medientyp, z. B. `application/json`, der als Wert ein weiteres JSON-Objekt hat, welches Folgendes enthält:
|
||||
* Ein Schlüssel `schema`, der als Wert das JSON-Schema aus dem Modell hat, hier ist die richtige Stelle.
|
||||
* **FastAPI** fügt hier eine Referenz auf die globalen JSON-Schemas an einer anderen Stelle in Ihrer OpenAPI hinzu, anstatt es direkt einzubinden. Auf diese Weise können andere Anwendungen und Clients diese JSON-Schemas direkt verwenden, bessere Tools zur Codegenerierung bereitstellen, usw.
|
||||
Der `model`-Schlüssel ist nicht Teil von OpenAPI.
|
||||
|
||||
**FastAPI** nimmt das Pydantic-Modell von dort, generiert das JSON-Schema und fügt es an der richtigen Stelle ein.
|
||||
|
||||
Die richtige Stelle ist:
|
||||
|
||||
* Im Schlüssel `content`, der als Wert ein weiteres JSON-Objekt (`dict`) hat, welches Folgendes enthält:
|
||||
* Ein Schlüssel mit dem Medientyp, z. B. `application/json`, der als Wert ein weiteres JSON-Objekt hat, welches Folgendes enthält:
|
||||
* Ein Schlüssel `schema`, der als Wert das JSON-Schema aus dem Modell hat, hier ist die richtige Stelle.
|
||||
* **FastAPI** fügt hier eine Referenz auf die globalen JSON-Schemas an einer anderen Stelle in Ihrer OpenAPI hinzu, anstatt es direkt einzubinden. Auf diese Weise können andere Anwendungen und Clients diese JSON-Schemas direkt verwenden, bessere Tools zur Codegenerierung bereitstellen, usw.
|
||||
|
||||
///
|
||||
|
||||
Die generierten Responses in der OpenAPI für diese *Pfadoperation* lauten:
|
||||
|
||||
|
|
@ -172,13 +181,19 @@ Sie können beispielsweise einen zusätzlichen Medientyp `image/png` hinzufügen
|
|||
{!../../../docs_src/additional_responses/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass Sie das Bild direkt mit einer `FileResponse` zurückgeben müssen.
|
||||
/// note | "Hinweis"
|
||||
|
||||
!!! info
|
||||
Sofern Sie in Ihrem Parameter `responses` nicht explizit einen anderen Medientyp angeben, geht FastAPI davon aus, dass die Response denselben Medientyp wie die Haupt-Response-Klasse hat (Standardmäßig `application/json`).
|
||||
Beachten Sie, dass Sie das Bild direkt mit einer `FileResponse` zurückgeben müssen.
|
||||
|
||||
Wenn Sie jedoch eine benutzerdefinierte Response-Klasse mit `None` als Medientyp angegeben haben, verwendet FastAPI `application/json` für jede zusätzliche Response, die über ein zugehöriges Modell verfügt.
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
Sofern Sie in Ihrem Parameter `responses` nicht explizit einen anderen Medientyp angeben, geht FastAPI davon aus, dass die Response denselben Medientyp wie die Haupt-Response-Klasse hat (Standardmäßig `application/json`).
|
||||
|
||||
Wenn Sie jedoch eine benutzerdefinierte Response-Klasse mit `None` als Medientyp angegeben haben, verwendet FastAPI `application/json` für jede zusätzliche Response, die über ein zugehöriges Modell verfügt.
|
||||
|
||||
///
|
||||
|
||||
## Informationen kombinieren
|
||||
|
||||
|
|
|
|||
|
|
@ -14,53 +14,75 @@ Sie möchten aber auch, dass sie neue Artikel akzeptiert. Und wenn die Elemente
|
|||
|
||||
Um dies zu erreichen, importieren Sie `JSONResponse`, und geben Sie Ihren Inhalt direkt zurück, indem Sie den gewünschten `status_code` setzen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="4 26"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="4 26"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="2 23"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Wenn Sie eine `Response` direkt zurückgeben, wie im obigen Beispiel, wird sie direkt zurückgegeben.
|
||||
///
|
||||
|
||||
Sie wird nicht mit einem Modell usw. serialisiert.
|
||||
```Python hl_lines="2 23"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
Stellen Sie sicher, dass sie die gewünschten Daten enthält und dass die Werte gültiges JSON sind (wenn Sie `JSONResponse` verwenden).
|
||||
////
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import JSONResponse` verwenden.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `status`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4 25"
|
||||
{!> ../../../docs_src/additional_status_codes/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Wenn Sie eine `Response` direkt zurückgeben, wie im obigen Beispiel, wird sie direkt zurückgegeben.
|
||||
|
||||
Sie wird nicht mit einem Modell usw. serialisiert.
|
||||
|
||||
Stellen Sie sicher, dass sie die gewünschten Daten enthält und dass die Werte gültiges JSON sind (wenn Sie `JSONResponse` verwenden).
|
||||
|
||||
///
|
||||
|
||||
/// note | "Technische Details"
|
||||
|
||||
Sie können auch `from starlette.responses import JSONResponse` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `status`.
|
||||
|
||||
///
|
||||
|
||||
## OpenAPI- und API-Dokumentation
|
||||
|
||||
|
|
|
|||
|
|
@ -18,26 +18,35 @@ Nicht die Klasse selbst (die bereits aufrufbar ist), sondern eine Instanz dieser
|
|||
|
||||
Dazu deklarieren wir eine Methode `__call__`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall ist dieses `__call__` das, was **FastAPI** verwendet, um nach zusätzlichen Parametern und Unterabhängigkeiten zu suchen, und das ist es auch, was später aufgerufen wird, um einen Wert an den Parameter in Ihrer *Pfadoperation-Funktion* zu übergeben.
|
||||
|
||||
|
|
@ -45,26 +54,35 @@ In diesem Fall ist dieses `__call__` das, was **FastAPI** verwendet, um nach zus
|
|||
|
||||
Und jetzt können wir `__init__` verwenden, um die Parameter der Instanz zu deklarieren, die wir zum `Parametrisieren` der Abhängigkeit verwenden können:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall wird **FastAPI** `__init__` nie berühren oder sich darum kümmern, wir werden es direkt in unserem Code verwenden.
|
||||
|
||||
|
|
@ -72,26 +90,35 @@ In diesem Fall wird **FastAPI** `__init__` nie berühren oder sich darum kümmer
|
|||
|
||||
Wir könnten eine Instanz dieser Klasse erstellen mit:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Und auf diese Weise können wir unsere Abhängigkeit „parametrisieren“, die jetzt `"bar"` enthält, als das Attribut `checker.fixed_content`.
|
||||
|
||||
|
|
@ -107,32 +134,44 @@ checker(q="somequery")
|
|||
|
||||
... und übergibt, was immer das als Wert dieser Abhängigkeit in unserer *Pfadoperation-Funktion* zurückgibt, als den Parameter `fixed_content_included`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/dependencies/tutorial011_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Das alles mag gekünstelt wirken. Und es ist möglicherweise noch nicht ganz klar, welchen Nutzen das hat.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Diese Beispiele sind bewusst einfach gehalten, zeigen aber, wie alles funktioniert.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
In den Kapiteln zum Thema Sicherheit gibt es Hilfsfunktionen, die auf die gleiche Weise implementiert werden.
|
||||
///
|
||||
|
||||
Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherheits-Hilfswerkzeuge unter der Haube funktionieren.
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Das alles mag gekünstelt wirken. Und es ist möglicherweise noch nicht ganz klar, welchen Nutzen das hat.
|
||||
|
||||
Diese Beispiele sind bewusst einfach gehalten, zeigen aber, wie alles funktioniert.
|
||||
|
||||
In den Kapiteln zum Thema Sicherheit gibt es Hilfsfunktionen, die auf die gleiche Weise implementiert werden.
|
||||
|
||||
Wenn Sie das hier alles verstanden haben, wissen Sie bereits, wie diese Sicherheits-Hilfswerkzeuge unter der Haube funktionieren.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -64,8 +64,11 @@ Der Marker `@pytest.mark.anyio` teilt pytest mit, dass diese Testfunktion asynch
|
|||
{!../../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wie zuvor, wenn Sie den `TestClient` verwenden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass die Testfunktion jetzt `async def` ist und nicht nur `def` wie zuvor, wenn Sie den `TestClient` verwenden.
|
||||
|
||||
///
|
||||
|
||||
Dann können wir einen `AsyncClient` mit der App erstellen und mit `await` asynchrone Requests an ihn senden.
|
||||
|
||||
|
|
@ -81,15 +84,24 @@ response = client.get('/')
|
|||
|
||||
... welches wir verwendet haben, um unsere Requests mit dem `TestClient` zu machen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass wir async/await mit dem neuen `AsyncClient` verwenden – der Request ist asynchron.
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! warning "Achtung"
|
||||
Falls Ihre Anwendung auf Lifespan-Events angewiesen ist, der `AsyncClient` löst diese Events nicht aus. Um sicherzustellen, dass sie ausgelöst werden, verwenden Sie `LifespanManager` von <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.
|
||||
Beachten Sie, dass wir async/await mit dem neuen `AsyncClient` verwenden – der Request ist asynchron.
|
||||
|
||||
///
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Falls Ihre Anwendung auf Lifespan-Events angewiesen ist, der `AsyncClient` löst diese Events nicht aus. Um sicherzustellen, dass sie ausgelöst werden, verwenden Sie `LifespanManager` von <a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>.
|
||||
|
||||
///
|
||||
|
||||
## Andere asynchrone Funktionsaufrufe
|
||||
|
||||
Da die Testfunktion jetzt asynchron ist, können Sie in Ihren Tests neben dem Senden von Requests an Ihre FastAPI-Anwendung jetzt auch andere `async`hrone Funktionen aufrufen (und `await`en), genau so, wie Sie diese an anderer Stelle in Ihrem Code aufrufen würden.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie einen `RuntimeError: Task attached to a different loop` erhalten, wenn Sie asynchrone Funktionsaufrufe in Ihre Tests integrieren (z. B. bei Verwendung von <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDBs MotorClient</a>), dann denken Sie daran, Objekte zu instanziieren, die einen Event Loop nur innerhalb asynchroner Funktionen benötigen, z. B. einen `@app.on_event("startup")`-Callback.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie einen `RuntimeError: Task attached to a different loop` erhalten, wenn Sie asynchrone Funktionsaufrufe in Ihre Tests integrieren (z. B. bei Verwendung von <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDBs MotorClient</a>), dann denken Sie daran, Objekte zu instanziieren, die einen Event Loop nur innerhalb asynchroner Funktionen benötigen, z. B. einen `@app.on_event("startup")`-Callback.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -43,8 +43,11 @@ browser --> proxy
|
|||
proxy --> server
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die IP `0.0.0.0` wird üblicherweise verwendet, um anzudeuten, dass das Programm alle auf diesem Computer/Server verfügbaren IPs abhört.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die IP `0.0.0.0` wird üblicherweise verwendet, um anzudeuten, dass das Programm alle auf diesem Computer/Server verfügbaren IPs abhört.
|
||||
|
||||
///
|
||||
|
||||
Die Benutzeroberfläche der Dokumentation würde benötigen, dass das OpenAPI-Schema deklariert, dass sich dieser API-`server` unter `/api/v1` (hinter dem Proxy) befindet. Zum Beispiel:
|
||||
|
||||
|
|
@ -81,10 +84,13 @@ $ uvicorn main:app --root-path /api/v1
|
|||
|
||||
Falls Sie Hypercorn verwenden, das hat auch die Option `--root-path`.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Die ASGI-Spezifikation definiert einen `root_path` für diesen Anwendungsfall.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Und die Kommandozeilenoption `--root-path` stellt diesen `root_path` bereit.
|
||||
Die ASGI-Spezifikation definiert einen `root_path` für diesen Anwendungsfall.
|
||||
|
||||
Und die Kommandozeilenoption `--root-path` stellt diesen `root_path` bereit.
|
||||
|
||||
///
|
||||
|
||||
### Überprüfen des aktuellen `root_path`
|
||||
|
||||
|
|
@ -172,8 +178,11 @@ Dann erstellen Sie eine Datei `traefik.toml` mit:
|
|||
|
||||
Dadurch wird Traefik angewiesen, Port 9999 abzuhören und eine andere Datei `routes.toml` zu verwenden.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wir verwenden Port 9999 anstelle des Standard-HTTP-Ports 80, damit Sie ihn nicht mit Administratorrechten (`sudo`) ausführen müssen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wir verwenden Port 9999 anstelle des Standard-HTTP-Ports 80, damit Sie ihn nicht mit Administratorrechten (`sudo`) ausführen müssen.
|
||||
|
||||
///
|
||||
|
||||
Erstellen Sie nun die andere Datei `routes.toml`:
|
||||
|
||||
|
|
@ -239,8 +248,11 @@ Wenn Sie nun zur URL mit dem Port für Uvicorn gehen: <a href="http://127.0.0.1:
|
|||
}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass, obwohl Sie unter `http://127.0.0.1:8000/app` darauf zugreifen, als `root_path` angezeigt wird `/api/v1`, welches aus der Option `--root-path` stammt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass, obwohl Sie unter `http://127.0.0.1:8000/app` darauf zugreifen, als `root_path` angezeigt wird `/api/v1`, welches aus der Option `--root-path` stammt.
|
||||
|
||||
///
|
||||
|
||||
Öffnen Sie nun die URL mit dem Port für Traefik, einschließlich des Pfadpräfixes: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
|
||||
|
||||
|
|
@ -283,8 +295,11 @@ Dies liegt daran, dass FastAPI diesen `root_path` verwendet, um den Default-`ser
|
|||
|
||||
## Zusätzliche Server
|
||||
|
||||
!!! warning "Achtung"
|
||||
Dies ist ein fortgeschrittener Anwendungsfall. Überspringen Sie das gerne.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Dies ist ein fortgeschrittener Anwendungsfall. Überspringen Sie das gerne.
|
||||
|
||||
///
|
||||
|
||||
Standardmäßig erstellt **FastAPI** einen `server` im OpenAPI-Schema mit der URL für den `root_path`.
|
||||
|
||||
|
|
@ -323,15 +338,21 @@ Erzeugt ein OpenAPI-Schema, wie:
|
|||
}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie den automatisch generierten Server mit dem `URL`-Wert `/api/v1`, welcher vom `root_path` stammt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie den automatisch generierten Server mit dem `URL`-Wert `/api/v1`, welcher vom `root_path` stammt.
|
||||
|
||||
///
|
||||
|
||||
In der Dokumentationsoberfläche unter <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> würde es so aussehen:
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image03.png">
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die Dokumentationsoberfläche interagiert mit dem von Ihnen ausgewählten Server.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die Dokumentationsoberfläche interagiert mit dem von Ihnen ausgewählten Server.
|
||||
|
||||
///
|
||||
|
||||
### Den automatischen Server von `root_path` deaktivieren
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ Der Inhalt, den Sie von Ihrer *Pfadoperation-Funktion* zurückgeben, wird in die
|
|||
|
||||
Und wenn diese `Response` einen JSON-Medientyp (`application/json`) hat, wie es bei `JSONResponse` und `UJSONResponse` der Fall ist, werden die von Ihnen zurückgegebenen Daten automatisch mit jedem Pydantic `response_model` konvertiert (und gefiltert), das Sie im *Pfadoperation-Dekorator* deklariert haben.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Wenn Sie eine Response-Klasse ohne Medientyp verwenden, erwartet FastAPI, dass Ihre Response keinen Inhalt hat, und dokumentiert daher das Format der Response nicht in deren generierter OpenAPI-Dokumentation.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Wenn Sie eine Response-Klasse ohne Medientyp verwenden, erwartet FastAPI, dass Ihre Response keinen Inhalt hat, und dokumentiert daher das Format der Response nicht in deren generierter OpenAPI-Dokumentation.
|
||||
|
||||
///
|
||||
|
||||
## `ORJSONResponse` verwenden
|
||||
|
||||
|
|
@ -31,15 +34,21 @@ Wenn Sie jedoch sicher sind, dass der von Ihnen zurückgegebene Inhalt **mit JSO
|
|||
{!../../../docs_src/custom_response/tutorial001b.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren.
|
||||
/// info
|
||||
|
||||
In diesem Fall wird der HTTP-Header `Content-Type` auf `application/json` gesetzt.
|
||||
Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren.
|
||||
|
||||
Und er wird als solcher in OpenAPI dokumentiert.
|
||||
In diesem Fall wird der HTTP-Header `Content-Type` auf `application/json` gesetzt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die `ORJSONResponse` ist derzeit nur in FastAPI verfügbar, nicht in Starlette.
|
||||
Und er wird als solcher in OpenAPI dokumentiert.
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die `ORJSONResponse` ist derzeit nur in FastAPI verfügbar, nicht in Starlette.
|
||||
|
||||
///
|
||||
|
||||
## HTML-Response
|
||||
|
||||
|
|
@ -52,12 +61,15 @@ Um eine Response mit HTML direkt von **FastAPI** zurückzugeben, verwenden Sie `
|
|||
{!../../../docs_src/custom_response/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren.
|
||||
/// info
|
||||
|
||||
In diesem Fall wird der HTTP-Header `Content-Type` auf `text/html` gesetzt.
|
||||
Der Parameter `response_class` wird auch verwendet, um den „Medientyp“ der Response zu definieren.
|
||||
|
||||
Und er wird als solcher in OpenAPI dokumentiert.
|
||||
In diesem Fall wird der HTTP-Header `Content-Type` auf `text/html` gesetzt.
|
||||
|
||||
Und er wird als solcher in OpenAPI dokumentiert.
|
||||
|
||||
///
|
||||
|
||||
### Eine `Response` zurückgeben
|
||||
|
||||
|
|
@ -69,11 +81,17 @@ Das gleiche Beispiel von oben, das eine `HTMLResponse` zurückgibt, könnte so a
|
|||
{!../../../docs_src/custom_response/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! warning "Achtung"
|
||||
Eine `Response`, die direkt von Ihrer *Pfadoperation-Funktion* zurückgegeben wird, wird in OpenAPI nicht dokumentiert (zum Beispiel wird der `Content-Type` nicht dokumentiert) und ist in der automatischen interaktiven Dokumentation nicht sichtbar.
|
||||
/// warning | "Achtung"
|
||||
|
||||
!!! info
|
||||
Natürlich stammen der eigentliche `Content-Type`-Header, der Statuscode, usw., aus dem `Response`-Objekt, das Sie zurückgegeben haben.
|
||||
Eine `Response`, die direkt von Ihrer *Pfadoperation-Funktion* zurückgegeben wird, wird in OpenAPI nicht dokumentiert (zum Beispiel wird der `Content-Type` nicht dokumentiert) und ist in der automatischen interaktiven Dokumentation nicht sichtbar.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
Natürlich stammen der eigentliche `Content-Type`-Header, der Statuscode, usw., aus dem `Response`-Objekt, das Sie zurückgegeben haben.
|
||||
|
||||
///
|
||||
|
||||
### In OpenAPI dokumentieren und `Response` überschreiben
|
||||
|
||||
|
|
@ -103,10 +121,13 @@ Hier sind einige der verfügbaren Responses.
|
|||
|
||||
Bedenken Sie, dass Sie `Response` verwenden können, um alles andere zurückzugeben, oder sogar eine benutzerdefinierte Unterklasse zu erstellen.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import HTMLResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette.responses import HTMLResponse` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
### `Response`
|
||||
|
||||
|
|
@ -153,15 +174,21 @@ Eine schnelle alternative JSON-Response mit <a href="https://github.com/ijl/orjs
|
|||
|
||||
Eine alternative JSON-Response mit <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
|
||||
|
||||
!!! warning "Achtung"
|
||||
`ujson` ist bei der Behandlung einiger Sonderfälle weniger sorgfältig als Pythons eingebaute Implementierung.
|
||||
/// warning | "Achtung"
|
||||
|
||||
`ujson` ist bei der Behandlung einiger Sonderfälle weniger sorgfältig als Pythons eingebaute Implementierung.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
{!../../../docs_src/custom_response/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Möglicherweise ist `ORJSONResponse` eine schnellere Alternative.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Möglicherweise ist `ORJSONResponse` eine schnellere Alternative.
|
||||
|
||||
///
|
||||
|
||||
### `RedirectResponse`
|
||||
|
||||
|
|
@ -222,8 +249,11 @@ Das umfasst viele Bibliotheken zur Interaktion mit Cloud-Speicher, Videoverarbei
|
|||
|
||||
Auf diese Weise können wir das Ganze in einen `with`-Block einfügen und so sicherstellen, dass das dateiartige Objekt nach Abschluss geschlossen wird.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass wir, da wir Standard-`open()` verwenden, welches `async` und `await` nicht unterstützt, hier die Pfadoperation mit normalen `def` deklarieren.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass wir, da wir Standard-`open()` verwenden, welches `async` und `await` nicht unterstützt, hier die Pfadoperation mit normalen `def` deklarieren.
|
||||
|
||||
///
|
||||
|
||||
### `FileResponse`
|
||||
|
||||
|
|
@ -292,8 +322,11 @@ Im folgenden Beispiel verwendet **FastAPI** standardmäßig `ORJSONResponse` in
|
|||
{!../../../docs_src/custom_response/tutorial010.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können dennoch weiterhin `response_class` in *Pfadoperationen* überschreiben, wie bisher.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können dennoch weiterhin `response_class` in *Pfadoperationen* überschreiben, wie bisher.
|
||||
|
||||
///
|
||||
|
||||
## Zusätzliche Dokumentation
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,15 @@ Und natürlich wird das gleiche unterstützt:
|
|||
|
||||
Das funktioniert genauso wie mit Pydantic-Modellen. Und tatsächlich wird es unter der Haube mittels Pydantic auf die gleiche Weise bewerkstelligt.
|
||||
|
||||
!!! info
|
||||
Bedenken Sie, dass Datenklassen nicht alles können, was Pydantic-Modelle können.
|
||||
/// info
|
||||
|
||||
Daher müssen Sie möglicherweise weiterhin Pydantic-Modelle verwenden.
|
||||
Bedenken Sie, dass Datenklassen nicht alles können, was Pydantic-Modelle können.
|
||||
|
||||
Wenn Sie jedoch eine Menge Datenklassen herumliegen haben, ist dies ein guter Trick, um sie für eine Web-API mithilfe von FastAPI zu verwenden. 🤓
|
||||
Daher müssen Sie möglicherweise weiterhin Pydantic-Modelle verwenden.
|
||||
|
||||
Wenn Sie jedoch eine Menge Datenklassen herumliegen haben, ist dies ein guter Trick, um sie für eine Web-API mithilfe von FastAPI zu verwenden. 🤓
|
||||
|
||||
///
|
||||
|
||||
## Datenklassen als `response_model`
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,13 @@ Hier simulieren wir das langsame *Hochfahren*, das Laden des Modells, indem wir
|
|||
|
||||
Und dann, direkt nach dem `yield`, entladen wir das Modell. Dieser Code wird unmittelbar vor dem *Herunterfahren* ausgeführt, **nachdem** die Anwendung **die Bearbeitung von Requests abgeschlossen hat**. Dadurch könnten beispielsweise Ressourcen wie Arbeitsspeicher oder eine GPU freigegeben werden.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Das *Herunterfahren* würde erfolgen, wenn Sie die Anwendung **stoppen**.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Möglicherweise müssen Sie eine neue Version starten, oder Sie haben es einfach satt, sie auszuführen. 🤷
|
||||
Das *Herunterfahren* würde erfolgen, wenn Sie die Anwendung **stoppen**.
|
||||
|
||||
Möglicherweise müssen Sie eine neue Version starten, oder Sie haben es einfach satt, sie auszuführen. 🤷
|
||||
|
||||
///
|
||||
|
||||
### Lifespan-Funktion
|
||||
|
||||
|
|
@ -91,10 +94,13 @@ Der Parameter `lifespan` der `FastAPI`-App benötigt einen **asynchronen Kontext
|
|||
|
||||
## Alternative Events (deprecated)
|
||||
|
||||
!!! warning "Achtung"
|
||||
Der empfohlene Weg, das *Hochfahren* und *Herunterfahren* zu handhaben, ist die Verwendung des `lifespan`-Parameters der `FastAPI`-App, wie oben beschrieben. Wenn Sie einen `lifespan`-Parameter übergeben, werden die `startup`- und `shutdown`-Eventhandler nicht mehr aufgerufen. Es ist entweder alles `lifespan` oder alles Events, nicht beides.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Sie können diesen Teil wahrscheinlich überspringen.
|
||||
Der empfohlene Weg, das *Hochfahren* und *Herunterfahren* zu handhaben, ist die Verwendung des `lifespan`-Parameters der `FastAPI`-App, wie oben beschrieben. Wenn Sie einen `lifespan`-Parameter übergeben, werden die `startup`- und `shutdown`-Eventhandler nicht mehr aufgerufen. Es ist entweder alles `lifespan` oder alles Events, nicht beides.
|
||||
|
||||
Sie können diesen Teil wahrscheinlich überspringen.
|
||||
|
||||
///
|
||||
|
||||
Es gibt eine alternative Möglichkeit, diese Logik zu definieren, sodass sie beim *Hochfahren* und beim *Herunterfahren* ausgeführt wird.
|
||||
|
||||
|
|
@ -126,17 +132,23 @@ Um eine Funktion hinzuzufügen, die beim Herunterfahren der Anwendung ausgeführ
|
|||
|
||||
Hier schreibt die `shutdown`-Eventhandler-Funktion eine Textzeile `"Application shutdown"` in eine Datei `log.txt`.
|
||||
|
||||
!!! info
|
||||
In der Funktion `open()` bedeutet `mode="a"` „append“ („anhängen“), sodass die Zeile nach dem, was sich in dieser Datei befindet, hinzugefügt wird, ohne den vorherigen Inhalt zu überschreiben.
|
||||
/// info
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass wir in diesem Fall eine Standard-Python-Funktion `open()` verwenden, die mit einer Datei interagiert.
|
||||
In der Funktion `open()` bedeutet `mode="a"` „append“ („anhängen“), sodass die Zeile nach dem, was sich in dieser Datei befindet, hinzugefügt wird, ohne den vorherigen Inhalt zu überschreiben.
|
||||
|
||||
Es handelt sich also um I/O (Input/Output), welches „Warten“ erfordert, bis Dinge auf die Festplatte geschrieben werden.
|
||||
///
|
||||
|
||||
Aber `open()` verwendet nicht `async` und `await`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Daher deklarieren wir die Eventhandler-Funktion mit Standard-`def` statt mit `async def`.
|
||||
Beachten Sie, dass wir in diesem Fall eine Standard-Python-Funktion `open()` verwenden, die mit einer Datei interagiert.
|
||||
|
||||
Es handelt sich also um I/O (Input/Output), welches „Warten“ erfordert, bis Dinge auf die Festplatte geschrieben werden.
|
||||
|
||||
Aber `open()` verwendet nicht `async` und `await`.
|
||||
|
||||
Daher deklarieren wir die Eventhandler-Funktion mit Standard-`def` statt mit `async def`.
|
||||
|
||||
///
|
||||
|
||||
### `startup` und `shutdown` zusammen
|
||||
|
||||
|
|
@ -152,10 +164,13 @@ Nur ein technisches Detail für die neugierigen Nerds. 🤓
|
|||
|
||||
In der technischen ASGI-Spezifikation ist dies Teil des <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Lifespan Protokolls</a> und definiert Events namens `startup` und `shutdown`.
|
||||
|
||||
!!! info
|
||||
Weitere Informationen zu Starlettes `lifespan`-Handlern finden Sie in <a href="https://www.starlette.io/lifespan/" class="external-link" target="_blank">Starlettes Lifespan-Dokumentation</a>.
|
||||
/// info
|
||||
|
||||
Einschließlich, wie man Lifespan-Zustand handhabt, der in anderen Bereichen Ihres Codes verwendet werden kann.
|
||||
Weitere Informationen zu Starlettes `lifespan`-Handlern finden Sie in <a href="https://www.starlette.io/lifespan/" class="external-link" target="_blank">Starlettes Lifespan-Dokumentation</a>.
|
||||
|
||||
Einschließlich, wie man Lifespan-Zustand handhabt, der in anderen Bereichen Ihres Codes verwendet werden kann.
|
||||
|
||||
///
|
||||
|
||||
## Unteranwendungen
|
||||
|
||||
|
|
|
|||
|
|
@ -28,17 +28,21 @@ Es gibt auch mehrere andere Unternehmen, welche ähnliche Dienste anbieten und d
|
|||
|
||||
Beginnen wir mit einer einfachen FastAPI-Anwendung:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="7-9 12-13 16-17 21"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
|
||||
```
|
||||
```Python hl_lines="7-9 12-13 16-17 21"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9-11 14-15 18 19 23"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9-11 14-15 18 19 23"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Beachten Sie, dass die *Pfadoperationen* die Modelle definieren, welche diese für die Request- und Response-<abbr title="Die eigentlichen Nutzdaten, abzüglich der Metadaten">Payload</abbr> verwenden, indem sie die Modelle `Item` und `ResponseMessage` verwenden.
|
||||
|
||||
|
|
@ -123,8 +127,11 @@ Sie erhalten außerdem automatische Vervollständigung für die zu sendende Payl
|
|||
|
||||
<img src="/img/tutorial/generate-clients/image03.png">
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie die automatische Vervollständigung für `name` und `price`, welche in der FastAPI-Anwendung im `Item`-Modell definiert wurden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie die automatische Vervollständigung für `name` und `price`, welche in der FastAPI-Anwendung im `Item`-Modell definiert wurden.
|
||||
|
||||
///
|
||||
|
||||
Sie erhalten Inline-Fehlerberichte für die von Ihnen gesendeten Daten:
|
||||
|
||||
|
|
@ -140,17 +147,21 @@ In vielen Fällen wird Ihre FastAPI-Anwendung größer sein und Sie werden wahrs
|
|||
|
||||
Beispielsweise könnten Sie einen Abschnitt für **Items (Artikel)** und einen weiteren Abschnitt für **Users (Benutzer)** haben, und diese könnten durch Tags getrennt sein:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="21 26 34"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
|
||||
```
|
||||
```Python hl_lines="21 26 34"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="23 28 36"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="23 28 36"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Einen TypeScript-Client mit Tags generieren
|
||||
|
||||
|
|
@ -197,17 +208,21 @@ Hier verwendet sie beispielsweise den ersten Tag (Sie werden wahrscheinlich nur
|
|||
|
||||
Anschließend können Sie diese benutzerdefinierte Funktion als Parameter `generate_unique_id_function` an **FastAPI** übergeben:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="6-7 10"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
|
||||
```
|
||||
```Python hl_lines="6-7 10"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8-9 12"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="8-9 12"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Einen TypeScript-Client mit benutzerdefinierten Operation-IDs generieren
|
||||
|
||||
|
|
@ -229,17 +244,21 @@ Aber für den generierten Client könnten wir die OpenAPI-Operation-IDs direkt v
|
|||
|
||||
Wir könnten das OpenAPI-JSON in eine Datei `openapi.json` herunterladen und dann mit einem Skript wie dem folgenden **den vorangestellten Tag entfernen**:
|
||||
|
||||
=== "Python"
|
||||
//// tab | Python
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/generate_clients/tutorial004.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/generate_clients/tutorial004.py!}
|
||||
```
|
||||
|
||||
=== "Node.js"
|
||||
////
|
||||
|
||||
```Javascript
|
||||
{!> ../../../docs_src/generate_clients/tutorial004.js!}
|
||||
```
|
||||
//// tab | Node.js
|
||||
|
||||
```Javascript
|
||||
{!> ../../../docs_src/generate_clients/tutorial004.js!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Damit würden die Operation-IDs von Dingen wie `items-get_items` in `get_items` umbenannt, sodass der Client-Generator einfachere Methodennamen generieren kann.
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@ Das Haupt-[Tutorial – Benutzerhandbuch](../tutorial/index.md){.internal-link t
|
|||
|
||||
In den nächsten Abschnitten sehen Sie weitere Optionen, Konfigurationen und zusätzliche Funktionen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die nächsten Abschnitte sind **nicht unbedingt „fortgeschritten“**.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon liegt.
|
||||
Die nächsten Abschnitte sind **nicht unbedingt „fortgeschritten“**.
|
||||
|
||||
Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon liegt.
|
||||
|
||||
///
|
||||
|
||||
## Lesen Sie zuerst das Tutorial
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,13 @@ app.add_middleware(UnicornMiddleware, some_config="rainbow")
|
|||
|
||||
**FastAPI** enthält mehrere Middlewares für gängige Anwendungsfälle. Wir werden als Nächstes sehen, wie man sie verwendet.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Für die nächsten Beispiele könnten Sie auch `from starlette.middleware.something import SomethingMiddleware` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet mehrere Middlewares via `fastapi.middleware` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Middlewares kommen aber direkt von Starlette.
|
||||
Für die nächsten Beispiele könnten Sie auch `from starlette.middleware.something import SomethingMiddleware` verwenden.
|
||||
|
||||
**FastAPI** bietet mehrere Middlewares via `fastapi.middleware` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Middlewares kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
## `HTTPSRedirectMiddleware`
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,11 @@ Dieser Teil ist ziemlich normal, der größte Teil des Codes ist Ihnen wahrschei
|
|||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Der Query-Parameter `callback_url` verwendet einen Pydantic-<a href="https://docs.pydantic.dev/latest/api/networks/" class="external-link" target="_blank">Url</a>-Typ.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Der Query-Parameter `callback_url` verwendet einen Pydantic-<a href="https://docs.pydantic.dev/latest/api/networks/" class="external-link" target="_blank">Url</a>-Typ.
|
||||
|
||||
///
|
||||
|
||||
Das einzig Neue ist `callbacks=invoices_callback_router.routes` als Argument für den *Pfadoperation-Dekorator*. Wir werden als Nächstes sehen, was das ist.
|
||||
|
||||
|
|
@ -61,10 +64,13 @@ Diese Dokumentation wird in der Swagger-Oberfläche unter `/docs` in Ihrer API a
|
|||
|
||||
In diesem Beispiel wird nicht der Callback selbst implementiert (das könnte nur eine Codezeile sein), sondern nur der Dokumentationsteil.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Der eigentliche Callback ist nur ein HTTP-Request.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie den Callback selbst implementieren, können Sie beispielsweise <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> oder <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a> verwenden.
|
||||
Der eigentliche Callback ist nur ein HTTP-Request.
|
||||
|
||||
Wenn Sie den Callback selbst implementieren, können Sie beispielsweise <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> oder <a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a> verwenden.
|
||||
|
||||
///
|
||||
|
||||
## Schreiben des Codes, der den Callback dokumentiert
|
||||
|
||||
|
|
@ -74,10 +80,13 @@ Sie wissen jedoch bereits, wie Sie mit **FastAPI** ganz einfach eine automatisch
|
|||
|
||||
Daher werden wir dasselbe Wissen nutzen, um zu dokumentieren, wie die *externe API* aussehen sollte ... indem wir die *Pfadoperation(en)* erstellen, welche die externe API implementieren soll (die, welche Ihre API aufruft).
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie den Code zum Dokumentieren eines Callbacks schreiben, kann es hilfreich sein, sich vorzustellen, dass Sie dieser *externe Entwickler* sind. Und dass Sie derzeit die *externe API* implementieren, nicht *Ihre API*.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie diese Sichtweise (des *externen Entwicklers*) vorübergehend übernehmen, wird es offensichtlicher, wo die Parameter, das Pydantic-Modell für den Body, die Response, usw. für diese *externe API* hingehören.
|
||||
Wenn Sie den Code zum Dokumentieren eines Callbacks schreiben, kann es hilfreich sein, sich vorzustellen, dass Sie dieser *externe Entwickler* sind. Und dass Sie derzeit die *externe API* implementieren, nicht *Ihre API*.
|
||||
|
||||
Wenn Sie diese Sichtweise (des *externen Entwicklers*) vorübergehend übernehmen, wird es offensichtlicher, wo die Parameter, das Pydantic-Modell für den Body, die Response, usw. für diese *externe API* hingehören.
|
||||
|
||||
///
|
||||
|
||||
### Einen Callback-`APIRouter` erstellen
|
||||
|
||||
|
|
@ -154,8 +163,11 @@ und sie würde eine Response von dieser *externen API* mit einem JSON-Body wie d
|
|||
}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-Parameter in `callback_url` (`https://www.external.org/events`) empfangen wurde, und auch die Rechnungs-`id` aus dem JSON-Body (`2expen51ve`).
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass die verwendete Callback-URL die URL enthält, die als Query-Parameter in `callback_url` (`https://www.external.org/events`) empfangen wurde, und auch die Rechnungs-`id` aus dem JSON-Body (`2expen51ve`).
|
||||
|
||||
///
|
||||
|
||||
### Den Callback-Router hinzufügen
|
||||
|
||||
|
|
@ -167,8 +179,11 @@ Verwenden Sie nun den Parameter `callbacks` im *Pfadoperation-Dekorator Ihrer AP
|
|||
{!../../../docs_src/openapi_callbacks/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callback=` übergeben, sondern das Attribut `.routes`, wie in `invoices_callback_router.routes`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass Sie nicht den Router selbst (`invoices_callback_router`) an `callback=` übergeben, sondern das Attribut `.routes`, wie in `invoices_callback_router.routes`.
|
||||
|
||||
///
|
||||
|
||||
### Es in der Dokumentation ansehen
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,11 @@ Mit **FastAPI** können Sie mithilfe von OpenAPI die Namen dieser Webhooks, die
|
|||
|
||||
Dies kann es Ihren Benutzern viel einfacher machen, **deren APIs zu implementieren**, um Ihre **Webhook**-Requests zu empfangen. Möglicherweise können diese sogar einen Teil des eigenem API-Codes automatisch generieren.
|
||||
|
||||
!!! info
|
||||
Webhooks sind in OpenAPI 3.1.0 und höher verfügbar und werden von FastAPI `0.99.0` und höher unterstützt.
|
||||
/// info
|
||||
|
||||
Webhooks sind in OpenAPI 3.1.0 und höher verfügbar und werden von FastAPI `0.99.0` und höher unterstützt.
|
||||
|
||||
///
|
||||
|
||||
## Eine Anwendung mit Webhooks
|
||||
|
||||
|
|
@ -35,8 +38,11 @@ Wenn Sie eine **FastAPI**-Anwendung erstellen, gibt es ein `webhooks`-Attribut,
|
|||
|
||||
Die von Ihnen definierten Webhooks landen im **OpenAPI**-Schema und der automatischen **Dokumentations-Oberfläche**.
|
||||
|
||||
!!! info
|
||||
Das `app.webhooks`-Objekt ist eigentlich nur ein `APIRouter`, derselbe Typ, den Sie verwenden würden, wenn Sie Ihre Anwendung mit mehreren Dateien strukturieren.
|
||||
/// info
|
||||
|
||||
Das `app.webhooks`-Objekt ist eigentlich nur ein `APIRouter`, derselbe Typ, den Sie verwenden würden, wenn Sie Ihre Anwendung mit mehreren Dateien strukturieren.
|
||||
|
||||
///
|
||||
|
||||
Beachten Sie, dass Sie bei Webhooks tatsächlich keinen *Pfad* (wie `/items/`) deklarieren, sondern dass der Text, den Sie dort übergeben, lediglich eine **Kennzeichnung** des Webhooks (der Name des Events) ist. Zum Beispiel ist in `@app.webhooks.post("new-subscription")` der Webhook-Name `new-subscription`.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
## OpenAPI operationId
|
||||
|
||||
!!! warning "Achtung"
|
||||
Wenn Sie kein „Experte“ für OpenAPI sind, brauchen Sie dies wahrscheinlich nicht.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Wenn Sie kein „Experte“ für OpenAPI sind, brauchen Sie dies wahrscheinlich nicht.
|
||||
|
||||
///
|
||||
|
||||
Mit dem Parameter `operation_id` können Sie die OpenAPI `operationId` festlegen, die in Ihrer *Pfadoperation* verwendet werden soll.
|
||||
|
||||
|
|
@ -23,13 +26,19 @@ Sie sollten dies tun, nachdem Sie alle Ihre *Pfadoperationen* hinzugefügt haben
|
|||
{!../../../docs_src/path_operation_advanced_configuration/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie `app.openapi()` manuell aufrufen, sollten Sie vorher die `operationId`s aktualisiert haben.
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! warning "Achtung"
|
||||
Wenn Sie dies tun, müssen Sie sicherstellen, dass jede Ihrer *Pfadoperation-Funktionen* einen eindeutigen Namen hat.
|
||||
Wenn Sie `app.openapi()` manuell aufrufen, sollten Sie vorher die `operationId`s aktualisiert haben.
|
||||
|
||||
Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden.
|
||||
///
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Wenn Sie dies tun, müssen Sie sicherstellen, dass jede Ihrer *Pfadoperation-Funktionen* einen eindeutigen Namen hat.
|
||||
|
||||
Auch wenn diese sich in unterschiedlichen Modulen (Python-Dateien) befinden.
|
||||
|
||||
///
|
||||
|
||||
## Von OpenAPI ausschließen
|
||||
|
||||
|
|
@ -65,8 +74,11 @@ Es gibt hier in der Dokumentation ein ganzes Kapitel darüber, Sie können es un
|
|||
|
||||
Wenn Sie in Ihrer Anwendung eine *Pfadoperation* deklarieren, generiert **FastAPI** automatisch die relevanten Metadaten dieser *Pfadoperation*, die in das OpenAPI-Schema aufgenommen werden sollen.
|
||||
|
||||
!!! note "Technische Details"
|
||||
In der OpenAPI-Spezifikation wird das <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Operationsobjekt</a> genannt.
|
||||
/// note | "Technische Details"
|
||||
|
||||
In der OpenAPI-Spezifikation wird das <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object" class="external-link" target="_blank">Operationsobjekt</a> genannt.
|
||||
|
||||
///
|
||||
|
||||
Es hat alle Informationen zur *Pfadoperation* und wird zur Erstellung der automatischen Dokumentation verwendet.
|
||||
|
||||
|
|
@ -74,10 +86,13 @@ Es enthält `tags`, `parameters`, `requestBody`, `responses`, usw.
|
|||
|
||||
Dieses *Pfadoperation*-spezifische OpenAPI-Schema wird normalerweise automatisch von **FastAPI** generiert, Sie können es aber auch erweitern.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Dies ist ein Low-Level Erweiterungspunkt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie nur zusätzliche Responses deklarieren müssen, können Sie dies bequemer mit [Zusätzliche Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} tun.
|
||||
Dies ist ein Low-Level Erweiterungspunkt.
|
||||
|
||||
Wenn Sie nur zusätzliche Responses deklarieren müssen, können Sie dies bequemer mit [Zusätzliche Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} tun.
|
||||
|
||||
///
|
||||
|
||||
Sie können das OpenAPI-Schema für eine *Pfadoperation* erweitern, indem Sie den Parameter `openapi_extra` verwenden.
|
||||
|
||||
|
|
@ -150,20 +165,27 @@ Und Sie könnten dies auch tun, wenn der Datentyp in der Anfrage nicht JSON ist.
|
|||
|
||||
In der folgenden Anwendung verwenden wir beispielsweise weder die integrierte Funktionalität von FastAPI zum Extrahieren des JSON-Schemas aus Pydantic-Modellen noch die automatische Validierung für JSON. Tatsächlich deklarieren wir den Request-Content-Type als YAML und nicht als JSON:
|
||||
|
||||
=== "Pydantic v2"
|
||||
//// tab | Pydantic v2
|
||||
|
||||
```Python hl_lines="17-22 24"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
|
||||
```
|
||||
```Python hl_lines="17-22 24"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
|
||||
```
|
||||
|
||||
=== "Pydantic v1"
|
||||
////
|
||||
|
||||
```Python hl_lines="17-22 24"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
|
||||
```
|
||||
//// tab | Pydantic v1
|
||||
|
||||
!!! info
|
||||
In Pydantic Version 1 hieß die Methode zum Abrufen des JSON-Schemas für ein Modell `Item.schema()`, in Pydantic Version 2 heißt die Methode `Item.model_json_schema()`.
|
||||
```Python hl_lines="17-22 24"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
In Pydantic Version 1 hieß die Methode zum Abrufen des JSON-Schemas für ein Modell `Item.schema()`, in Pydantic Version 2 heißt die Methode `Item.model_json_schema()`.
|
||||
|
||||
///
|
||||
|
||||
Obwohl wir nicht die standardmäßig integrierte Funktionalität verwenden, verwenden wir dennoch ein Pydantic-Modell, um das JSON-Schema für die Daten, die wir in YAML empfangen möchten, manuell zu generieren.
|
||||
|
||||
|
|
@ -171,22 +193,32 @@ Dann verwenden wir den Request direkt und extrahieren den Body als `bytes`. Das
|
|||
|
||||
Und dann parsen wir in unserem Code diesen YAML-Inhalt direkt und verwenden dann wieder dasselbe Pydantic-Modell, um den YAML-Inhalt zu validieren:
|
||||
|
||||
=== "Pydantic v2"
|
||||
//// tab | Pydantic v2
|
||||
|
||||
```Python hl_lines="26-33"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
|
||||
```
|
||||
```Python hl_lines="26-33"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007.py!}
|
||||
```
|
||||
|
||||
=== "Pydantic v1"
|
||||
////
|
||||
|
||||
```Python hl_lines="26-33"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
|
||||
```
|
||||
//// tab | Pydantic v1
|
||||
|
||||
!!! info
|
||||
In Pydantic Version 1 war die Methode zum Parsen und Validieren eines Objekts `Item.parse_obj()`, in Pydantic Version 2 heißt die Methode `Item.model_validate()`.
|
||||
```Python hl_lines="26-33"
|
||||
{!> ../../../docs_src/path_operation_advanced_configuration/tutorial007_pv1.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Hier verwenden wir dasselbe Pydantic-Modell wieder.
|
||||
////
|
||||
|
||||
Aber genauso hätten wir es auch auf andere Weise validieren können.
|
||||
/// info
|
||||
|
||||
In Pydantic Version 1 war die Methode zum Parsen und Validieren eines Objekts `Item.parse_obj()`, in Pydantic Version 2 heißt die Methode `Item.model_validate()`.
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Hier verwenden wir dasselbe Pydantic-Modell wieder.
|
||||
|
||||
Aber genauso hätten wir es auch auf andere Weise validieren können.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -30,20 +30,26 @@ Setzen Sie dann Cookies darin und geben Sie sie dann zurück:
|
|||
{!../../../docs_src/response_cookies/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass, wenn Sie eine Response direkt zurückgeben, anstatt den `Response`-Parameter zu verwenden, FastAPI diese direkt zurückgibt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie müssen also sicherstellen, dass Ihre Daten vom richtigen Typ sind. Z. B. sollten diese mit JSON kompatibel sein, wenn Sie eine `JSONResponse` zurückgeben.
|
||||
Beachten Sie, dass, wenn Sie eine Response direkt zurückgeben, anstatt den `Response`-Parameter zu verwenden, FastAPI diese direkt zurückgibt.
|
||||
|
||||
Und auch, dass Sie keine Daten senden, die durch ein `response_model` hätten gefiltert werden sollen.
|
||||
Sie müssen also sicherstellen, dass Ihre Daten vom richtigen Typ sind. Z. B. sollten diese mit JSON kompatibel sein, wenn Sie eine `JSONResponse` zurückgeben.
|
||||
|
||||
Und auch, dass Sie keine Daten senden, die durch ein `response_model` hätten gefiltert werden sollen.
|
||||
|
||||
///
|
||||
|
||||
### Mehr Informationen
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import Response` oder `from starlette.responses import JSONResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette.responses import Response` oder `from starlette.responses import JSONResponse` verwenden.
|
||||
|
||||
Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, stellt **FastAPI** diese auch unter `fastapi.Response` bereit.
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
|
||||
Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, stellt **FastAPI** diese auch unter `fastapi.Response` bereit.
|
||||
|
||||
///
|
||||
|
||||
Um alle verfügbaren Parameter und Optionen anzuzeigen, sehen Sie sich deren <a href="https://www.starlette.io/responses/#set-cookie" class="external-link" target="_blank">Dokumentation in Starlette</a> an.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,11 @@ Das kann beispielsweise nützlich sein, um benutzerdefinierte Header oder Cookie
|
|||
|
||||
Tatsächlich können Sie jede `Response` oder jede Unterklasse davon zurückgeben.
|
||||
|
||||
!!! tip "Tipp"
|
||||
`JSONResponse` selbst ist eine Unterklasse von `Response`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
`JSONResponse` selbst ist eine Unterklasse von `Response`.
|
||||
|
||||
///
|
||||
|
||||
Und wenn Sie eine `Response` zurückgeben, wird **FastAPI** diese direkt weiterleiten.
|
||||
|
||||
|
|
@ -35,10 +38,13 @@ In diesen Fällen können Sie den `jsonable_encoder` verwenden, um Ihre Daten zu
|
|||
{!../../../docs_src/response_directly/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import JSONResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette.responses import JSONResponse` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
## Eine benutzerdefinierte `Response` zurückgeben
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,15 @@ Erstellen Sie eine Response wie in [Eine Response direkt zurückgeben](response-
|
|||
{!../../../docs_src/response_headers/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import Response` oder `from starlette.responses import JSONResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette.responses import Response` oder `from starlette.responses import JSONResponse` verwenden.
|
||||
|
||||
Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, stellt **FastAPI** diese auch unter `fastapi.Response` bereit.
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
|
||||
Und da die `Response` häufig zum Setzen von Headern und Cookies verwendet wird, stellt **FastAPI** diese auch unter `fastapi.Response` bereit.
|
||||
|
||||
///
|
||||
|
||||
## Benutzerdefinierte Header
|
||||
|
||||
|
|
|
|||
|
|
@ -20,26 +20,35 @@ Wenn Sie dann den Benutzernamen und das Passwort eingeben, sendet der Browser di
|
|||
* Diese gibt ein Objekt vom Typ `HTTPBasicCredentials` zurück:
|
||||
* Es enthält den gesendeten `username` und das gesendete `password`.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="4 8 12"
|
||||
{!> ../../../docs_src/security/tutorial006_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="4 8 12"
|
||||
{!> ../../../docs_src/security/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="2 7 11"
|
||||
{!> ../../../docs_src/security/tutorial006_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="2 7 11"
|
||||
{!> ../../../docs_src/security/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="2 6 10"
|
||||
{!> ../../../docs_src/security/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 6 10"
|
||||
{!> ../../../docs_src/security/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Wenn Sie versuchen, die URL zum ersten Mal zu öffnen (oder in der Dokumentation auf den Button „Execute“ zu klicken), wird der Browser Sie nach Ihrem Benutzernamen und Passwort fragen:
|
||||
|
||||
|
|
@ -59,26 +68,35 @@ Um dies zu lösen, konvertieren wir zunächst den `username` und das `password`
|
|||
|
||||
Dann können wir `secrets.compare_digest()` verwenden, um sicherzustellen, dass `credentials.username` `"stanleyjobson"` und `credentials.password` `"swordfish"` ist.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="1 12-24"
|
||||
{!> ../../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="1 11-21"
|
||||
{!> ../../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 11-21"
|
||||
{!> ../../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Dies wäre das gleiche wie:
|
||||
|
||||
|
|
@ -142,23 +160,32 @@ So ist Ihr Anwendungscode, dank der Verwendung von `secrets.compare_digest()`, v
|
|||
|
||||
Nachdem Sie festgestellt haben, dass die Anmeldeinformationen falsch sind, geben Sie eine `HTTPException` mit dem Statuscode 401 zurück (derselbe, der auch zurückgegeben wird, wenn keine Anmeldeinformationen angegeben werden) und fügen den Header `WWW-Authenticate` hinzu, damit der Browser die Anmeldeaufforderung erneut anzeigt:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../../docs_src/security/tutorial007_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="26-30"
|
||||
{!> ../../../docs_src/security/tutorial007_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="23-27"
|
||||
{!> ../../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="23-27"
|
||||
{!> ../../../docs_src/security/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
|
|
|||
|
|
@ -4,10 +4,13 @@
|
|||
|
||||
Neben den in [Tutorial – Benutzerhandbuch: Sicherheit](../../tutorial/security/index.md){.internal-link target=_blank} behandelten Funktionen gibt es noch einige zusätzliche Funktionen zur Handhabung der Sicherheit.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die nächsten Abschnitte sind **nicht unbedingt „fortgeschritten“**.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon liegt.
|
||||
Die nächsten Abschnitte sind **nicht unbedingt „fortgeschritten“**.
|
||||
|
||||
Und es ist möglich, dass für Ihren Anwendungsfall die Lösung in einem davon liegt.
|
||||
|
||||
///
|
||||
|
||||
## Lesen Sie zuerst das Tutorial
|
||||
|
||||
|
|
|
|||
|
|
@ -10,18 +10,21 @@ Jedes Mal, wenn Sie sich mit Facebook, Google, GitHub, Microsoft oder Twitter an
|
|||
|
||||
In diesem Abschnitt erfahren Sie, wie Sie Authentifizierung und Autorisierung mit demselben OAuth2, mit Scopes in Ihrer **FastAPI**-Anwendung verwalten.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Dies ist ein mehr oder weniger fortgeschrittener Abschnitt. Wenn Sie gerade erst anfangen, können Sie ihn überspringen.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Sie benötigen nicht unbedingt OAuth2-Scopes, und Sie können die Authentifizierung und Autorisierung handhaben wie Sie möchten.
|
||||
Dies ist ein mehr oder weniger fortgeschrittener Abschnitt. Wenn Sie gerade erst anfangen, können Sie ihn überspringen.
|
||||
|
||||
Aber OAuth2 mit Scopes kann bequem in Ihre API (mit OpenAPI) und deren API-Dokumentation integriert werden.
|
||||
Sie benötigen nicht unbedingt OAuth2-Scopes, und Sie können die Authentifizierung und Autorisierung handhaben wie Sie möchten.
|
||||
|
||||
Dennoch, verwenden Sie solche Scopes oder andere Sicherheits-/Autorisierungsanforderungen in Ihrem Code so wie Sie es möchten.
|
||||
Aber OAuth2 mit Scopes kann bequem in Ihre API (mit OpenAPI) und deren API-Dokumentation integriert werden.
|
||||
|
||||
In vielen Fällen kann OAuth2 mit Scopes ein Overkill sein.
|
||||
Dennoch, verwenden Sie solche Scopes oder andere Sicherheits-/Autorisierungsanforderungen in Ihrem Code so wie Sie es möchten.
|
||||
|
||||
Aber wenn Sie wissen, dass Sie es brauchen oder neugierig sind, lesen Sie weiter.
|
||||
In vielen Fällen kann OAuth2 mit Scopes ein Overkill sein.
|
||||
|
||||
Aber wenn Sie wissen, dass Sie es brauchen oder neugierig sind, lesen Sie weiter.
|
||||
|
||||
///
|
||||
|
||||
## OAuth2-Scopes und OpenAPI
|
||||
|
||||
|
|
@ -43,63 +46,87 @@ Er wird normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu dekla
|
|||
* `instagram_basic` wird von Facebook / Instagram verwendet.
|
||||
* `https://www.googleapis.com/auth/drive` wird von Google verwendet.
|
||||
|
||||
!!! info
|
||||
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
|
||||
/// info
|
||||
|
||||
Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist.
|
||||
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
|
||||
|
||||
Diese Details sind implementierungsspezifisch.
|
||||
Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist.
|
||||
|
||||
Für OAuth2 sind es einfach nur Strings.
|
||||
Diese Details sind implementierungsspezifisch.
|
||||
|
||||
Für OAuth2 sind es einfach nur Strings.
|
||||
|
||||
///
|
||||
|
||||
## Gesamtübersicht
|
||||
|
||||
Sehen wir uns zunächst kurz die Teile an, die sich gegenüber den Beispielen im Haupt-**Tutorial – Benutzerhandbuch** für [OAuth2 mit Password (und Hashing), Bearer mit JWT-Tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} ändern. Diesmal verwenden wir OAuth2-Scopes:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="2 4 8 12 47 65 106 108-116 122-125 129-135 140 156"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="2 4 8 12 47 65 106 108-116 122-125 129-135 140 156"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3 7 11 45 63 104 106-114 120-123 127-133 138 154"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="3 7 11 45 63 104 106-114 120-123 127-133 138 154"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 4 8 12 46 64 105 107-115 121-124 128-134 139 155"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Sehen wir uns diese Änderungen nun Schritt für Schritt an.
|
||||
|
||||
|
|
@ -109,51 +136,71 @@ Die erste Änderung ist, dass wir jetzt das OAuth2-Sicherheitsschema mit zwei ve
|
|||
|
||||
Der `scopes`-Parameter erhält ein `dict` mit jedem Scope als Schlüssel und dessen Beschreibung als Wert:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="63-66"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="63-66"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="61-64"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="61-64"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="62-65"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Da wir diese Scopes jetzt deklarieren, werden sie in der API-Dokumentation angezeigt, wenn Sie sich einloggen/autorisieren.
|
||||
|
||||
|
|
@ -171,55 +218,79 @@ Wir verwenden immer noch dasselbe `OAuth2PasswordRequestForm`. Es enthält eine
|
|||
|
||||
Und wir geben die Scopes als Teil des JWT-Tokens zurück.
|
||||
|
||||
!!! danger "Gefahr"
|
||||
Der Einfachheit halber fügen wir hier die empfangenen Scopes direkt zum Token hinzu.
|
||||
/// danger | "Gefahr"
|
||||
|
||||
Aus Sicherheitsgründen sollten Sie jedoch sicherstellen, dass Sie in Ihrer Anwendung nur die Scopes hinzufügen, die der Benutzer tatsächlich haben kann, oder die Sie vordefiniert haben.
|
||||
Der Einfachheit halber fügen wir hier die empfangenen Scopes direkt zum Token hinzu.
|
||||
|
||||
=== "Python 3.10+"
|
||||
Aus Sicherheitsgründen sollten Sie jedoch sicherstellen, dass Sie in Ihrer Anwendung nur die Scopes hinzufügen, die der Benutzer tatsächlich haben kann, oder die Sie vordefiniert haben.
|
||||
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="156"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="154"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
```Python hl_lines="156"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
///
|
||||
|
||||
```Python hl_lines="154"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="155"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Scopes in *Pfadoperationen* und Abhängigkeiten deklarieren
|
||||
|
||||
|
|
@ -237,62 +308,89 @@ Und die Abhängigkeitsfunktion `get_current_active_user` kann auch Unterabhängi
|
|||
|
||||
In diesem Fall erfordert sie den Scope `me` (sie könnte mehr als einen Scope erfordern).
|
||||
|
||||
!!! note "Hinweis"
|
||||
Sie müssen nicht unbedingt an verschiedenen Stellen verschiedene Scopes hinzufügen.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Wir tun dies hier, um zu demonstrieren, wie **FastAPI** auf verschiedenen Ebenen deklarierte Scopes verarbeitet.
|
||||
Sie müssen nicht unbedingt an verschiedenen Stellen verschiedene Scopes hinzufügen.
|
||||
|
||||
=== "Python 3.10+"
|
||||
Wir tun dies hier, um zu demonstrieren, wie **FastAPI** auf verschiedenen Ebenen deklarierte Scopes verarbeitet.
|
||||
|
||||
```Python hl_lines="4 139 170"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4 139 170"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="4 139 170"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="4 140 171"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
```Python hl_lines="4 139 170"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="3 138 167"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
```Python hl_lines="4 140 171"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="4 139 168"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
```Python hl_lines="4 139 168"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
///
|
||||
|
||||
!!! info "Technische Details"
|
||||
`Security` ist tatsächlich eine Unterklasse von `Depends` und hat nur noch einen zusätzlichen Parameter, den wir später kennenlernen werden.
|
||||
```Python hl_lines="3 138 167"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
Durch die Verwendung von `Security` anstelle von `Depends` weiß **FastAPI** jedoch, dass es Sicherheits-Scopes deklarieren, intern verwenden und die API mit OpenAPI dokumentieren kann.
|
||||
////
|
||||
|
||||
Wenn Sie jedoch `Query`, `Path`, `Depends`, `Security` und andere von `fastapi` importieren, handelt es sich tatsächlich um Funktionen, die spezielle Klassen zurückgeben.
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4 139 168"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4 139 168"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info | "Technische Details"
|
||||
|
||||
`Security` ist tatsächlich eine Unterklasse von `Depends` und hat nur noch einen zusätzlichen Parameter, den wir später kennenlernen werden.
|
||||
|
||||
Durch die Verwendung von `Security` anstelle von `Depends` weiß **FastAPI** jedoch, dass es Sicherheits-Scopes deklarieren, intern verwenden und die API mit OpenAPI dokumentieren kann.
|
||||
|
||||
Wenn Sie jedoch `Query`, `Path`, `Depends`, `Security` und andere von `fastapi` importieren, handelt es sich tatsächlich um Funktionen, die spezielle Klassen zurückgeben.
|
||||
|
||||
///
|
||||
|
||||
## `SecurityScopes` verwenden
|
||||
|
||||
|
|
@ -308,50 +406,71 @@ Wir deklarieren auch einen speziellen Parameter vom Typ `SecurityScopes`, der au
|
|||
|
||||
Diese `SecurityScopes`-Klasse ähnelt `Request` (`Request` wurde verwendet, um das Request-Objekt direkt zu erhalten).
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="8 106"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="8 106"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7 104"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="7 104"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8 105"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Die `scopes` verwenden
|
||||
|
||||
|
|
@ -365,50 +484,71 @@ Wir erstellen eine `HTTPException`, die wir später an mehreren Stellen wiederve
|
|||
|
||||
In diese Exception fügen wir (falls vorhanden) die erforderlichen Scopes als durch Leerzeichen getrennten String ein (unter Verwendung von `scope_str`). Wir fügen diesen String mit den Scopes in den Header `WWW-Authenticate` ein (das ist Teil der Spezifikation).
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="106 108-116"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="106 108-116"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="104 106-114"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="104 106-114"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="105 107-115"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Den `username` und das Format der Daten überprüfen
|
||||
|
||||
|
|
@ -424,50 +564,71 @@ Anstelle beispielsweise eines `dict`s oder etwas anderem, was später in der Anw
|
|||
|
||||
Wir verifizieren auch, dass wir einen Benutzer mit diesem Benutzernamen haben, und wenn nicht, lösen wir dieselbe Exception aus, die wir zuvor erstellt haben.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="47 117-128"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="47 117-128"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="45 115-126"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="45 115-126"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="46 116-127"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Die `scopes` verifizieren
|
||||
|
||||
|
|
@ -475,50 +636,71 @@ Wir überprüfen nun, ob das empfangenen Token alle Scopes enthält, die von die
|
|||
|
||||
Hierzu verwenden wir `security_scopes.scopes`, das eine `list`e mit allen diesen Scopes als `str` enthält.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="129-135"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="129-135"
|
||||
{!> ../../../docs_src/security/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="127-133"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="127-133"
|
||||
{!> ../../../docs_src/security/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="128-134"
|
||||
{!> ../../../docs_src/security/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Abhängigkeitsbaum und Scopes
|
||||
|
||||
|
|
@ -545,10 +727,13 @@ So sieht die Hierarchie der Abhängigkeiten und Scopes aus:
|
|||
* `security_scopes.scopes` enthält `["me"]` für die *Pfadoperation* `read_users_me`, da das in der Abhängigkeit `get_current_active_user` deklariert ist.
|
||||
* `security_scopes.scopes` wird `[]` (nichts) für die *Pfadoperation* `read_system_status` enthalten, da diese keine `Security` mit `scopes` deklariert hat, und deren Abhängigkeit `get_current_user` ebenfalls keinerlei `scopes` deklariert.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Das Wichtige und „Magische“ hier ist, dass `get_current_user` für jede *Pfadoperation* eine andere Liste von `scopes` hat, die überprüft werden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Alles hängt von den „Scopes“ ab, die in jeder *Pfadoperation* und jeder Abhängigkeit im Abhängigkeitsbaum für diese bestimmte *Pfadoperation* deklariert wurden.
|
||||
Das Wichtige und „Magische“ hier ist, dass `get_current_user` für jede *Pfadoperation* eine andere Liste von `scopes` hat, die überprüft werden.
|
||||
|
||||
Alles hängt von den „Scopes“ ab, die in jeder *Pfadoperation* und jeder Abhängigkeit im Abhängigkeitsbaum für diese bestimmte *Pfadoperation* deklariert wurden.
|
||||
|
||||
///
|
||||
|
||||
## Weitere Details zu `SecurityScopes`.
|
||||
|
||||
|
|
@ -586,10 +771,13 @@ Am häufigsten ist der „Implicit“-Flow.
|
|||
|
||||
Am sichersten ist der „Code“-Flow, die Implementierung ist jedoch komplexer, da mehr Schritte erforderlich sind. Da er komplexer ist, schlagen viele Anbieter letztendlich den „Implicit“-Flow vor.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Es ist üblich, dass jeder Authentifizierungsanbieter seine Flows anders benennt, um sie zu einem Teil seiner Marke zu machen.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Aber am Ende implementieren sie denselben OAuth2-Standard.
|
||||
Es ist üblich, dass jeder Authentifizierungsanbieter seine Flows anders benennt, um sie zu einem Teil seiner Marke zu machen.
|
||||
|
||||
Aber am Ende implementieren sie denselben OAuth2-Standard.
|
||||
|
||||
///
|
||||
|
||||
**FastAPI** enthält Werkzeuge für alle diese OAuth2-Authentifizierungs-Flows in `fastapi.security.oauth2`.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,44 +8,51 @@ Aus diesem Grund werden diese üblicherweise in Umgebungsvariablen bereitgestell
|
|||
|
||||
## Umgebungsvariablen
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie bereits wissen, was „Umgebungsvariablen“ sind und wie man sie verwendet, können Sie gerne mit dem nächsten Abschnitt weiter unten fortfahren.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie bereits wissen, was „Umgebungsvariablen“ sind und wie man sie verwendet, können Sie gerne mit dem nächsten Abschnitt weiter unten fortfahren.
|
||||
|
||||
///
|
||||
|
||||
Eine <a href="https://de.wikipedia.org/wiki/Umgebungsvariable" class="external-link" target="_blank">Umgebungsvariable</a> (auch bekannt als „env var“) ist eine Variable, die sich außerhalb des Python-Codes im Betriebssystem befindet und von Ihrem Python-Code (oder auch von anderen Programmen) gelesen werden kann.
|
||||
|
||||
Sie können Umgebungsvariablen in der Shell erstellen und verwenden, ohne Python zu benötigen:
|
||||
|
||||
=== "Linux, macOS, Windows Bash"
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
|
||||
<div class="termy">
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
// Sie könnten eine Umgebungsvariable MY_NAME erstellen mittels
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
```console
|
||||
// Sie könnten eine Umgebungsvariable MY_NAME erstellen mittels
|
||||
$ export MY_NAME="Wade Wilson"
|
||||
|
||||
// Dann könnten Sie diese mit anderen Programmen verwenden, etwa
|
||||
$ echo "Hello $MY_NAME"
|
||||
// Dann könnten Sie diese mit anderen Programmen verwenden, etwa
|
||||
$ echo "Hello $MY_NAME"
|
||||
|
||||
Hello Wade Wilson
|
||||
```
|
||||
Hello Wade Wilson
|
||||
```
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
=== "Windows PowerShell"
|
||||
////
|
||||
|
||||
<div class="termy">
|
||||
//// tab | Windows PowerShell
|
||||
|
||||
```console
|
||||
// Erstelle eine Umgebungsvariable MY_NAME
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
<div class="termy">
|
||||
|
||||
// Verwende sie mit anderen Programmen, etwa
|
||||
$ echo "Hello $Env:MY_NAME"
|
||||
```console
|
||||
// Erstelle eine Umgebungsvariable MY_NAME
|
||||
$ $Env:MY_NAME = "Wade Wilson"
|
||||
|
||||
Hello Wade Wilson
|
||||
```
|
||||
// Verwende sie mit anderen Programmen, etwa
|
||||
$ echo "Hello $Env:MY_NAME"
|
||||
|
||||
</div>
|
||||
Hello Wade Wilson
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
### Umgebungsvariablen mit Python auslesen
|
||||
|
||||
|
|
@ -60,10 +67,13 @@ name = os.getenv("MY_NAME", "World")
|
|||
print(f"Hello {name} from Python")
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Das zweite Argument für <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> ist der zurückzugebende Defaultwert.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn nicht angegeben, ist er standardmäßig `None`. Hier übergeben wir `"World"` als Defaultwert.
|
||||
Das zweite Argument für <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> ist der zurückzugebende Defaultwert.
|
||||
|
||||
Wenn nicht angegeben, ist er standardmäßig `None`. Hier übergeben wir `"World"` als Defaultwert.
|
||||
|
||||
///
|
||||
|
||||
Dann könnten Sie dieses Python-Programm aufrufen:
|
||||
|
||||
|
|
@ -114,8 +124,11 @@ Hello World from Python
|
|||
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Weitere Informationen dazu finden Sie unter <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Weitere Informationen dazu finden Sie unter <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>.
|
||||
|
||||
///
|
||||
|
||||
### Typen und Validierung
|
||||
|
||||
|
|
@ -151,8 +164,11 @@ $ pip install "fastapi[all]"
|
|||
|
||||
</div>
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 war das im Hauptpackage enthalten. Jetzt wird es als unabhängiges Package verteilt, sodass Sie wählen können, ob Sie es installieren möchten oder nicht, falls Sie die Funktionalität nicht benötigen.
|
||||
/// info
|
||||
|
||||
In Pydantic v1 war das im Hauptpackage enthalten. Jetzt wird es als unabhängiges Package verteilt, sodass Sie wählen können, ob Sie es installieren möchten oder nicht, falls Sie die Funktionalität nicht benötigen.
|
||||
|
||||
///
|
||||
|
||||
### Das `Settings`-Objekt erstellen
|
||||
|
||||
|
|
@ -162,23 +178,33 @@ Auf die gleiche Weise wie bei Pydantic-Modellen deklarieren Sie Klassenattribute
|
|||
|
||||
Sie können dieselben Validierungs-Funktionen und -Tools verwenden, die Sie für Pydantic-Modelle verwenden, z. B. verschiedene Datentypen und zusätzliche Validierungen mit `Field()`.
|
||||
|
||||
=== "Pydantic v2"
|
||||
//// tab | Pydantic v2
|
||||
|
||||
```Python hl_lines="2 5-8 11"
|
||||
{!> ../../../docs_src/settings/tutorial001.py!}
|
||||
```
|
||||
```Python hl_lines="2 5-8 11"
|
||||
{!> ../../../docs_src/settings/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "Pydantic v1"
|
||||
////
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 würden Sie `BaseSettings` direkt von `pydantic` statt von `pydantic_settings` importieren.
|
||||
//// tab | Pydantic v1
|
||||
|
||||
```Python hl_lines="2 5-8 11"
|
||||
{!> ../../../docs_src/settings/tutorial001_pv1.py!}
|
||||
```
|
||||
/// info
|
||||
|
||||
!!! tip "Tipp"
|
||||
Für ein schnelles Copy-and-paste verwenden Sie nicht dieses Beispiel, sondern das letzte unten.
|
||||
In Pydantic v1 würden Sie `BaseSettings` direkt von `pydantic` statt von `pydantic_settings` importieren.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 5-8 11"
|
||||
{!> ../../../docs_src/settings/tutorial001_pv1.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Für ein schnelles Copy-and-paste verwenden Sie nicht dieses Beispiel, sondern das letzte unten.
|
||||
|
||||
///
|
||||
|
||||
Wenn Sie dann eine Instanz dieser `Settings`-Klasse erstellen (in diesem Fall als `settings`-Objekt), liest Pydantic die Umgebungsvariablen ohne Berücksichtigung der Groß- und Kleinschreibung. Eine Variable `APP_NAME` in Großbuchstaben wird also als Attribut `app_name` gelesen.
|
||||
|
||||
|
|
@ -206,8 +232,11 @@ $ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" uvicorn main:app
|
|||
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um mehrere Umgebungsvariablen für einen einzelnen Befehl festzulegen, trennen Sie diese einfach durch ein Leerzeichen und fügen Sie alle vor dem Befehl ein.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um mehrere Umgebungsvariablen für einen einzelnen Befehl festzulegen, trennen Sie diese einfach durch ein Leerzeichen und fügen Sie alle vor dem Befehl ein.
|
||||
|
||||
///
|
||||
|
||||
Und dann würde die Einstellung `admin_email` auf `"deadpool@example.com"` gesetzt.
|
||||
|
||||
|
|
@ -231,8 +260,11 @@ Und dann verwenden Sie diese in einer Datei `main.py`:
|
|||
{!../../../docs_src/settings/app01/main.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie benötigen außerdem eine Datei `__init__.py`, wie in [Größere Anwendungen – mehrere Dateien](../tutorial/bigger-applications.md){.internal-link target=_blank} gesehen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie benötigen außerdem eine Datei `__init__.py`, wie in [Größere Anwendungen – mehrere Dateien](../tutorial/bigger-applications.md){.internal-link target=_blank} gesehen.
|
||||
|
||||
///
|
||||
|
||||
## Einstellungen in einer Abhängigkeit
|
||||
|
||||
|
|
@ -254,54 +286,75 @@ Beachten Sie, dass wir jetzt keine Standardinstanz `settings = Settings()` erste
|
|||
|
||||
Jetzt erstellen wir eine Abhängigkeit, die ein neues `config.Settings()` zurückgibt.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="6 12-13"
|
||||
{!> ../../../docs_src/settings/app02_an_py39/main.py!}
|
||||
```
|
||||
```Python hl_lines="6 12-13"
|
||||
{!> ../../../docs_src/settings/app02_an_py39/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="6 12-13"
|
||||
{!> ../../../docs_src/settings/app02_an/main.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="6 12-13"
|
||||
{!> ../../../docs_src/settings/app02_an/main.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="5 11-12"
|
||||
{!> ../../../docs_src/settings/app02/main.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wir werden das `@lru_cache` in Kürze besprechen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Im Moment nehmen Sie an, dass `get_settings()` eine normale Funktion ist.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="5 11-12"
|
||||
{!> ../../../docs_src/settings/app02/main.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wir werden das `@lru_cache` in Kürze besprechen.
|
||||
|
||||
Im Moment nehmen Sie an, dass `get_settings()` eine normale Funktion ist.
|
||||
|
||||
///
|
||||
|
||||
Und dann können wir das von der *Pfadoperation-Funktion* als Abhängigkeit einfordern und es überall dort verwenden, wo wir es brauchen.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="17 19-21"
|
||||
{!> ../../../docs_src/settings/app02_an_py39/main.py!}
|
||||
```
|
||||
```Python hl_lines="17 19-21"
|
||||
{!> ../../../docs_src/settings/app02_an_py39/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17 19-21"
|
||||
{!> ../../../docs_src/settings/app02_an/main.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="17 19-21"
|
||||
{!> ../../../docs_src/settings/app02_an/main.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="16 18-20"
|
||||
{!> ../../../docs_src/settings/app02/main.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="16 18-20"
|
||||
{!> ../../../docs_src/settings/app02/main.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Einstellungen und Tests
|
||||
|
||||
|
|
@ -321,15 +374,21 @@ Wenn Sie viele Einstellungen haben, die sich möglicherweise oft ändern, vielle
|
|||
|
||||
Diese Praxis ist so weit verbreitet, dass sie einen Namen hat. Diese Umgebungsvariablen werden üblicherweise in einer Datei `.env` abgelegt und die Datei wird „dotenv“ genannt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Eine Datei, die mit einem Punkt (`.`) beginnt, ist eine versteckte Datei in Unix-ähnlichen Systemen wie Linux und macOS.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Aber eine dotenv-Datei muss nicht unbedingt genau diesen Dateinamen haben.
|
||||
Eine Datei, die mit einem Punkt (`.`) beginnt, ist eine versteckte Datei in Unix-ähnlichen Systemen wie Linux und macOS.
|
||||
|
||||
Aber eine dotenv-Datei muss nicht unbedingt genau diesen Dateinamen haben.
|
||||
|
||||
///
|
||||
|
||||
Pydantic unterstützt das Lesen dieser Dateitypen mithilfe einer externen Bibliothek. Weitere Informationen finden Sie unter <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a>.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Damit das funktioniert, müssen Sie `pip install python-dotenv` ausführen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Damit das funktioniert, müssen Sie `pip install python-dotenv` ausführen.
|
||||
|
||||
///
|
||||
|
||||
### Die `.env`-Datei
|
||||
|
||||
|
|
@ -344,26 +403,39 @@ APP_NAME="ChimichangApp"
|
|||
|
||||
Und dann aktualisieren Sie Ihre `config.py` mit:
|
||||
|
||||
=== "Pydantic v2"
|
||||
//// tab | Pydantic v2
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/settings/app03_an/config.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/settings/app03_an/config.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Configuration</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
=== "Pydantic v1"
|
||||
Das Attribut `model_config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Configuration</a>.
|
||||
|
||||
```Python hl_lines="9-10"
|
||||
{!> ../../../docs_src/settings/app03_an/config_pv1.py!}
|
||||
```
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die Klasse `Config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>.
|
||||
////
|
||||
|
||||
!!! info
|
||||
In Pydantic Version 1 erfolgte die Konfiguration in einer internen Klasse `Config`, in Pydantic Version 2 erfolgt sie in einem Attribut `model_config`. Dieses Attribut akzeptiert ein `dict`. Um automatische Codevervollständigung und Inline-Fehlerberichte zu erhalten, können Sie `SettingsConfigDict` importieren und verwenden, um dieses `dict` zu definieren.
|
||||
//// tab | Pydantic v1
|
||||
|
||||
```Python hl_lines="9-10"
|
||||
{!> ../../../docs_src/settings/app03_an/config_pv1.py!}
|
||||
```
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die Klasse `Config` wird nur für die Pydantic-Konfiguration verwendet. Weitere Informationen finden Sie unter <a href="https://docs.pydantic.dev/1.10/usage/model_config/" class="external-link" target="_blank">Pydantic Model Config</a>.
|
||||
|
||||
///
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
In Pydantic Version 1 erfolgte die Konfiguration in einer internen Klasse `Config`, in Pydantic Version 2 erfolgt sie in einem Attribut `model_config`. Dieses Attribut akzeptiert ein `dict`. Um automatische Codevervollständigung und Inline-Fehlerberichte zu erhalten, können Sie `SettingsConfigDict` importieren und verwenden, um dieses `dict` zu definieren.
|
||||
|
||||
///
|
||||
|
||||
Hier definieren wir die Konfiguration `env_file` innerhalb Ihrer Pydantic-`Settings`-Klasse und setzen den Wert auf den Dateinamen mit der dotenv-Datei, die wir verwenden möchten.
|
||||
|
||||
|
|
@ -390,26 +462,35 @@ würden wir dieses Objekt für jeden Request erstellen und die `.env`-Datei für
|
|||
|
||||
Da wir jedoch den `@lru_cache`-Dekorator oben verwenden, wird das `Settings`-Objekt nur einmal erstellt, nämlich beim ersten Aufruf. ✔️
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1 11"
|
||||
{!> ../../../docs_src/settings/app03_an_py39/main.py!}
|
||||
```
|
||||
```Python hl_lines="1 11"
|
||||
{!> ../../../docs_src/settings/app03_an_py39/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 11"
|
||||
{!> ../../../docs_src/settings/app03_an/main.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="1 11"
|
||||
{!> ../../../docs_src/settings/app03_an/main.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="1 10"
|
||||
{!> ../../../docs_src/settings/app03/main.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 10"
|
||||
{!> ../../../docs_src/settings/app03/main.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Dann wird bei allen nachfolgenden Aufrufen von `get_settings()`, in den Abhängigkeiten für darauffolgende Requests, dasselbe Objekt zurückgegeben, das beim ersten Aufruf zurückgegeben wurde, anstatt den Code von `get_settings()` erneut auszuführen und ein neues `Settings`-Objekt zu erstellen.
|
||||
|
||||
|
|
|
|||
|
|
@ -31,18 +31,27 @@ $ pip install jinja2
|
|||
{!../../../docs_src/templates/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Vor FastAPI 0.108.0 und Starlette 0.29.0 war `name` der erste Parameter.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Außerdem wurde in früheren Versionen das `request`-Objekt als Teil der Schlüssel-Wert-Paare im Kontext für Jinja2 übergeben.
|
||||
Vor FastAPI 0.108.0 und Starlette 0.29.0 war `name` der erste Parameter.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Durch die Deklaration von `response_class=HTMLResponse` kann die Dokumentationsoberfläche erkennen, dass die Response HTML sein wird.
|
||||
Außerdem wurde in früheren Versionen das `request`-Objekt als Teil der Schlüssel-Wert-Paare im Kontext für Jinja2 übergeben.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.templating import Jinja2Templates` verwenden.
|
||||
///
|
||||
|
||||
**FastAPI** bietet dasselbe `starlette.templating` auch via `fastapi.templating` an, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber direkt von Starlette. Das Gleiche gilt für `Request` und `StaticFiles`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Durch die Deklaration von `response_class=HTMLResponse` kann die Dokumentationsoberfläche erkennen, dass die Response HTML sein wird.
|
||||
|
||||
///
|
||||
|
||||
/// note | "Technische Details"
|
||||
|
||||
Sie können auch `from starlette.templating import Jinja2Templates` verwenden.
|
||||
|
||||
**FastAPI** bietet dasselbe `starlette.templating` auch via `fastapi.templating` an, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber direkt von Starlette. Das Gleiche gilt für `Request` und `StaticFiles`.
|
||||
|
||||
///
|
||||
|
||||
## Templates erstellen
|
||||
|
||||
|
|
|
|||
|
|
@ -28,48 +28,67 @@ Um eine Abhängigkeit für das Testen zu überschreiben, geben Sie als Schlüsse
|
|||
|
||||
Und dann ruft **FastAPI** diese Überschreibung anstelle der ursprünglichen Abhängigkeit auf.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="26-27 30"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="26-27 30"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="28-29 32"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="28-29 32"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="29-30 33"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="29-30 33"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="24-25 28"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="28-29 32"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können eine Überschreibung für eine Abhängigkeit festlegen, die an einer beliebigen Stelle in Ihrer **FastAPI**-Anwendung verwendet wird.
|
||||
///
|
||||
|
||||
Die ursprüngliche Abhängigkeit könnte in einer *Pfadoperation-Funktion*, einem *Pfadoperation-Dekorator* (wenn Sie den Rückgabewert nicht verwenden), einem `.include_router()`-Aufruf, usw. verwendet werden.
|
||||
```Python hl_lines="24-25 28"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
FastAPI kann sie in jedem Fall überschreiben.
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="28-29 32"
|
||||
{!> ../../../docs_src/dependency_testing/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können eine Überschreibung für eine Abhängigkeit festlegen, die an einer beliebigen Stelle in Ihrer **FastAPI**-Anwendung verwendet wird.
|
||||
|
||||
Die ursprüngliche Abhängigkeit könnte in einer *Pfadoperation-Funktion*, einem *Pfadoperation-Dekorator* (wenn Sie den Rückgabewert nicht verwenden), einem `.include_router()`-Aufruf, usw. verwendet werden.
|
||||
|
||||
FastAPI kann sie in jedem Fall überschreiben.
|
||||
|
||||
///
|
||||
|
||||
Anschließend können Sie Ihre Überschreibungen zurücksetzen (entfernen), indem Sie `app.dependency_overrides` auf ein leeres `dict` setzen:
|
||||
|
||||
|
|
@ -77,5 +96,8 @@ Anschließend können Sie Ihre Überschreibungen zurücksetzen (entfernen), inde
|
|||
app.dependency_overrides = {}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie eine Abhängigkeit nur während einiger Tests überschreiben möchten, können Sie die Überschreibung zu Beginn des Tests (innerhalb der Testfunktion) festlegen und am Ende (am Ende der Testfunktion) zurücksetzen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie eine Abhängigkeit nur während einiger Tests überschreiben möchten, können Sie die Überschreibung zu Beginn des Tests (innerhalb der Testfunktion) festlegen und am Ende (am Ende der Testfunktion) zurücksetzen.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -8,5 +8,8 @@ Dazu verwenden Sie den `TestClient` in einer `with`-Anweisung, eine Verbindung z
|
|||
{!../../../docs_src/app_testing/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Weitere Informationen finden Sie in der Starlette-Dokumentation zum <a href="https://www.starlette.io/testclient/#testing-websocket-sessions" class="external-link" target="_blank">Testen von WebSockets</a>.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Weitere Informationen finden Sie in der Starlette-Dokumentation zum <a href="https://www.starlette.io/testclient/#testing-websocket-sessions" class="external-link" target="_blank">Testen von WebSockets</a>.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -35,18 +35,24 @@ Dazu müssen Sie direkt auf den Request zugreifen.
|
|||
|
||||
Durch die Deklaration eines *Pfadoperation-Funktionsparameters*, dessen Typ der `Request` ist, weiß **FastAPI**, dass es den `Request` diesem Parameter übergeben soll.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass wir in diesem Fall einen Pfad-Parameter zusätzlich zum Request-Parameter deklarieren.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Der Pfad-Parameter wird also extrahiert, validiert, in den spezifizierten Typ konvertiert und mit OpenAPI annotiert.
|
||||
Beachten Sie, dass wir in diesem Fall einen Pfad-Parameter zusätzlich zum Request-Parameter deklarieren.
|
||||
|
||||
Auf die gleiche Weise können Sie wie gewohnt jeden anderen Parameter deklarieren und zusätzlich auch den `Request` erhalten.
|
||||
Der Pfad-Parameter wird also extrahiert, validiert, in den spezifizierten Typ konvertiert und mit OpenAPI annotiert.
|
||||
|
||||
Auf die gleiche Weise können Sie wie gewohnt jeden anderen Parameter deklarieren und zusätzlich auch den `Request` erhalten.
|
||||
|
||||
///
|
||||
|
||||
## `Request`-Dokumentation
|
||||
|
||||
Weitere Details zum <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">`Request`-Objekt finden Sie in der offiziellen Starlette-Dokumentation</a>.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.requests import Request` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** stellt es direkt zur Verfügung, als Komfort für Sie, den Entwickler. Es kommt aber direkt von Starlette.
|
||||
Sie können auch `from starlette.requests import Request` verwenden.
|
||||
|
||||
**FastAPI** stellt es direkt zur Verfügung, als Komfort für Sie, den Entwickler. Es kommt aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -50,10 +50,13 @@ Erstellen Sie in Ihrer **FastAPI**-Anwendung einen `websocket`:
|
|||
{!../../../docs_src/websockets/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.websockets import WebSocket` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** stellt den gleichen `WebSocket` direkt zur Verfügung, als Annehmlichkeit für Sie, den Entwickler. Er kommt aber direkt von Starlette.
|
||||
Sie können auch `from starlette.websockets import WebSocket` verwenden.
|
||||
|
||||
**FastAPI** stellt den gleichen `WebSocket` direkt zur Verfügung, als Annehmlichkeit für Sie, den Entwickler. Er kommt aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
## Nachrichten erwarten und Nachrichten senden
|
||||
|
||||
|
|
@ -112,46 +115,65 @@ In WebSocket-Endpunkten können Sie Folgendes aus `fastapi` importieren und verw
|
|||
|
||||
Diese funktionieren auf die gleiche Weise wie für andere FastAPI-Endpunkte/*Pfadoperationen*:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="68-69 82"
|
||||
{!> ../../../docs_src/websockets/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="68-69 82"
|
||||
{!> ../../../docs_src/websockets/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="68-69 82"
|
||||
{!> ../../../docs_src/websockets/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="68-69 82"
|
||||
{!> ../../../docs_src/websockets/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="69-70 83"
|
||||
{!> ../../../docs_src/websockets/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="69-70 83"
|
||||
{!> ../../../docs_src/websockets/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="66-67 79"
|
||||
{!> ../../../docs_src/websockets/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="68-69 81"
|
||||
{!> ../../../docs_src/websockets/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! info
|
||||
Da es sich um einen WebSocket handelt, macht es keinen Sinn, eine `HTTPException` auszulösen, stattdessen lösen wir eine `WebSocketException` aus.
|
||||
///
|
||||
|
||||
Sie können einen „Closing“-Code verwenden, aus den <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">gültigen Codes, die in der Spezifikation definiert sind</a>.
|
||||
```Python hl_lines="66-67 79"
|
||||
{!> ../../../docs_src/websockets/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="68-69 81"
|
||||
{!> ../../../docs_src/websockets/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
Da es sich um einen WebSocket handelt, macht es keinen Sinn, eine `HTTPException` auszulösen, stattdessen lösen wir eine `WebSocketException` aus.
|
||||
|
||||
Sie können einen „Closing“-Code verwenden, aus den <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1" class="external-link" target="_blank">gültigen Codes, die in der Spezifikation definiert sind</a>.
|
||||
|
||||
///
|
||||
|
||||
### WebSockets mit Abhängigkeiten ausprobieren
|
||||
|
||||
|
|
@ -174,8 +196,11 @@ Dort können Sie einstellen:
|
|||
* Die „Item ID“, die im Pfad verwendet wird.
|
||||
* Das „Token“, das als Query-Parameter verwendet wird.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass der Query-„Token“ von einer Abhängigkeit verarbeitet wird.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass der Query-„Token“ von einer Abhängigkeit verarbeitet wird.
|
||||
|
||||
///
|
||||
|
||||
Damit können Sie den WebSocket verbinden und dann Nachrichten senden und empfangen:
|
||||
|
||||
|
|
@ -185,17 +210,21 @@ Damit können Sie den WebSocket verbinden und dann Nachrichten senden und empfan
|
|||
|
||||
Wenn eine WebSocket-Verbindung geschlossen wird, löst `await websocket.receive_text()` eine `WebSocketDisconnect`-Exception aus, die Sie dann wie in folgendem Beispiel abfangen und behandeln können.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="79-81"
|
||||
{!> ../../../docs_src/websockets/tutorial003_py39.py!}
|
||||
```
|
||||
```Python hl_lines="79-81"
|
||||
{!> ../../../docs_src/websockets/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="81-83"
|
||||
{!> ../../../docs_src/websockets/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="81-83"
|
||||
{!> ../../../docs_src/websockets/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Zum Ausprobieren:
|
||||
|
||||
|
|
@ -209,12 +238,15 @@ Das wird die Ausnahme `WebSocketDisconnect` auslösen und alle anderen Clients e
|
|||
Client #1596980209979 left the chat
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die obige Anwendung ist ein minimales und einfaches Beispiel, das zeigt, wie Nachrichten verarbeitet und an mehrere WebSocket-Verbindungen gesendet werden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie jedoch, dass, da alles nur im Speicher in einer einzigen Liste verwaltet wird, es nur funktioniert, während der Prozess ausgeführt wird, und nur mit einem einzelnen Prozess.
|
||||
Die obige Anwendung ist ein minimales und einfaches Beispiel, das zeigt, wie Nachrichten verarbeitet und an mehrere WebSocket-Verbindungen gesendet werden.
|
||||
|
||||
Wenn Sie etwas benötigen, das sich leicht in FastAPI integrieren lässt, aber robuster ist und von Redis, PostgreSQL und anderen unterstützt wird, sehen Sie sich <a href="https://github.com/encode/broadcaster" class="external-link" target="_blank">encode/broadcaster</a> an.
|
||||
Beachten Sie jedoch, dass, da alles nur im Speicher in einer einzigen Liste verwaltet wird, es nur funktioniert, während der Prozess ausgeführt wird, und nur mit einem einzelnen Prozess.
|
||||
|
||||
Wenn Sie etwas benötigen, das sich leicht in FastAPI integrieren lässt, aber robuster ist und von Redis, PostgreSQL und anderen unterstützt wird, sehen Sie sich <a href="https://github.com/encode/broadcaster" class="external-link" target="_blank">encode/broadcaster</a> an.
|
||||
|
||||
///
|
||||
|
||||
## Mehr Informationen
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,17 @@ Es wird von vielen Unternehmen verwendet, darunter Mozilla, Red Hat und Eventbri
|
|||
|
||||
Es war eines der ersten Beispiele für **automatische API-Dokumentation**, und dies war insbesondere eine der ersten Ideen, welche „die Suche nach“ **FastAPI** inspirierten.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Das Django REST Framework wurde von Tom Christie erstellt. Derselbe Schöpfer von Starlette und Uvicorn, auf denen **FastAPI** basiert.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Das Django REST Framework wurde von Tom Christie erstellt. Derselbe Schöpfer von Starlette und Uvicorn, auf denen **FastAPI** basiert.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Eine automatische API-Dokumentationsoberfläche zu haben.
|
||||
///
|
||||
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Eine automatische API-Dokumentationsoberfläche zu haben.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a>
|
||||
|
||||
|
|
@ -51,11 +56,13 @@ Diese Entkopplung der Teile und die Tatsache, dass es sich um ein „Mikroframew
|
|||
|
||||
Angesichts der Einfachheit von Flask schien es eine gute Ergänzung zum Erstellen von APIs zu sein. Als Nächstes musste ein „Django REST Framework“ für Flask gefunden werden.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Ein Mikroframework zu sein. Es einfach zu machen, die benötigten Tools und Teile zu kombinieren.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Über ein einfaches und benutzerfreundliches Routingsystem zu verfügen.
|
||||
Ein Mikroframework zu sein. Es einfach zu machen, die benötigten Tools und Teile zu kombinieren.
|
||||
|
||||
Über ein einfaches und benutzerfreundliches Routingsystem zu verfügen.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a>
|
||||
|
||||
|
|
@ -91,11 +98,13 @@ def read_url():
|
|||
|
||||
Sehen Sie sich die Ähnlichkeiten in `requests.get(...)` und `@app.get(...)` an.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
* Über eine einfache und intuitive API zu verfügen.
|
||||
* HTTP-Methodennamen (Operationen) direkt, auf einfache und intuitive Weise zu verwenden.
|
||||
* Vernünftige Standardeinstellungen zu haben, aber auch mächtige Einstellungsmöglichkeiten.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
* Über eine einfache und intuitive API zu verfügen.
|
||||
* HTTP-Methodennamen (Operationen) direkt, auf einfache und intuitive Weise zu verwenden.
|
||||
* Vernünftige Standardeinstellungen zu haben, aber auch mächtige Einstellungsmöglichkeiten.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
|
||||
|
||||
|
|
@ -109,15 +118,18 @@ Irgendwann wurde Swagger an die Linux Foundation übergeben und in OpenAPI umben
|
|||
|
||||
Aus diesem Grund spricht man bei Version 2.0 häufig von „Swagger“ und ab Version 3 von „OpenAPI“.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Einen offenen Standard für API-Spezifikationen zu übernehmen und zu verwenden, anstelle eines benutzerdefinierten Schemas.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Und Standard-basierte Tools für die Oberfläche zu integrieren:
|
||||
Einen offenen Standard für API-Spezifikationen zu übernehmen und zu verwenden, anstelle eines benutzerdefinierten Schemas.
|
||||
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
|
||||
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
|
||||
Und Standard-basierte Tools für die Oberfläche zu integrieren:
|
||||
|
||||
Diese beiden wurden ausgewählt, weil sie ziemlich beliebt und stabil sind, aber bei einer schnellen Suche könnten Sie Dutzende alternativer Benutzeroberflächen für OpenAPI finden (welche Sie mit **FastAPI** verwenden können).
|
||||
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>
|
||||
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>
|
||||
|
||||
Diese beiden wurden ausgewählt, weil sie ziemlich beliebt und stabil sind, aber bei einer schnellen Suche könnten Sie Dutzende alternativer Benutzeroberflächen für OpenAPI finden (welche Sie mit **FastAPI** verwenden können).
|
||||
|
||||
///
|
||||
|
||||
### Flask REST Frameworks
|
||||
|
||||
|
|
@ -135,8 +147,11 @@ Für diese Funktionen wurde Marshmallow entwickelt. Es ist eine großartige Bibl
|
|||
|
||||
Aber sie wurde erstellt, bevor Typhinweise in Python existierten. Um also ein <abbr title="die Definition, wie Daten geformt sein werden sollen">Schema</abbr> zu definieren, müssen Sie bestimmte Werkzeuge und Klassen verwenden, die von Marshmallow bereitgestellt werden.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Code zu verwenden, um „Schemas“ zu definieren, welche Datentypen und Validierung automatisch bereitstellen.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Code zu verwenden, um „Schemas“ zu definieren, welche Datentypen und Validierung automatisch bereitstellen.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
|
||||
|
||||
|
|
@ -148,11 +163,17 @@ Es verwendet unter der Haube Marshmallow, um die Datenvalidierung durchzuführen
|
|||
|
||||
Es ist ein großartiges Tool und ich habe es auch oft verwendet, bevor ich **FastAPI** hatte.
|
||||
|
||||
!!! info
|
||||
Webargs wurde von denselben Marshmallow-Entwicklern erstellt.
|
||||
/// info
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Eingehende Requestdaten automatisch zu validieren.
|
||||
Webargs wurde von denselben Marshmallow-Entwicklern erstellt.
|
||||
|
||||
///
|
||||
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Eingehende Requestdaten automatisch zu validieren.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
|
||||
|
||||
|
|
@ -172,12 +193,17 @@ Aber dann haben wir wieder das Problem einer Mikrosyntax innerhalb eines Python-
|
|||
|
||||
Der Texteditor kann dabei nicht viel helfen. Und wenn wir Parameter oder Marshmallow-Schemas ändern und vergessen, auch den YAML-Docstring zu ändern, wäre das generierte Schema veraltet.
|
||||
|
||||
!!! info
|
||||
APISpec wurde von denselben Marshmallow-Entwicklern erstellt.
|
||||
/// info
|
||||
|
||||
APISpec wurde von denselben Marshmallow-Entwicklern erstellt.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Den offenen Standard für APIs, OpenAPI, zu unterstützen.
|
||||
///
|
||||
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Den offenen Standard für APIs, OpenAPI, zu unterstützen.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
|
||||
|
||||
|
|
@ -199,11 +225,17 @@ Die Verwendung führte zur Entwicklung mehrerer Flask-Full-Stack-Generatoren. Di
|
|||
|
||||
Und dieselben Full-Stack-Generatoren bildeten die Basis der [**FastAPI**-Projektgeneratoren](project-generation.md){.internal-link target=_blank}.
|
||||
|
||||
!!! info
|
||||
Flask-apispec wurde von denselben Marshmallow-Entwicklern erstellt.
|
||||
/// info
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Das OpenAPI-Schema automatisch zu generieren, aus demselben Code, welcher die Serialisierung und Validierung definiert.
|
||||
Flask-apispec wurde von denselben Marshmallow-Entwicklern erstellt.
|
||||
|
||||
///
|
||||
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Das OpenAPI-Schema automatisch zu generieren, aus demselben Code, welcher die Serialisierung und Validierung definiert.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (und <a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
|
||||
|
||||
|
|
@ -219,24 +251,33 @@ Da TypeScript-Daten jedoch nach der Kompilierung nach JavaScript nicht erhalten
|
|||
|
||||
Es kann nicht sehr gut mit verschachtelten Modellen umgehen. Wenn es sich beim JSON-Body in der Anfrage also um ein JSON-Objekt mit inneren Feldern handelt, die wiederum verschachtelte JSON-Objekte sind, kann er nicht richtig dokumentiert und validiert werden.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Python-Typen zu verwenden, um eine hervorragende Editorunterstützung zu erhalten.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Über ein leistungsstarkes Dependency Injection System zu verfügen. Eine Möglichkeit zu finden, Codeverdoppelung zu minimieren.
|
||||
Python-Typen zu verwenden, um eine hervorragende Editorunterstützung zu erhalten.
|
||||
|
||||
Über ein leistungsstarkes Dependency Injection System zu verfügen. Eine Möglichkeit zu finden, Codeverdoppelung zu minimieren.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
|
||||
|
||||
Es war eines der ersten extrem schnellen Python-Frameworks, welches auf `asyncio` basierte. Es wurde so gestaltet, dass es Flask sehr ähnlich ist.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Es verwendete <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> anstelle der standardmäßigen Python-`asyncio`-Schleife. Das hat es so schnell gemacht.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Hat eindeutig Uvicorn und Starlette inspiriert, welche derzeit in offenen Benchmarks schneller als Sanic sind.
|
||||
Es verwendete <a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a> anstelle der standardmäßigen Python-`asyncio`-Schleife. Das hat es so schnell gemacht.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Einen Weg zu finden, eine hervorragende Performanz zu haben.
|
||||
Hat eindeutig Uvicorn und Starlette inspiriert, welche derzeit in offenen Benchmarks schneller als Sanic sind.
|
||||
|
||||
Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste verfügbare Framework ist (getestet in Benchmarks von Dritten).
|
||||
///
|
||||
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Einen Weg zu finden, eine hervorragende Performanz zu haben.
|
||||
|
||||
Aus diesem Grund basiert **FastAPI** auf Starlette, da dieses das schnellste verfügbare Framework ist (getestet in Benchmarks von Dritten).
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
|
||||
|
||||
|
|
@ -246,12 +287,15 @@ Es ist so konzipiert, dass es über Funktionen verfügt, welche zwei Parameter e
|
|||
|
||||
Daher müssen Datenvalidierung, Serialisierung und Dokumentation im Code und nicht automatisch erfolgen. Oder sie müssen als Framework oberhalb von Falcon implementiert werden, so wie Hug. Dieselbe Unterscheidung findet auch in anderen Frameworks statt, die vom Design von Falcon inspiriert sind und ein Requestobjekt und ein Responseobjekt als Parameter haben.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Wege zu finden, eine großartige Performanz zu erzielen.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Zusammen mit Hug (da Hug auf Falcon basiert), einen `response`-Parameter in Funktionen zu deklarieren.
|
||||
Wege zu finden, eine großartige Performanz zu erzielen.
|
||||
|
||||
Obwohl er in FastAPI optional ist und hauptsächlich zum Festlegen von Headern, Cookies und alternativen Statuscodes verwendet wird.
|
||||
Zusammen mit Hug (da Hug auf Falcon basiert), einen `response`-Parameter in Funktionen zu deklarieren.
|
||||
|
||||
Obwohl er in FastAPI optional ist und hauptsächlich zum Festlegen von Headern, Cookies und alternativen Statuscodes verwendet wird.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
|
||||
|
||||
|
|
@ -269,10 +313,13 @@ Das Dependency Injection System erfordert eine Vorab-Registrierung der Abhängig
|
|||
|
||||
Routen werden an einer einzigen Stelle deklariert, indem Funktionen verwendet werden, die an anderen Stellen deklariert wurden (anstatt Dekoratoren zu verwenden, welche direkt über der Funktion platziert werden können, welche den Endpunkt verarbeitet). Dies ähnelt eher der Vorgehensweise von Django als der Vorgehensweise von Flask (und Starlette). Es trennt im Code Dinge, die relativ eng miteinander gekoppelt sind.
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Zusätzliche Validierungen für Datentypen zu definieren, mithilfe des „Default“-Werts von Modellattributen. Dies verbessert die Editorunterstützung und war zuvor in Pydantic nicht verfügbar.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Das hat tatsächlich dazu geführt, dass Teile von Pydantic aktualisiert wurden, um denselben Validierungsdeklarationsstil zu unterstützen (diese gesamte Funktionalität ist jetzt bereits in Pydantic verfügbar).
|
||||
Zusätzliche Validierungen für Datentypen zu definieren, mithilfe des „Default“-Werts von Modellattributen. Dies verbessert die Editorunterstützung und war zuvor in Pydantic nicht verfügbar.
|
||||
|
||||
Das hat tatsächlich dazu geführt, dass Teile von Pydantic aktualisiert wurden, um denselben Validierungsdeklarationsstil zu unterstützen (diese gesamte Funktionalität ist jetzt bereits in Pydantic verfügbar).
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.hug.rest/" class="external-link" target="_blank">Hug</a>
|
||||
|
||||
|
|
@ -288,15 +335,21 @@ Es verfügt über eine interessante, ungewöhnliche Funktion: Mit demselben Fram
|
|||
|
||||
Da es auf dem bisherigen Standard für synchrone Python-Webframeworks (WSGI) basiert, kann es nicht mit Websockets und anderen Dingen umgehen, verfügt aber dennoch über eine hohe Performanz.
|
||||
|
||||
!!! info
|
||||
Hug wurde von Timothy Crosley erstellt, dem gleichen Schöpfer von <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, einem großartigen Tool zum automatischen Sortieren von Importen in Python-Dateien.
|
||||
/// info
|
||||
|
||||
!!! check "Ideen, die **FastAPI** inspiriert haben"
|
||||
Hug inspirierte Teile von APIStar und war eines der Tools, die ich am vielversprechendsten fand, neben APIStar.
|
||||
Hug wurde von Timothy Crosley erstellt, dem gleichen Schöpfer von <a href="https://github.com/timothycrosley/isort" class="external-link" target="_blank">`isort`</a>, einem großartigen Tool zum automatischen Sortieren von Importen in Python-Dateien.
|
||||
|
||||
Hug hat dazu beigetragen, **FastAPI** dazu zu inspirieren, Python-Typhinweise zum Deklarieren von Parametern zu verwenden und ein Schema zu generieren, das die API automatisch definiert.
|
||||
///
|
||||
|
||||
Hug inspirierte **FastAPI** dazu, einen `response`-Parameter in Funktionen zu deklarieren, um Header und Cookies zu setzen.
|
||||
/// check | "Ideen, die **FastAPI** inspiriert haben"
|
||||
|
||||
Hug inspirierte Teile von APIStar und war eines der Tools, die ich am vielversprechendsten fand, neben APIStar.
|
||||
|
||||
Hug hat dazu beigetragen, **FastAPI** dazu zu inspirieren, Python-Typhinweise zum Deklarieren von Parametern zu verwenden und ein Schema zu generieren, das die API automatisch definiert.
|
||||
|
||||
Hug inspirierte **FastAPI** dazu, einen `response`-Parameter in Funktionen zu deklarieren, um Header und Cookies zu setzen.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (≦ 0.5)
|
||||
|
||||
|
|
@ -322,23 +375,29 @@ Es handelte sich nicht länger um ein API-Webframework, da sich der Entwickler a
|
|||
|
||||
Jetzt handelt es sich bei APIStar um eine Reihe von Tools zur Validierung von OpenAPI-Spezifikationen, nicht um ein Webframework.
|
||||
|
||||
!!! info
|
||||
APIStar wurde von Tom Christie erstellt. Derselbe, welcher Folgendes erstellt hat:
|
||||
/// info
|
||||
|
||||
* Django REST Framework
|
||||
* Starlette (auf welchem **FastAPI** basiert)
|
||||
* Uvicorn (verwendet von Starlette und **FastAPI**)
|
||||
APIStar wurde von Tom Christie erstellt. Derselbe, welcher Folgendes erstellt hat:
|
||||
|
||||
!!! check "Inspirierte **FastAPI**"
|
||||
Zu existieren.
|
||||
* Django REST Framework
|
||||
* Starlette (auf welchem **FastAPI** basiert)
|
||||
* Uvicorn (verwendet von Starlette und **FastAPI**)
|
||||
|
||||
Die Idee, mehrere Dinge (Datenvalidierung, Serialisierung und Dokumentation) mit denselben Python-Typen zu deklarieren, welche gleichzeitig eine hervorragende Editorunterstützung bieten, hielt ich für eine brillante Idee.
|
||||
///
|
||||
|
||||
Und nach einer langen Suche nach einem ähnlichen Framework und dem Testen vieler verschiedener Alternativen, war APIStar die beste verfügbare Option.
|
||||
/// check | "Inspirierte **FastAPI**"
|
||||
|
||||
Dann hörte APIStar auf, als Server zu existieren, und Starlette wurde geschaffen, welches eine neue, bessere Grundlage für ein solches System bildete. Das war die finale Inspiration für die Entwicklung von **FastAPI**.
|
||||
Zu existieren.
|
||||
|
||||
Ich betrachte **FastAPI** als einen „spirituellen Nachfolger“ von APIStar, welcher die Funktionen, das Typsystem und andere Teile verbessert und erweitert, basierend auf den Erkenntnissen aus all diesen früheren Tools.
|
||||
Die Idee, mehrere Dinge (Datenvalidierung, Serialisierung und Dokumentation) mit denselben Python-Typen zu deklarieren, welche gleichzeitig eine hervorragende Editorunterstützung bieten, hielt ich für eine brillante Idee.
|
||||
|
||||
Und nach einer langen Suche nach einem ähnlichen Framework und dem Testen vieler verschiedener Alternativen, war APIStar die beste verfügbare Option.
|
||||
|
||||
Dann hörte APIStar auf, als Server zu existieren, und Starlette wurde geschaffen, welches eine neue, bessere Grundlage für ein solches System bildete. Das war die finale Inspiration für die Entwicklung von **FastAPI**.
|
||||
|
||||
Ich betrachte **FastAPI** als einen „spirituellen Nachfolger“ von APIStar, welcher die Funktionen, das Typsystem und andere Teile verbessert und erweitert, basierend auf den Erkenntnissen aus all diesen früheren Tools.
|
||||
|
||||
///
|
||||
|
||||
## Verwendet von **FastAPI**
|
||||
|
||||
|
|
@ -350,10 +409,13 @@ Das macht es äußerst intuitiv.
|
|||
|
||||
Es ist vergleichbar mit Marshmallow. Obwohl es in Benchmarks schneller als Marshmallow ist. Und da es auf den gleichen Python-Typhinweisen basiert, ist die Editorunterstützung großartig.
|
||||
|
||||
!!! check "**FastAPI** verwendet es, um"
|
||||
Die gesamte Datenvalidierung, Datenserialisierung und automatische Modelldokumentation (basierend auf JSON Schema) zu erledigen.
|
||||
/// check | "**FastAPI** verwendet es, um"
|
||||
|
||||
**FastAPI** nimmt dann, abgesehen von all den anderen Dingen, die es tut, dieses JSON-Schema und fügt es in OpenAPI ein.
|
||||
Die gesamte Datenvalidierung, Datenserialisierung und automatische Modelldokumentation (basierend auf JSON Schema) zu erledigen.
|
||||
|
||||
**FastAPI** nimmt dann, abgesehen von all den anderen Dingen, die es tut, dieses JSON-Schema und fügt es in OpenAPI ein.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>
|
||||
|
||||
|
|
@ -382,17 +444,23 @@ Es bietet jedoch keine automatische Datenvalidierung, Serialisierung oder Dokume
|
|||
|
||||
Das ist eines der wichtigsten Dinge, welche **FastAPI** hinzufügt, alles basierend auf Python-Typhinweisen (mit Pydantic). Das, plus, das Dependency Injection System, Sicherheitswerkzeuge, OpenAPI-Schemagenerierung, usw.
|
||||
|
||||
!!! note "Technische Details"
|
||||
ASGI ist ein neuer „Standard“, welcher von Mitgliedern des Django-Kernteams entwickelt wird. Es handelt sich immer noch nicht um einen „Python-Standard“ (ein PEP), obwohl sie gerade dabei sind, das zu tun.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jeden anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können.
|
||||
ASGI ist ein neuer „Standard“, welcher von Mitgliedern des Django-Kernteams entwickelt wird. Es handelt sich immer noch nicht um einen „Python-Standard“ (ein PEP), obwohl sie gerade dabei sind, das zu tun.
|
||||
|
||||
!!! check "**FastAPI** verwendet es, um"
|
||||
Alle Kern-Webaspekte zu handhaben. Und fügt Funktionen obenauf.
|
||||
Dennoch wird es bereits von mehreren Tools als „Standard“ verwendet. Das verbessert die Interoperabilität erheblich, da Sie Uvicorn mit jeden anderen ASGI-Server (wie Daphne oder Hypercorn) tauschen oder ASGI-kompatible Tools wie `python-socketio` hinzufügen können.
|
||||
|
||||
Die Klasse `FastAPI` selbst erbt direkt von der Klasse `Starlette`.
|
||||
///
|
||||
|
||||
Alles, was Sie also mit Starlette machen können, können Sie direkt mit **FastAPI** machen, da es sich im Grunde um Starlette auf Steroiden handelt.
|
||||
/// check | "**FastAPI** verwendet es, um"
|
||||
|
||||
Alle Kern-Webaspekte zu handhaben. Und fügt Funktionen obenauf.
|
||||
|
||||
Die Klasse `FastAPI` selbst erbt direkt von der Klasse `Starlette`.
|
||||
|
||||
Alles, was Sie also mit Starlette machen können, können Sie direkt mit **FastAPI** machen, da es sich im Grunde um Starlette auf Steroiden handelt.
|
||||
|
||||
///
|
||||
|
||||
### <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>
|
||||
|
||||
|
|
@ -402,12 +470,15 @@ Es handelt sich nicht um ein Webframework, sondern um einen Server. Beispielswei
|
|||
|
||||
Es ist der empfohlene Server für Starlette und **FastAPI**.
|
||||
|
||||
!!! check "**FastAPI** empfiehlt es als"
|
||||
Hauptwebserver zum Ausführen von **FastAPI**-Anwendungen.
|
||||
/// check | "**FastAPI** empfiehlt es als"
|
||||
|
||||
Sie können ihn mit Gunicorn kombinieren, um einen asynchronen Multiprozess-Server zu erhalten.
|
||||
Hauptwebserver zum Ausführen von **FastAPI**-Anwendungen.
|
||||
|
||||
Weitere Details finden Sie im Abschnitt [Deployment](deployment/index.md){.internal-link target=_blank}.
|
||||
Sie können ihn mit Gunicorn kombinieren, um einen asynchronen Multiprozess-Server zu erhalten.
|
||||
|
||||
Weitere Details finden Sie im Abschnitt [Deployment](deployment/index.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
## Benchmarks und Geschwindigkeit
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,11 @@ async def read_results():
|
|||
return results
|
||||
```
|
||||
|
||||
!!! note
|
||||
Sie können `await` nur innerhalb von Funktionen verwenden, die mit `async def` erstellt wurden.
|
||||
/// note
|
||||
|
||||
Sie können `await` nur innerhalb von Funktionen verwenden, die mit `async def` erstellt wurden.
|
||||
|
||||
///
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -136,8 +139,11 @@ Sie und Ihr Schwarm essen die Burger und haben eine schöne Zeit. ✨
|
|||
|
||||
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
|
||||
|
||||
!!! info
|
||||
Die wunderschönen Illustrationen stammen von <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||
/// info
|
||||
|
||||
Die wunderschönen Illustrationen stammen von <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||
|
||||
///
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -199,8 +205,11 @@ Sie essen sie und sind fertig. ⏹
|
|||
|
||||
Es wurde nicht viel geredet oder geflirtet, da die meiste Zeit mit Warten 🕙 vor der Theke verbracht wurde. 😞
|
||||
|
||||
!!! info
|
||||
Die wunderschönen Illustrationen stammen von <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||
/// info
|
||||
|
||||
Die wunderschönen Illustrationen stammen von <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a>. 🎨
|
||||
|
||||
///
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -392,12 +401,15 @@ All das ist es, was FastAPI (via Starlette) befeuert und es eine so beeindrucken
|
|||
|
||||
## Sehr technische Details
|
||||
|
||||
!!! warning "Achtung"
|
||||
Das folgende können Sie wahrscheinlich überspringen.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Dies sind sehr technische Details darüber, wie **FastAPI** unter der Haube funktioniert.
|
||||
Das folgende können Sie wahrscheinlich überspringen.
|
||||
|
||||
Wenn Sie über gute technische Kenntnisse verfügen (Coroutinen, Threads, Blocking, usw.) und neugierig sind, wie FastAPI mit `async def`s im Vergleich zu normalen `def`s umgeht, fahren Sie fort.
|
||||
Dies sind sehr technische Details darüber, wie **FastAPI** unter der Haube funktioniert.
|
||||
|
||||
Wenn Sie über gute technische Kenntnisse verfügen (Coroutinen, Threads, Blocking, usw.) und neugierig sind, wie FastAPI mit `async def`s im Vergleich zu normalen `def`s umgeht, fahren Sie fort.
|
||||
|
||||
///
|
||||
|
||||
### Pfadoperation-Funktionen
|
||||
|
||||
|
|
|
|||
|
|
@ -24,63 +24,73 @@ Das erstellt ein Verzeichnis `./env/` mit den Python-Binärdateien und Sie könn
|
|||
|
||||
Aktivieren Sie die neue Umgebung mit:
|
||||
|
||||
=== "Linux, macOS"
|
||||
//// tab | Linux, macOS
|
||||
|
||||
<div class="termy">
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ source ./env/bin/activate
|
||||
```
|
||||
```console
|
||||
$ source ./env/bin/activate
|
||||
```
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
=== "Windows PowerShell"
|
||||
////
|
||||
|
||||
<div class="termy">
|
||||
//// tab | Windows PowerShell
|
||||
|
||||
```console
|
||||
$ .\env\Scripts\Activate.ps1
|
||||
```
|
||||
<div class="termy">
|
||||
|
||||
</div>
|
||||
```console
|
||||
$ .\env\Scripts\Activate.ps1
|
||||
```
|
||||
|
||||
=== "Windows Bash"
|
||||
</div>
|
||||
|
||||
Oder, wenn Sie Bash für Windows verwenden (z. B. <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>):
|
||||
////
|
||||
|
||||
<div class="termy">
|
||||
//// tab | Windows Bash
|
||||
|
||||
```console
|
||||
$ source ./env/Scripts/activate
|
||||
```
|
||||
Oder, wenn Sie Bash für Windows verwenden (z. B. <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>):
|
||||
|
||||
</div>
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ source ./env/Scripts/activate
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
Um zu überprüfen, ob es funktioniert hat, geben Sie ein:
|
||||
|
||||
=== "Linux, macOS, Windows Bash"
|
||||
//// tab | Linux, macOS, Windows Bash
|
||||
|
||||
<div class="termy">
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ which pip
|
||||
```console
|
||||
$ which pip
|
||||
|
||||
some/directory/fastapi/env/bin/pip
|
||||
```
|
||||
some/directory/fastapi/env/bin/pip
|
||||
```
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
=== "Windows PowerShell"
|
||||
////
|
||||
|
||||
<div class="termy">
|
||||
//// tab | Windows PowerShell
|
||||
|
||||
```console
|
||||
$ Get-Command pip
|
||||
<div class="termy">
|
||||
|
||||
some/directory/fastapi/env/bin/pip
|
||||
```
|
||||
```console
|
||||
$ Get-Command pip
|
||||
|
||||
</div>
|
||||
some/directory/fastapi/env/bin/pip
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
////
|
||||
|
||||
Wenn die `pip` Binärdatei unter `env/bin/pip` angezeigt wird, hat es funktioniert. 🎉
|
||||
|
||||
|
|
@ -96,10 +106,13 @@ $ python -m pip install --upgrade pip
|
|||
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Aktivieren Sie jedes Mal, wenn Sie ein neues Package mit `pip` in dieser Umgebung installieren, die Umgebung erneut.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Dadurch wird sichergestellt, dass Sie, wenn Sie ein von diesem Package installiertes Terminalprogramm verwenden, das Programm aus Ihrer lokalen Umgebung verwenden und kein anderes, das global installiert sein könnte.
|
||||
Aktivieren Sie jedes Mal, wenn Sie ein neues Package mit `pip` in dieser Umgebung installieren, die Umgebung erneut.
|
||||
|
||||
Dadurch wird sichergestellt, dass Sie, wenn Sie ein von diesem Package installiertes Terminalprogramm verwenden, das Programm aus Ihrer lokalen Umgebung verwenden und kein anderes, das global installiert sein könnte.
|
||||
|
||||
///
|
||||
|
||||
### Benötigtes mit pip installieren
|
||||
|
||||
|
|
@ -125,10 +138,13 @@ Und wenn Sie diesen lokalen FastAPI-Quellcode aktualisieren und dann die Python-
|
|||
|
||||
Auf diese Weise müssen Sie Ihre lokale Version nicht „installieren“, um jede Änderung testen zu können.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Das geschieht nur, wenn Sie die Installation mit der enthaltenen `requirements.txt` durchführen, anstatt `pip install fastapi` direkt auszuführen.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Das liegt daran, dass in der Datei `requirements.txt` die lokale Version von FastAPI mit der Option `-e` für die Installation im „editierbaren“ Modus markiert ist.
|
||||
Das geschieht nur, wenn Sie die Installation mit der enthaltenen `requirements.txt` durchführen, anstatt `pip install fastapi` direkt auszuführen.
|
||||
|
||||
Das liegt daran, dass in der Datei `requirements.txt` die lokale Version von FastAPI mit der Option `-e` für die Installation im „editierbaren“ Modus markiert ist.
|
||||
|
||||
///
|
||||
|
||||
### Den Code formatieren
|
||||
|
||||
|
|
@ -170,20 +186,23 @@ Das stellt die Dokumentation unter `http://127.0.0.1:8008` bereit.
|
|||
|
||||
Auf diese Weise können Sie die Dokumentation/Quelldateien bearbeiten und die Änderungen live sehen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Alternativ können Sie die Schritte des Skripts auch manuell ausführen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Gehen Sie in das Verzeichnis für die entsprechende Sprache. Das für die englischsprachige Hauptdokumentation befindet sich unter `docs/en/`:
|
||||
Alternativ können Sie die Schritte des Skripts auch manuell ausführen.
|
||||
|
||||
```console
|
||||
$ cd docs/en/
|
||||
```
|
||||
Gehen Sie in das Verzeichnis für die entsprechende Sprache. Das für die englischsprachige Hauptdokumentation befindet sich unter `docs/en/`:
|
||||
|
||||
Führen Sie dann `mkdocs` in diesem Verzeichnis aus:
|
||||
```console
|
||||
$ cd docs/en/
|
||||
```
|
||||
|
||||
```console
|
||||
$ mkdocs serve --dev-addr 8008
|
||||
```
|
||||
Führen Sie dann `mkdocs` in diesem Verzeichnis aus:
|
||||
|
||||
```console
|
||||
$ mkdocs serve --dev-addr 8008
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
#### Typer-CLI (optional)
|
||||
|
||||
|
|
@ -210,8 +229,11 @@ Die Dokumentation verwendet <a href="https://www.mkdocs.org/" class="external-li
|
|||
|
||||
Und es gibt zusätzliche Tools/Skripte für Übersetzungen, in `./scripts/docs.py`.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie müssen sich den Code in `./scripts/docs.py` nicht anschauen, verwenden Sie ihn einfach in der Kommandozeile.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie müssen sich den Code in `./scripts/docs.py` nicht anschauen, verwenden Sie ihn einfach in der Kommandozeile.
|
||||
|
||||
///
|
||||
|
||||
Die gesamte Dokumentation befindet sich im Markdown-Format im Verzeichnis `./docs/en/`.
|
||||
|
||||
|
|
@ -261,10 +283,13 @@ Hier sind die Schritte, die Ihnen bei Übersetzungen helfen.
|
|||
|
||||
* Sehen Sie diese Pull Requests durch (Review), schlagen Sie Änderungen vor, oder segnen Sie sie ab (Approval). Bei den Sprachen, die ich nicht spreche, warte ich, bis mehrere andere die Übersetzung durchgesehen haben, bevor ich den Pull Request merge.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request" class="external-link" target="_blank">Kommentare mit Änderungsvorschlägen</a> zu vorhandenen Pull Requests hinzufügen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Schauen Sie sich die Dokumentation an, <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-reviews" class="external-link" target="_blank">wie man ein Review zu einem Pull Request hinzufügt</a>, welches den PR absegnet oder Änderungen vorschlägt.
|
||||
Sie können <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request" class="external-link" target="_blank">Kommentare mit Änderungsvorschlägen</a> zu vorhandenen Pull Requests hinzufügen.
|
||||
|
||||
Schauen Sie sich die Dokumentation an, <a href="https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-reviews" class="external-link" target="_blank">wie man ein Review zu einem Pull Request hinzufügt</a>, welches den PR absegnet oder Änderungen vorschlägt.
|
||||
|
||||
///
|
||||
|
||||
* Überprüfen Sie, ob es eine <a href="https://github.com/fastapi/fastapi/discussions/categories/translations" class="external-link" target="_blank">GitHub-Diskussion</a> gibt, die Übersetzungen für Ihre Sprache koordiniert. Sie können sie abonnieren, und wenn ein neuer Pull Request zum Review vorliegt, wird der Diskussion automatisch ein Kommentar hinzugefügt.
|
||||
|
||||
|
|
@ -278,8 +303,11 @@ Angenommen, Sie möchten eine Seite für eine Sprache übersetzen, die bereits
|
|||
|
||||
Im Spanischen lautet der Zwei-Buchstaben-Code `es`. Das Verzeichnis für spanische Übersetzungen befindet sich also unter `docs/es/`.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die Haupt („offizielle“) Sprache ist Englisch und befindet sich unter `docs/en/`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die Haupt („offizielle“) Sprache ist Englisch und befindet sich unter `docs/en/`.
|
||||
|
||||
///
|
||||
|
||||
Führen Sie nun den Live-Server für die Dokumentation auf Spanisch aus:
|
||||
|
||||
|
|
@ -296,20 +324,23 @@ $ python ./scripts/docs.py live es
|
|||
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Alternativ können Sie die Schritte des Skripts auch manuell ausführen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Gehen Sie in das Sprachverzeichnis, für die spanischen Übersetzungen ist das `docs/es/`:
|
||||
Alternativ können Sie die Schritte des Skripts auch manuell ausführen.
|
||||
|
||||
```console
|
||||
$ cd docs/es/
|
||||
```
|
||||
Gehen Sie in das Sprachverzeichnis, für die spanischen Übersetzungen ist das `docs/es/`:
|
||||
|
||||
Dann führen Sie in dem Verzeichnis `mkdocs` aus:
|
||||
```console
|
||||
$ cd docs/es/
|
||||
```
|
||||
|
||||
```console
|
||||
$ mkdocs serve --dev-addr 8008
|
||||
```
|
||||
Dann führen Sie in dem Verzeichnis `mkdocs` aus:
|
||||
|
||||
```console
|
||||
$ mkdocs serve --dev-addr 8008
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
Jetzt können Sie auf <a href="http://127.0.0.1:8008" class="external-link" target="_blank">http://127.0.0.1:8008</a> gehen und Ihre Änderungen live sehen.
|
||||
|
||||
|
|
@ -329,8 +360,11 @@ docs/en/docs/features.md
|
|||
docs/es/docs/features.md
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass die einzige Änderung in Pfad und Dateiname der Sprachcode ist, von `en` zu `es`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass die einzige Änderung in Pfad und Dateiname der Sprachcode ist, von `en` zu `es`.
|
||||
|
||||
///
|
||||
|
||||
Wenn Sie in Ihrem Browser nachsehen, werden Sie feststellen, dass die Dokumentation jetzt Ihren neuen Abschnitt anzeigt (die Info-Box oben ist verschwunden). 🎉
|
||||
|
||||
|
|
@ -365,8 +399,11 @@ Obiges Kommando hat eine Datei `docs/ht/mkdocs.yml` mit einer Minimal-Konfigurat
|
|||
INHERIT: ../en/mkdocs.yml
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können diese Datei mit diesem Inhalt auch einfach manuell erstellen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können diese Datei mit diesem Inhalt auch einfach manuell erstellen.
|
||||
|
||||
///
|
||||
|
||||
Das Kommando hat auch eine Dummy-Datei `docs/ht/index.md` für die Hauptseite erstellt. Sie können mit der Übersetzung dieser Datei beginnen.
|
||||
|
||||
|
|
|
|||
|
|
@ -151,10 +151,13 @@ Und dennoch möchten Sie wahrscheinlich nicht, dass die Anwendung tot bleibt, we
|
|||
|
||||
Aber in den Fällen mit wirklich schwerwiegenden Fehlern, die den laufenden **Prozess** zum Absturz bringen, benötigen Sie eine externe Komponente, die den Prozess **neu startet**, zumindest ein paar Mal ...
|
||||
|
||||
!!! tip "Tipp"
|
||||
... Obwohl es wahrscheinlich keinen Sinn macht, sie immer wieder neu zu starten, wenn die gesamte Anwendung einfach **sofort abstürzt**. Aber in diesen Fällen werden Sie es wahrscheinlich während der Entwicklung oder zumindest direkt nach dem Deployment bemerken.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Konzentrieren wir uns also auf die Hauptfälle, in denen die Anwendung in bestimmten Fällen **in der Zukunft** völlig abstürzen könnte und es dann dennoch sinnvoll ist, sie neu zu starten.
|
||||
... Obwohl es wahrscheinlich keinen Sinn macht, sie immer wieder neu zu starten, wenn die gesamte Anwendung einfach **sofort abstürzt**. Aber in diesen Fällen werden Sie es wahrscheinlich während der Entwicklung oder zumindest direkt nach dem Deployment bemerken.
|
||||
|
||||
Konzentrieren wir uns also auf die Hauptfälle, in denen die Anwendung in bestimmten Fällen **in der Zukunft** völlig abstürzen könnte und es dann dennoch sinnvoll ist, sie neu zu starten.
|
||||
|
||||
///
|
||||
|
||||
Sie möchten wahrscheinlich, dass eine **externe Komponente** für den Neustart Ihrer Anwendung verantwortlich ist, da zu diesem Zeitpunkt dieselbe Anwendung mit Uvicorn und Python bereits abgestürzt ist und es daher nichts im selben Code derselben Anwendung gibt, was etwas dagegen tun kann.
|
||||
|
||||
|
|
@ -238,10 +241,13 @@ Hier sind einige mögliche Kombinationen und Strategien:
|
|||
* **Cloud-Dienste**, welche das für Sie erledigen
|
||||
* Der Cloud-Dienst wird wahrscheinlich **die Replikation für Sie übernehmen**. Er würde Sie möglicherweise **einen auszuführenden Prozess** oder ein **zu verwendendes Container-Image** definieren lassen, in jedem Fall wäre es höchstwahrscheinlich **ein einzelner Uvicorn-Prozess**, und der Cloud-Dienst wäre auch verantwortlich für die Replikation.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Machen Sie sich keine Sorgen, wenn einige dieser Punkte zu **Containern**, Docker oder Kubernetes noch nicht viel Sinn ergeben.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Ich werde Ihnen in einem zukünftigen Kapitel mehr über Container-Images, Docker, Kubernetes, usw. erzählen: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}.
|
||||
Machen Sie sich keine Sorgen, wenn einige dieser Punkte zu **Containern**, Docker oder Kubernetes noch nicht viel Sinn ergeben.
|
||||
|
||||
Ich werde Ihnen in einem zukünftigen Kapitel mehr über Container-Images, Docker, Kubernetes, usw. erzählen: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
## Schritte vor dem Start
|
||||
|
||||
|
|
@ -257,10 +263,13 @@ Und Sie müssen sicherstellen, dass es sich um einen einzelnen Prozess handelt,
|
|||
|
||||
Natürlich gibt es Fälle, in denen es kein Problem darstellt, die Vorab-Schritte mehrmals auszuführen. In diesem Fall ist die Handhabung viel einfacher.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bedenken Sie außerdem, dass Sie, abhängig von Ihrer Einrichtung, in manchen Fällen **gar keine Vorab-Schritte** benötigen, bevor Sie die Anwendung starten.
|
||||
/// tip | "Tipp"
|
||||
|
||||
In diesem Fall müssen Sie sich darüber keine Sorgen machen. 🤷
|
||||
Bedenken Sie außerdem, dass Sie, abhängig von Ihrer Einrichtung, in manchen Fällen **gar keine Vorab-Schritte** benötigen, bevor Sie die Anwendung starten.
|
||||
|
||||
In diesem Fall müssen Sie sich darüber keine Sorgen machen. 🤷
|
||||
|
||||
///
|
||||
|
||||
### Beispiele für Strategien für Vorab-Schritte
|
||||
|
||||
|
|
@ -272,8 +281,11 @@ Hier sind einige mögliche Ideen:
|
|||
* Ein Bash-Skript, das die Vorab-Schritte ausführt und dann Ihre Anwendung startet
|
||||
* Sie benötigen immer noch eine Möglichkeit, *dieses* Bash-Skript zu starten/neu zu starten, Fehler zu erkennen, usw.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Konkretere Beispiele hierfür mit Containern gebe ich Ihnen in einem späteren Kapitel: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Konkretere Beispiele hierfür mit Containern gebe ich Ihnen in einem späteren Kapitel: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
## Ressourcennutzung
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ Beim Deployment von FastAPI-Anwendungen besteht ein gängiger Ansatz darin, ein
|
|||
|
||||
Die Verwendung von Linux-Containern bietet mehrere Vorteile, darunter **Sicherheit**, **Replizierbarkeit**, **Einfachheit** und andere.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie haben es eilig und kennen sich bereits aus? Springen Sie zum [`Dockerfile` unten 👇](#ein-docker-image-fur-fastapi-erstellen).
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie haben es eilig und kennen sich bereits aus? Springen Sie zum [`Dockerfile` unten 👇](#ein-docker-image-fur-fastapi-erstellen).
|
||||
|
||||
///
|
||||
|
||||
<Details>
|
||||
<summary>Dockerfile-Vorschau 👀</summary>
|
||||
|
|
@ -130,10 +133,13 @@ Successfully installed fastapi pydantic uvicorn
|
|||
|
||||
</div>
|
||||
|
||||
!!! info
|
||||
Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhängigkeiten.
|
||||
/// info
|
||||
|
||||
Ich zeige Ihnen später in einem Abschnitt unten ein Beispiel unter Verwendung von Poetry. 👇
|
||||
Es gibt andere Formate und Tools zum Definieren und Installieren von Paketabhängigkeiten.
|
||||
|
||||
Ich zeige Ihnen später in einem Abschnitt unten ein Beispiel unter Verwendung von Poetry. 👇
|
||||
|
||||
///
|
||||
|
||||
### Den **FastAPI**-Code erstellen
|
||||
|
||||
|
|
@ -222,8 +228,11 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
Da das Programm unter `/code` gestartet wird und sich darin das Verzeichnis `./app` mit Ihrem Code befindet, kann **Uvicorn** `app` sehen und aus `app.main` **importieren**.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Lernen Sie, was jede Zeile bewirkt, indem Sie auf die Zahlenblasen im Code klicken. 👆
|
||||
/// tip | "Tipp"
|
||||
|
||||
Lernen Sie, was jede Zeile bewirkt, indem Sie auf die Zahlenblasen im Code klicken. 👆
|
||||
|
||||
///
|
||||
|
||||
Sie sollten jetzt eine Verzeichnisstruktur wie diese haben:
|
||||
|
||||
|
|
@ -293,10 +302,13 @@ $ docker build -t myimage .
|
|||
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie das `.` am Ende, es entspricht `./` und teilt Docker mit, welches Verzeichnis zum Erstellen des Containerimages verwendet werden soll.
|
||||
/// tip | "Tipp"
|
||||
|
||||
In diesem Fall handelt es sich um dasselbe aktuelle Verzeichnis (`.`).
|
||||
Beachten Sie das `.` am Ende, es entspricht `./` und teilt Docker mit, welches Verzeichnis zum Erstellen des Containerimages verwendet werden soll.
|
||||
|
||||
In diesem Fall handelt es sich um dasselbe aktuelle Verzeichnis (`.`).
|
||||
|
||||
///
|
||||
|
||||
### Den Docker-Container starten
|
||||
|
||||
|
|
@ -394,8 +406,11 @@ Wenn wir uns nur auf das **Containerimage** für eine FastAPI-Anwendung (und sp
|
|||
|
||||
Es könnte sich um einen anderen Container handeln, zum Beispiel mit <a href="https://traefik.io/" class="external-link" target="_blank">Traefik</a>, welcher **HTTPS** und **automatischen** Erwerb von **Zertifikaten** handhabt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Traefik verfügt über Integrationen mit Docker, Kubernetes und anderen, sodass Sie damit ganz einfach HTTPS für Ihre Container einrichten und konfigurieren können.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Traefik verfügt über Integrationen mit Docker, Kubernetes und anderen, sodass Sie damit ganz einfach HTTPS für Ihre Container einrichten und konfigurieren können.
|
||||
|
||||
///
|
||||
|
||||
Alternativ könnte HTTPS von einem Cloud-Anbieter als einer seiner Dienste gehandhabt werden (während die Anwendung weiterhin in einem Container ausgeführt wird).
|
||||
|
||||
|
|
@ -423,8 +438,11 @@ Bei der Verwendung von Containern ist normalerweise eine Komponente vorhanden, *
|
|||
|
||||
Da diese Komponente die **Last** an Requests aufnehmen und diese (hoffentlich) **ausgewogen** auf die Worker verteilen würde, wird sie üblicherweise auch **Load Balancer** – Lastverteiler – genannt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die gleiche **TLS-Terminierungsproxy**-Komponente, die für HTTPS verwendet wird, wäre wahrscheinlich auch ein **Load Balancer**.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die gleiche **TLS-Terminierungsproxy**-Komponente, die für HTTPS verwendet wird, wäre wahrscheinlich auch ein **Load Balancer**.
|
||||
|
||||
///
|
||||
|
||||
Und wenn Sie mit Containern arbeiten, verfügt das gleiche System, mit dem Sie diese starten und verwalten, bereits über interne Tools, um die **Netzwerkkommunikation** (z. B. HTTP-Requests) von diesem **Load Balancer** (das könnte auch ein **TLS-Terminierungsproxy** sein) zu den Containern mit Ihrer Anwendung weiterzuleiten.
|
||||
|
||||
|
|
@ -503,8 +521,11 @@ Wenn Sie Container (z. B. Docker, Kubernetes) verwenden, können Sie hauptsächl
|
|||
|
||||
Wenn Sie **mehrere Container** haben, von denen wahrscheinlich jeder einen **einzelnen Prozess** ausführt (z. B. in einem **Kubernetes**-Cluster), dann möchten Sie wahrscheinlich einen **separaten Container** haben, welcher die Arbeit der **Vorab-Schritte** in einem einzelnen Container, mit einem einzelnenen Prozess ausführt, **bevor** die replizierten Workercontainer ausgeführt werden.
|
||||
|
||||
!!! info
|
||||
Wenn Sie Kubernetes verwenden, wäre dies wahrscheinlich ein <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init-Container</a>.
|
||||
/// info
|
||||
|
||||
Wenn Sie Kubernetes verwenden, wäre dies wahrscheinlich ein <a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" class="external-link" target="_blank">Init-Container</a>.
|
||||
|
||||
///
|
||||
|
||||
Wenn es in Ihrem Anwendungsfall kein Problem darstellt, diese vorherigen Schritte **mehrmals parallel** auszuführen (z. B. wenn Sie keine Datenbankmigrationen ausführen, sondern nur prüfen, ob die Datenbank bereits bereit ist), können Sie sie auch einfach in jedem Container direkt vor dem Start des Hauptprozesses einfügen.
|
||||
|
||||
|
|
@ -520,8 +541,11 @@ Dieses Image wäre vor allem in den oben beschriebenen Situationen nützlich: [C
|
|||
|
||||
* <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Es besteht eine hohe Wahrscheinlichkeit, dass Sie dieses oder ein ähnliches Basisimage **nicht** benötigen und es besser wäre, wenn Sie das Image von Grund auf neu erstellen würden, wie [oben beschrieben in: Ein Docker-Image für FastAPI erstellen](#ein-docker-image-fur-fastapi-erstellen).
|
||||
/// warning | "Achtung"
|
||||
|
||||
Es besteht eine hohe Wahrscheinlichkeit, dass Sie dieses oder ein ähnliches Basisimage **nicht** benötigen und es besser wäre, wenn Sie das Image von Grund auf neu erstellen würden, wie [oben beschrieben in: Ein Docker-Image für FastAPI erstellen](#ein-docker-image-fur-fastapi-erstellen).
|
||||
|
||||
///
|
||||
|
||||
Dieses Image verfügt über einen **Auto-Tuning**-Mechanismus, um die **Anzahl der Arbeitsprozesse** basierend auf den verfügbaren CPU-Kernen festzulegen.
|
||||
|
||||
|
|
@ -529,8 +553,11 @@ Es verfügt über **vernünftige Standardeinstellungen**, aber Sie können trotz
|
|||
|
||||
Es unterstützt auch die Ausführung von <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker#pre_start_path" class="external-link" target="_blank">**Vorab-Schritten vor dem Start** </a> mit einem Skript.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um alle Konfigurationen und Optionen anzuzeigen, gehen Sie zur Docker-Image-Seite: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um alle Konfigurationen und Optionen anzuzeigen, gehen Sie zur Docker-Image-Seite: <a href="https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker" class="external-link" target="_blank">tiangolo/uvicorn-gunicorn-fastapi</a>.
|
||||
|
||||
///
|
||||
|
||||
### Anzahl der Prozesse auf dem offiziellen Docker-Image
|
||||
|
||||
|
|
@ -657,8 +684,11 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|||
|
||||
11. Führe den Befehl `uvicorn` aus und weise ihn an, das aus `app.main` importierte `app`-Objekt zu verwenden.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Klicken Sie auf die Zahlenblasen, um zu sehen, was jede Zeile bewirkt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Klicken Sie auf die Zahlenblasen, um zu sehen, was jede Zeile bewirkt.
|
||||
|
||||
///
|
||||
|
||||
Eine **Docker-Phase** ist ein Teil eines `Dockerfile`s, welcher als **temporäres Containerimage** fungiert und nur zum Generieren einiger Dateien für die spätere Verwendung verwendet wird.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ Es ist leicht anzunehmen, dass HTTPS etwas ist, was einfach nur „aktiviert“
|
|||
|
||||
Aber es ist viel komplexer als das.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie es eilig haben oder es Ihnen egal ist, fahren Sie mit den nächsten Abschnitten fort, um Schritt-für-Schritt-Anleitungen für die Einrichtung der verschiedenen Technologien zu erhalten.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie es eilig haben oder es Ihnen egal ist, fahren Sie mit den nächsten Abschnitten fort, um Schritt-für-Schritt-Anleitungen für die Einrichtung der verschiedenen Technologien zu erhalten.
|
||||
|
||||
///
|
||||
|
||||
Um **die Grundlagen von HTTPS** aus Sicht des Benutzers zu erlernen, schauen Sie sich <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a> an.
|
||||
|
||||
|
|
@ -68,8 +71,11 @@ In dem oder den DNS-Server(n) würden Sie einen Eintrag (einen „`A record`“)
|
|||
|
||||
Sie würden dies wahrscheinlich nur einmal tun, beim ersten Mal, wenn Sie alles einrichten.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Dieser Domainnamen-Aspekt liegt weit vor HTTPS, aber da alles von der Domain und der IP-Adresse abhängt, lohnt es sich, das hier zu erwähnen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Dieser Domainnamen-Aspekt liegt weit vor HTTPS, aber da alles von der Domain und der IP-Adresse abhängt, lohnt es sich, das hier zu erwähnen.
|
||||
|
||||
///
|
||||
|
||||
### DNS
|
||||
|
||||
|
|
@ -115,8 +121,11 @@ Danach verfügen der Client und der Server über eine **verschlüsselte TCP-Verb
|
|||
|
||||
Und genau das ist **HTTPS**, es ist einfach **HTTP** innerhalb einer **sicheren TLS-Verbindung**, statt einer puren (unverschlüsselten) TCP-Verbindung.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass die Verschlüsselung der Kommunikation auf der **TCP-Ebene** und nicht auf der HTTP-Ebene erfolgt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass die Verschlüsselung der Kommunikation auf der **TCP-Ebene** und nicht auf der HTTP-Ebene erfolgt.
|
||||
|
||||
///
|
||||
|
||||
### HTTPS-Request
|
||||
|
||||
|
|
|
|||
|
|
@ -22,75 +22,89 @@ Wenn man sich auf die entfernte Maschine bezieht, wird sie üblicherweise als **
|
|||
|
||||
Sie können einen ASGI-kompatiblen Server installieren mit:
|
||||
|
||||
=== "Uvicorn"
|
||||
//// tab | Uvicorn
|
||||
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, ein blitzschneller ASGI-Server, basierend auf uvloop und httptools.
|
||||
* <a href="https://www.uvicorn.org/" class="external-link" target="_blank">Uvicorn</a>, ein blitzschneller ASGI-Server, basierend auf uvloop und httptools.
|
||||
|
||||
<div class="termy">
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
```console
|
||||
$ pip install "uvicorn[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Durch das Hinzufügen von `standard` installiert und verwendet Uvicorn einige empfohlene zusätzliche Abhängigkeiten.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Inklusive `uvloop`, einen hochperformanten Drop-in-Ersatz für `asyncio`, welcher für einen großen Leistungsschub bei der Nebenläufigkeit sorgt.
|
||||
Durch das Hinzufügen von `standard` installiert und verwendet Uvicorn einige empfohlene zusätzliche Abhängigkeiten.
|
||||
|
||||
=== "Hypercorn"
|
||||
Inklusive `uvloop`, einen hochperformanten Drop-in-Ersatz für `asyncio`, welcher für einen großen Leistungsschub bei der Nebenläufigkeit sorgt.
|
||||
|
||||
* <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, ein ASGI-Server, der auch mit HTTP/2 kompatibel ist.
|
||||
///
|
||||
|
||||
<div class="termy">
|
||||
////
|
||||
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
//// tab | Hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
* <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, ein ASGI-Server, der auch mit HTTP/2 kompatibel ist.
|
||||
|
||||
</div>
|
||||
<div class="termy">
|
||||
|
||||
... oder jeden anderen ASGI-Server.
|
||||
```console
|
||||
$ pip install hypercorn
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
... oder jeden anderen ASGI-Server.
|
||||
|
||||
////
|
||||
|
||||
## Das Serverprogramm ausführen
|
||||
|
||||
Anschließend können Sie Ihre Anwendung auf die gleiche Weise ausführen, wie Sie es in den Tutorials getan haben, jedoch ohne die Option `--reload`, z. B.:
|
||||
|
||||
=== "Uvicorn"
|
||||
//// tab | Uvicorn
|
||||
|
||||
<div class="termy">
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --host 0.0.0.0 --port 80
|
||||
```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)
|
||||
```
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
=== "Hypercorn"
|
||||
////
|
||||
|
||||
<div class="termy">
|
||||
//// tab | Hypercorn
|
||||
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
<div class="termy">
|
||||
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
```console
|
||||
$ hypercorn main:app --bind 0.0.0.0:80
|
||||
|
||||
</div>
|
||||
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
|
||||
```
|
||||
|
||||
!!! warning "Achtung"
|
||||
Denken Sie daran, die Option `--reload` zu entfernen, wenn Sie diese verwendet haben.
|
||||
</div>
|
||||
|
||||
Die Option `--reload` verbraucht viel mehr Ressourcen, ist instabiler, usw.
|
||||
////
|
||||
|
||||
Sie hilft sehr während der **Entwicklung**, aber Sie sollten sie **nicht** in der **Produktion** verwenden.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Denken Sie daran, die Option `--reload` zu entfernen, wenn Sie diese verwendet haben.
|
||||
|
||||
Die Option `--reload` verbraucht viel mehr Ressourcen, ist instabiler, usw.
|
||||
|
||||
Sie hilft sehr während der **Entwicklung**, aber Sie sollten sie **nicht** in der **Produktion** verwenden.
|
||||
|
||||
///
|
||||
|
||||
## Hypercorn mit Trio
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,13 @@ Wie Sie im vorherigen Kapitel über [Deployment-Konzepte](concepts.md){.internal
|
|||
|
||||
Hier zeige ich Ihnen, wie Sie <a href="https://gunicorn.org/" class="external-link" target="_blank">**Gunicorn**</a> mit **Uvicorn Workerprozessen** verwenden.
|
||||
|
||||
!!! info
|
||||
Wenn Sie Container verwenden, beispielsweise mit Docker oder Kubernetes, erzähle ich Ihnen mehr darüber im nächsten Kapitel: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}.
|
||||
/// info
|
||||
|
||||
Insbesondere wenn die Anwendung auf **Kubernetes** läuft, werden Sie Gunicorn wahrscheinlich **nicht** verwenden wollen und stattdessen **einen einzelnen Uvicorn-Prozess pro Container** ausführen wollen, aber ich werde Ihnen später in diesem Kapitel mehr darüber erzählen.
|
||||
Wenn Sie Container verwenden, beispielsweise mit Docker oder Kubernetes, erzähle ich Ihnen mehr darüber im nächsten Kapitel: [FastAPI in Containern – Docker](docker.md){.internal-link target=_blank}.
|
||||
|
||||
Insbesondere wenn die Anwendung auf **Kubernetes** läuft, werden Sie Gunicorn wahrscheinlich **nicht** verwenden wollen und stattdessen **einen einzelnen Uvicorn-Prozess pro Container** ausführen wollen, aber ich werde Ihnen später in diesem Kapitel mehr darüber erzählen.
|
||||
|
||||
///
|
||||
|
||||
## Gunicorn mit Uvicorn-Workern
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,11 @@ Gemäß den Konventionen zur semantischen Versionierung könnte jede Version unt
|
|||
|
||||
FastAPI folgt auch der Konvention, dass jede „PATCH“-Versionsänderung für Bugfixes und abwärtskompatible Änderungen gedacht ist.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Der „PATCH“ ist die letzte Zahl, zum Beispiel ist in `0.2.3` die PATCH-Version `3`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Der „PATCH“ ist die letzte Zahl, zum Beispiel ist in `0.2.3` die PATCH-Version `3`.
|
||||
|
||||
///
|
||||
|
||||
Sie sollten also in der Lage sein, eine Version wie folgt anzupinnen:
|
||||
|
||||
|
|
@ -53,8 +56,11 @@ fastapi>=0.45.0,<0.46.0
|
|||
|
||||
Nicht abwärtskompatible Änderungen und neue Funktionen werden in „MINOR“-Versionen hinzugefügt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
„MINOR“ ist die Zahl in der Mitte, zum Beispiel ist in `0.2.3` die MINOR-Version `2`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
„MINOR“ ist die Zahl in der Mitte, zum Beispiel ist in `0.2.3` die MINOR-Version `2`.
|
||||
|
||||
///
|
||||
|
||||
## Upgrade der FastAPI-Versionen
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,17 @@ Es gibt viele Beiträge, Artikel, Tools und Projekte zum Thema **FastAPI**.
|
|||
|
||||
Hier ist eine unvollständige Liste einiger davon.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie einen Artikel, ein Projekt, ein Tool oder irgendetwas im Zusammenhang mit **FastAPI** haben, was hier noch nicht aufgeführt ist, erstellen Sie einen <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request und fügen Sie es hinzu</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! note "Hinweis Deutsche Übersetzung"
|
||||
Die folgenden Überschriften und Links werden aus einer <a href="https://github.com/fastapi/fastapi/blob/master/docs/en/data/external_links.yml" class="external-link" target="_blank">anderen Datei</a> gelesen und sind daher nicht ins Deutsche übersetzt.
|
||||
Wenn Sie einen Artikel, ein Projekt, ein Tool oder irgendetwas im Zusammenhang mit **FastAPI** haben, was hier noch nicht aufgeführt ist, erstellen Sie einen <a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request und fügen Sie es hinzu</a>.
|
||||
|
||||
///
|
||||
|
||||
/// note | "Hinweis Deutsche Übersetzung"
|
||||
|
||||
Die folgenden Überschriften und Links werden aus einer <a href="https://github.com/fastapi/fastapi/blob/master/docs/en/data/external_links.yml" class="external-link" target="_blank">anderen Datei</a> gelesen und sind daher nicht ins Deutsche übersetzt.
|
||||
|
||||
///
|
||||
|
||||
{% for section_name, section_content in external_links.items() %}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,10 +64,13 @@ second_user_data = {
|
|||
my_second_user: User = User(**second_user_data)
|
||||
```
|
||||
|
||||
!!! info
|
||||
`**second_user_data` bedeutet:
|
||||
/// info
|
||||
|
||||
Nimm die Schlüssel-Wert-Paare des `second_user_data` <abbr title="Dictionary – Wörterbuch: In anderen Programmiersprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dicts</abbr> und übergib sie direkt als Schlüsselwort-Argumente. Äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")`.
|
||||
`**second_user_data` bedeutet:
|
||||
|
||||
Nimm die Schlüssel-Wert-Paare des `second_user_data` <abbr title="Dictionary – Wörterbuch: In anderen Programmiersprachen auch Hash, Map, Objekt, Assoziatives Array genannt">Dicts</abbr> und übergib sie direkt als Schlüsselwort-Argumente. Äquivalent zu: `User(id=4, name="Mary", joined="2018-11-30")`.
|
||||
|
||||
///
|
||||
|
||||
### Editor Unterstützung
|
||||
|
||||
|
|
|
|||
|
|
@ -169,12 +169,15 @@ Und wenn es irgendeinen anderen Stil- oder Konsistenz-Bedarf gibt, bitte ich dir
|
|||
|
||||
* Schreiben Sie dann einen **Kommentar** und berichten, dass Sie das getan haben. So weiß ich, dass Sie ihn wirklich überprüft haben.
|
||||
|
||||
!!! info
|
||||
Leider kann ich PRs, nur weil sie von Mehreren gutgeheißen wurden, nicht einfach vertrauen.
|
||||
/// info
|
||||
|
||||
Es ist mehrmals passiert, dass es PRs mit drei, fünf oder mehr Zustimmungen gibt, wahrscheinlich weil die Beschreibung ansprechend ist, aber wenn ich die PRs überprüfe, sind sie tatsächlich fehlerhaft, haben einen Bug, oder lösen das Problem nicht, welches sie behaupten, zu lösen. 😅
|
||||
Leider kann ich PRs, nur weil sie von Mehreren gutgeheißen wurden, nicht einfach vertrauen.
|
||||
|
||||
Daher ist es wirklich wichtig, dass Sie den Code tatsächlich lesen und ausführen und mir in den Kommentaren mitteilen, dass Sie dies getan haben. 🤓
|
||||
Es ist mehrmals passiert, dass es PRs mit drei, fünf oder mehr Zustimmungen gibt, wahrscheinlich weil die Beschreibung ansprechend ist, aber wenn ich die PRs überprüfe, sind sie tatsächlich fehlerhaft, haben einen Bug, oder lösen das Problem nicht, welches sie behaupten, zu lösen. 😅
|
||||
|
||||
Daher ist es wirklich wichtig, dass Sie den Code tatsächlich lesen und ausführen und mir in den Kommentaren mitteilen, dass Sie dies getan haben. 🤓
|
||||
|
||||
///
|
||||
|
||||
* Wenn der PR irgendwie vereinfacht werden kann, fragen Sie ruhig danach, aber seien Sie nicht zu wählerisch, es gibt viele subjektive Standpunkte (und ich habe auch meinen eigenen 🙈), also ist es besser, wenn man sich auf die wesentlichen Dinge konzentriert.
|
||||
|
||||
|
|
@ -225,10 +228,13 @@ Wenn Sie mir dabei helfen können, **helfen Sie mir, FastAPI am Laufen zu erhalt
|
|||
|
||||
Treten Sie dem 👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">Discord-Chatserver</a> 👥 bei und treffen Sie sich mit anderen Mitgliedern der FastAPI-Community.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie Fragen haben, stellen Sie sie bei <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Diskussionen</a>, es besteht eine viel bessere Chance, dass Sie hier Hilfe von den [FastAPI-Experten](fastapi-people.md#experten){.internal-link target=_blank} erhalten.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Nutzen Sie den Chat nur für andere allgemeine Gespräche.
|
||||
Wenn Sie Fragen haben, stellen Sie sie bei <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Diskussionen</a>, es besteht eine viel bessere Chance, dass Sie hier Hilfe von den [FastAPI-Experten](fastapi-people.md#experten){.internal-link target=_blank} erhalten.
|
||||
|
||||
Nutzen Sie den Chat nur für andere allgemeine Gespräche.
|
||||
|
||||
///
|
||||
|
||||
### Den Chat nicht für Fragen verwenden
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,15 @@ Und genau so für ReDoc ...
|
|||
{!../../../docs_src/custom_docs_ui/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die *Pfadoperation* für `swagger_ui_redirect` ist ein Hilfsmittel bei der Verwendung von OAuth2.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie Ihre API mit einem OAuth2-Anbieter integrieren, können Sie sich authentifizieren und mit den erworbenen Anmeldeinformationen zur API-Dokumentation zurückkehren. Und mit ihr interagieren, die echte OAuth2-Authentifizierung verwendend.
|
||||
Die *Pfadoperation* für `swagger_ui_redirect` ist ein Hilfsmittel bei der Verwendung von OAuth2.
|
||||
|
||||
Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „Umleitungs“-Helfer.
|
||||
Wenn Sie Ihre API mit einem OAuth2-Anbieter integrieren, können Sie sich authentifizieren und mit den erworbenen Anmeldeinformationen zur API-Dokumentation zurückkehren. Und mit ihr interagieren, die echte OAuth2-Authentifizierung verwendend.
|
||||
|
||||
Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „Umleitungs“-Helfer.
|
||||
|
||||
///
|
||||
|
||||
### Eine *Pfadoperation* erstellen, um es zu testen
|
||||
|
||||
|
|
@ -177,12 +180,15 @@ Und genau so für ReDoc ...
|
|||
{!../../../docs_src/custom_docs_ui/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die *Pfadoperation* für `swagger_ui_redirect` ist ein Hilfsmittel bei der Verwendung von OAuth2.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie Ihre API mit einem OAuth2-Anbieter integrieren, können Sie sich authentifizieren und mit den erworbenen Anmeldeinformationen zur API-Dokumentation zurückkehren. Und mit ihr interagieren, die echte OAuth2-Authentifizierung verwendend.
|
||||
Die *Pfadoperation* für `swagger_ui_redirect` ist ein Hilfsmittel bei der Verwendung von OAuth2.
|
||||
|
||||
Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „Umleitungs“-Helfer.
|
||||
Wenn Sie Ihre API mit einem OAuth2-Anbieter integrieren, können Sie sich authentifizieren und mit den erworbenen Anmeldeinformationen zur API-Dokumentation zurückkehren. Und mit ihr interagieren, die echte OAuth2-Authentifizierung verwendend.
|
||||
|
||||
Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „Umleitungs“-Helfer.
|
||||
|
||||
///
|
||||
|
||||
### Eine *Pfadoperation* erstellen, um statische Dateien zu testen
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@ Das kann insbesondere eine gute Alternative zur Logik in einer Middleware sein.
|
|||
|
||||
Wenn Sie beispielsweise den Requestbody lesen oder manipulieren möchten, bevor er von Ihrer Anwendung verarbeitet wird.
|
||||
|
||||
!!! danger "Gefahr"
|
||||
Dies ist eine „fortgeschrittene“ Funktion.
|
||||
/// danger | "Gefahr"
|
||||
|
||||
Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie diesen Abschnitt vielleicht überspringen.
|
||||
Dies ist eine „fortgeschrittene“ Funktion.
|
||||
|
||||
Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie diesen Abschnitt vielleicht überspringen.
|
||||
|
||||
///
|
||||
|
||||
## Anwendungsfälle
|
||||
|
||||
|
|
@ -27,8 +30,11 @@ Und eine `APIRoute`-Unterklasse zur Verwendung dieser benutzerdefinierten Reques
|
|||
|
||||
### Eine benutzerdefinierte `GzipRequest`-Klasse erstellen
|
||||
|
||||
!!! tip "Tipp"
|
||||
Dies ist nur ein einfaches Beispiel, um zu demonstrieren, wie es funktioniert. Wenn Sie Gzip-Unterstützung benötigen, können Sie die bereitgestellte [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} verwenden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Dies ist nur ein einfaches Beispiel, um zu demonstrieren, wie es funktioniert. Wenn Sie Gzip-Unterstützung benötigen, können Sie die bereitgestellte [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} verwenden.
|
||||
|
||||
///
|
||||
|
||||
Zuerst erstellen wir eine `GzipRequest`-Klasse, welche die Methode `Request.body()` überschreibt, um den Body bei Vorhandensein eines entsprechenden Headers zu dekomprimieren.
|
||||
|
||||
|
|
@ -54,16 +60,19 @@ Hier verwenden wir sie, um aus dem ursprünglichen Request einen `GzipRequest` z
|
|||
{!../../../docs_src/custom_request_and_route/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Ein `Request` hat ein `request.scope`-Attribut, welches einfach ein Python-`dict` ist, welches die mit dem Request verbundenen Metadaten enthält.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Ein `Request` hat auch ein `request.receive`, welches eine Funktion ist, die den Hauptteil des Requests empfängt.
|
||||
Ein `Request` hat ein `request.scope`-Attribut, welches einfach ein Python-`dict` ist, welches die mit dem Request verbundenen Metadaten enthält.
|
||||
|
||||
Das `scope`-`dict` und die `receive`-Funktion sind beide Teil der ASGI-Spezifikation.
|
||||
Ein `Request` hat auch ein `request.receive`, welches eine Funktion ist, die den Hauptteil des Requests empfängt.
|
||||
|
||||
Und diese beiden Dinge, `scope` und `receive`, werden benötigt, um eine neue `Request`-Instanz zu erstellen.
|
||||
Das `scope`-`dict` und die `receive`-Funktion sind beide Teil der ASGI-Spezifikation.
|
||||
|
||||
Um mehr über den `Request` zu erfahren, schauen Sie sich <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">Starlettes Dokumentation zu Requests</a> an.
|
||||
Und diese beiden Dinge, `scope` und `receive`, werden benötigt, um eine neue `Request`-Instanz zu erstellen.
|
||||
|
||||
Um mehr über den `Request` zu erfahren, schauen Sie sich <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">Starlettes Dokumentation zu Requests</a> an.
|
||||
|
||||
///
|
||||
|
||||
Das Einzige, was die von `GzipRequest.get_route_handler` zurückgegebene Funktion anders macht, ist die Konvertierung von `Request` in ein `GzipRequest`.
|
||||
|
||||
|
|
@ -75,10 +84,13 @@ Aufgrund unserer Änderungen in `GzipRequest.body` wird der Requestbody jedoch b
|
|||
|
||||
## Zugriff auf den Requestbody in einem Exceptionhandler
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um dasselbe Problem zu lösen, ist es wahrscheinlich viel einfacher, den `body` in einem benutzerdefinierten Handler für `RequestValidationError` zu verwenden ([Fehlerbehandlung](../tutorial/handling-errors.md#den-requestvalidationerror-body-verwenden){.internal-link target=_blank}).
|
||||
/// tip | "Tipp"
|
||||
|
||||
Dieses Beispiel ist jedoch immer noch gültig und zeigt, wie mit den internen Komponenten interagiert wird.
|
||||
Um dasselbe Problem zu lösen, ist es wahrscheinlich viel einfacher, den `body` in einem benutzerdefinierten Handler für `RequestValidationError` zu verwenden ([Fehlerbehandlung](../tutorial/handling-errors.md#den-requestvalidationerror-body-verwenden){.internal-link target=_blank}).
|
||||
|
||||
Dieses Beispiel ist jedoch immer noch gültig und zeigt, wie mit den internen Komponenten interagiert wird.
|
||||
|
||||
///
|
||||
|
||||
Wir können denselben Ansatz auch verwenden, um in einem Exceptionhandler auf den Requestbody zuzugreifen.
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,11 @@ Und diese Funktion `get_openapi()` erhält als Parameter:
|
|||
* `description`: Die Beschreibung Ihrer API. Dies kann Markdown enthalten und wird in der Dokumentation angezeigt.
|
||||
* `routes`: Eine Liste von Routen, dies sind alle registrierten *Pfadoperationen*. Sie stammen von `app.routes`.
|
||||
|
||||
!!! info
|
||||
Der Parameter `summary` ist in OpenAPI 3.1.0 und höher verfügbar und wird von FastAPI 0.99.0 und höher unterstützt.
|
||||
/// info
|
||||
|
||||
Der Parameter `summary` ist in OpenAPI 3.1.0 und höher verfügbar und wird von FastAPI 0.99.0 und höher unterstützt.
|
||||
|
||||
///
|
||||
|
||||
## Überschreiben der Standardeinstellungen
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@ Da **FastAPI** auf dem **ASGI**-Standard basiert, ist es sehr einfach, jede **Gr
|
|||
|
||||
Sie können normale FastAPI-*Pfadoperationen* mit GraphQL in derselben Anwendung kombinieren.
|
||||
|
||||
!!! tip "Tipp"
|
||||
**GraphQL** löst einige sehr spezifische Anwendungsfälle.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Es hat **Vorteile** und **Nachteile** im Vergleich zu gängigen **Web-APIs**.
|
||||
**GraphQL** löst einige sehr spezifische Anwendungsfälle.
|
||||
|
||||
Wiegen Sie ab, ob die **Vorteile** für Ihren Anwendungsfall die **Nachteile** ausgleichen. 🤓
|
||||
Es hat **Vorteile** und **Nachteile** im Vergleich zu gängigen **Web-APIs**.
|
||||
|
||||
Wiegen Sie ab, ob die **Vorteile** für Ihren Anwendungsfall die **Nachteile** ausgleichen. 🤓
|
||||
|
||||
///
|
||||
|
||||
## GraphQL-Bibliotheken
|
||||
|
||||
|
|
@ -46,8 +49,11 @@ Frühere Versionen von Starlette enthielten eine `GraphQLApp`-Klasse zur Integra
|
|||
|
||||
Das wurde von Starlette deprecated, aber wenn Sie Code haben, der das verwendet, können Sie einfach zu <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a> **migrieren**, welches denselben Anwendungsfall abdeckt und über eine **fast identische Schnittstelle** verfügt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie GraphQL benötigen, würde ich Ihnen trotzdem empfehlen, sich <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a> anzuschauen, da es auf Typannotationen basiert, statt auf benutzerdefinierten Klassen und Typen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie GraphQL benötigen, würde ich Ihnen trotzdem empfehlen, sich <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a> anzuschauen, da es auf Typannotationen basiert, statt auf benutzerdefinierten Klassen und Typen.
|
||||
|
||||
///
|
||||
|
||||
## Mehr darüber lernen
|
||||
|
||||
|
|
|
|||
|
|
@ -6,5 +6,8 @@ Die meisten dieser Ideen sind mehr oder weniger **unabhängig**, und in den meis
|
|||
|
||||
Wenn etwas für Ihr Projekt interessant und nützlich erscheint, lesen Sie es, andernfalls überspringen Sie es einfach.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie strukturiert **FastAPI lernen** möchten (empfohlen), lesen Sie stattdessen Kapitel für Kapitel das [Tutorial – Benutzerhandbuch](../tutorial/index.md){.internal-link target=_blank}.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie strukturiert **FastAPI lernen** möchten (empfohlen), lesen Sie stattdessen Kapitel für Kapitel das [Tutorial – Benutzerhandbuch](../tutorial/index.md){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -10,111 +10,123 @@ Sehen wir uns an, wie das funktioniert und wie Sie es bei Bedarf ändern können
|
|||
|
||||
Nehmen wir an, Sie haben ein Pydantic-Modell mit Defaultwerten wie dieses:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-7]!}
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-7]!}
|
||||
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
</details>
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-9]!}
|
||||
//// tab | Python 3.9+
|
||||
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-9]!}
|
||||
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
|
||||
</details>
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
</details>
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-9]!}
|
||||
////
|
||||
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-9]!}
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
### Modell für Eingabe
|
||||
|
||||
Wenn Sie dieses Modell wie hier als Eingabe verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-15]!}
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py[ln:1-15]!}
|
||||
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
</details>
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-17]!}
|
||||
//// tab | Python 3.9+
|
||||
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py[ln:1-17]!}
|
||||
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
|
||||
</details>
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
</details>
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-17]!}
|
||||
////
|
||||
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py[ln:1-17]!}
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
# Code unterhalb weggelassen 👇
|
||||
```
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>👀 Vollständige Dateivorschau</summary>
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
////
|
||||
|
||||
... dann ist das Feld `description` **nicht erforderlich**. Weil es den Defaultwert `None` hat.
|
||||
|
||||
|
|
@ -130,23 +142,29 @@ Sie können überprüfen, dass das Feld `description` in der Dokumentation kein
|
|||
|
||||
Wenn Sie jedoch dasselbe Modell als Ausgabe verwenden, wie hier:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... dann, weil `description` einen Defaultwert hat, wird es, wenn Sie für dieses Feld **nichts zurückgeben**, immer noch diesen **Defaultwert** haben.
|
||||
|
||||
|
|
@ -199,26 +217,35 @@ Der Hauptanwendungsfall hierfür besteht wahrscheinlich darin, dass Sie das mal
|
|||
|
||||
In diesem Fall können Sie diese Funktion in **FastAPI** mit dem Parameter `separate_input_output_schemas=False` deaktivieren.
|
||||
|
||||
!!! info
|
||||
Unterstützung für `separate_input_output_schemas` wurde in FastAPI `0.102.0` hinzugefügt. 🤓
|
||||
/// info
|
||||
|
||||
=== "Python 3.10+"
|
||||
Unterstützung für `separate_input_output_schemas` wurde in FastAPI `0.102.0` hinzugefügt. 🤓
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial002_py310.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial002_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/separate_openapi_schemas/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Gleiches Schema für Eingabe- und Ausgabemodelle in der Dokumentation
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ Dies ist lediglich eine **schnelle Anleitung / Auffrischung** über Pythons Typh
|
|||
|
||||
Aber selbst wenn Sie **FastAPI** nie verwenden, wird es für Sie nützlich sein, ein wenig darüber zu lernen.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Wenn Sie ein Python-Experte sind und bereits alles über Typhinweise wissen, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Wenn Sie ein Python-Experte sind und bereits alles über Typhinweise wissen, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
|
||||
|
||||
///
|
||||
|
||||
## Motivation
|
||||
|
||||
|
|
@ -170,45 +173,55 @@ Wenn Sie über die **neueste Version von Python** verfügen, verwenden Sie die B
|
|||
|
||||
Definieren wir zum Beispiel eine Variable, die eine `list` von `str` – eine Liste von Strings – sein soll.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
||||
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
||||
|
||||
Als Typ nehmen Sie `list`.
|
||||
Als Typ nehmen Sie `list`.
|
||||
|
||||
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
||||
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
Von `typing` importieren Sie `List` (mit Großbuchstaben `L`):
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
Von `typing` importieren Sie `List` (mit Großbuchstaben `L`):
|
||||
|
||||
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
Als Typ nehmen Sie das `List`, das Sie von `typing` importiert haben.
|
||||
Deklarieren Sie die Variable mit der gleichen Doppelpunkt-Syntax (`:`).
|
||||
|
||||
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
||||
Als Typ nehmen Sie das `List`, das Sie von `typing` importiert haben.
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
Da die Liste ein Typ ist, welcher innere Typen enthält, werden diese von eckigen Klammern umfasst:
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die inneren Typen in den eckigen Klammern werden als „Typ-Parameter“ bezeichnet.
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/python_types/tutorial006.py!}
|
||||
```
|
||||
|
||||
In diesem Fall ist `str` der Typ-Parameter, der an `List` übergeben wird (oder `list` in Python 3.9 und darüber).
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die inneren Typen in den eckigen Klammern werden als „Typ-Parameter“ bezeichnet.
|
||||
|
||||
In diesem Fall ist `str` der Typ-Parameter, der an `List` übergeben wird (oder `list` in Python 3.9 und darüber).
|
||||
|
||||
///
|
||||
|
||||
Das bedeutet: Die Variable `items` ist eine Liste – `list` – und jedes der Elemente in dieser Liste ist ein String – `str`.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie Python 3.9 oder höher verwenden, müssen Sie `List` nicht von `typing` importieren, Sie können stattdessen den regulären `list`-Typ verwenden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie Python 3.9 oder höher verwenden, müssen Sie `List` nicht von `typing` importieren, Sie können stattdessen den regulären `list`-Typ verwenden.
|
||||
|
||||
///
|
||||
|
||||
Auf diese Weise kann Ihr Editor Sie auch bei der Bearbeitung von Einträgen aus der Liste unterstützen:
|
||||
|
||||
|
|
@ -224,17 +237,21 @@ Und trotzdem weiß der Editor, dass es sich um ein `str` handelt, und bietet ent
|
|||
|
||||
Das Gleiche gilt für die Deklaration eines Tupels – `tuple` – und einer Menge – `set`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial007_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das bedeutet:
|
||||
|
||||
|
|
@ -249,17 +266,21 @@ Der erste Typ-Parameter ist für die Schlüssel des `dict`.
|
|||
|
||||
Der zweite Typ-Parameter ist für die Werte des `dict`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das bedeutet:
|
||||
|
||||
|
|
@ -275,17 +296,21 @@ In Python 3.6 und höher (inklusive Python 3.10) können Sie den `Union`-Typ von
|
|||
|
||||
In Python 3.10 gibt es zusätzlich eine **neue Syntax**, die es erlaubt, die möglichen Typen getrennt von einem <abbr title='Allgemein: „oder“. In anderem Zusammenhang auch „Bitweises ODER“, aber letztere Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> aufzulisten.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial008b_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008b.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial008b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In beiden Fällen bedeutet das, dass `item` ein `int` oder ein `str` sein kann.
|
||||
|
||||
|
|
@ -305,23 +330,29 @@ Wenn Sie `Optional[str]` anstelle von nur `str` verwenden, wird Ihr Editor Ihnen
|
|||
|
||||
Das bedeutet auch, dass Sie in Python 3.10 `Something | None` verwenden können:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/python_types/tutorial009_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ Alternative"
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009b.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ Alternative
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial009b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
#### `Union` oder `Optional` verwenden?
|
||||
|
||||
|
|
@ -366,47 +397,53 @@ Und dann müssen Sie sich nicht mehr um Namen wie `Optional` und `Union` kümmer
|
|||
|
||||
Diese Typen, die Typ-Parameter in eckigen Klammern akzeptieren, werden **generische Typen** oder **Generics** genannt.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
Sie können die eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin):
|
||||
Sie können die eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin):
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul:
|
||||
Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul:
|
||||
|
||||
* `Union`
|
||||
* `Optional` (so wie unter Python 3.8)
|
||||
* ... und andere.
|
||||
* `Union`
|
||||
* `Optional` (so wie unter Python 3.8)
|
||||
* ... und andere.
|
||||
|
||||
In Python 3.10 können Sie als Alternative zu den Generics `Union` und `Optional` den <abbr title='Allgemein: „oder“. In anderem Zusammenhang auch „Bitweises ODER“, aber letztere Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> verwenden, um Vereinigungen von Typen zu deklarieren, das ist besser und einfacher.
|
||||
In Python 3.10 können Sie als Alternative zu den Generics `Union` und `Optional` den <abbr title='Allgemein: „oder“. In anderem Zusammenhang auch „Bitweises ODER“, aber letztere Bedeutung ist hier nicht relevant'>vertikalen Balken (`|`)</abbr> verwenden, um Vereinigungen von Typen zu deklarieren, das ist besser und einfacher.
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
Sie können die eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin):
|
||||
//// tab | Python 3.9+
|
||||
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
Sie können die eingebauten Typen als Generics verwenden (mit eckigen Klammern und Typen darin):
|
||||
|
||||
Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul:
|
||||
* `list`
|
||||
* `tuple`
|
||||
* `set`
|
||||
* `dict`
|
||||
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ... und andere.
|
||||
Verwenden Sie für den Rest, wie unter Python 3.8, das `typing`-Modul:
|
||||
|
||||
=== "Python 3.8+"
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ... und andere.
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ... und andere.
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Set`
|
||||
* `Dict`
|
||||
* `Union`
|
||||
* `Optional`
|
||||
* ... und andere.
|
||||
|
||||
////
|
||||
|
||||
### Klassen als Typen
|
||||
|
||||
|
|
@ -446,55 +483,71 @@ Und Sie erhalten volle Editor-Unterstützung für dieses Objekt.
|
|||
|
||||
Ein Beispiel aus der offiziellen Pydantic Dokumentation:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011_py39.py!}
|
||||
```
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! info
|
||||
Um mehr über <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic zu erfahren, schauen Sie sich dessen Dokumentation an</a>.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/python_types/tutorial011.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
Um mehr über <a href="https://pydantic-docs.helpmanual.io/" class="external-link" target="_blank">Pydantic zu erfahren, schauen Sie sich dessen Dokumentation an</a>.
|
||||
|
||||
///
|
||||
|
||||
**FastAPI** basiert vollständig auf Pydantic.
|
||||
|
||||
Viel mehr von all dem werden Sie in praktischer Anwendung im [Tutorial - Benutzerhandbuch](tutorial/index.md){.internal-link target=_blank} sehen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Pydantic verhält sich speziell, wenn Sie `Optional` oder `Union[Etwas, None]` ohne einen Default-Wert verwenden. Sie können darüber in der Pydantic Dokumentation unter <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Required fields</a> mehr erfahren.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Pydantic verhält sich speziell, wenn Sie `Optional` oder `Union[Etwas, None]` ohne einen Default-Wert verwenden. Sie können darüber in der Pydantic Dokumentation unter <a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Required fields</a> mehr erfahren.
|
||||
|
||||
///
|
||||
|
||||
## Typhinweise mit Metadaten-Annotationen
|
||||
|
||||
Python bietet auch die Möglichkeit, **zusätzliche Metadaten** in Typhinweisen unterzubringen, mittels `Annotated`.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
In Python 3.9 ist `Annotated` ein Teil der Standardbibliothek, Sie können es von `typing` importieren.
|
||||
In Python 3.9 ist `Annotated` ein Teil der Standardbibliothek, Sie können es von `typing` importieren.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013_py39.py!}
|
||||
```
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
In Versionen niedriger als Python 3.9 importieren Sie `Annotated` von `typing_extensions`.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
Es wird bereits mit **FastAPI** installiert sein.
|
||||
In Versionen niedriger als Python 3.9 importieren Sie `Annotated` von `typing_extensions`.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013.py!}
|
||||
```
|
||||
Es wird bereits mit **FastAPI** installiert sein.
|
||||
|
||||
```Python hl_lines="1 4"
|
||||
{!> ../../../docs_src/python_types/tutorial013.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Python selbst macht nichts mit `Annotated`. Für Editoren und andere Tools ist der Typ immer noch `str`.
|
||||
|
||||
|
|
@ -506,10 +559,13 @@ Im Moment müssen Sie nur wissen, dass `Annotated` existiert, und dass es Standa
|
|||
|
||||
Später werden Sie sehen, wie **mächtig** es sein kann.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Der Umstand, dass es **Standard-Python** ist, bedeutet, dass Sie immer noch die **bestmögliche Entwickler-Erfahrung** in ihrem Editor haben, sowie mit den Tools, die Sie nutzen, um ihren Code zu analysieren, zu refaktorisieren, usw. ✨
|
||||
/// tip | "Tipp"
|
||||
|
||||
Und ebenfalls, dass Ihr Code sehr kompatibel mit vielen anderen Python-Tools und -Bibliotheken sein wird. 🚀
|
||||
Der Umstand, dass es **Standard-Python** ist, bedeutet, dass Sie immer noch die **bestmögliche Entwickler-Erfahrung** in ihrem Editor haben, sowie mit den Tools, die Sie nutzen, um ihren Code zu analysieren, zu refaktorisieren, usw. ✨
|
||||
|
||||
Und ebenfalls, dass Ihr Code sehr kompatibel mit vielen anderen Python-Tools und -Bibliotheken sein wird. 🚀
|
||||
|
||||
///
|
||||
|
||||
## Typhinweise in **FastAPI**
|
||||
|
||||
|
|
@ -533,5 +589,8 @@ Das mag alles abstrakt klingen. Machen Sie sich keine Sorgen. Sie werden all das
|
|||
|
||||
Das Wichtigste ist, dass **FastAPI** durch die Verwendung von Standard-Python-Typen an einer einzigen Stelle (anstatt weitere Klassen, Dekoratoren usw. hinzuzufügen) einen Großteil der Arbeit für Sie erledigt.
|
||||
|
||||
!!! info
|
||||
Wenn Sie bereits das ganze Tutorial durchgearbeitet haben und mehr über Typen erfahren wollen, dann ist eine gute Ressource <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">der „Cheat Sheet“ von `mypy`</a>.
|
||||
/// info
|
||||
|
||||
Wenn Sie bereits das ganze Tutorial durchgearbeitet haben und mehr über Typen erfahren wollen, dann ist eine gute Ressource <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">der „Cheat Sheet“ von `mypy`</a>.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -4,5 +4,8 @@ Hier ist die Referenz oder Code-API, die Klassen, Funktionen, Parameter, Attribu
|
|||
|
||||
Wenn Sie **FastAPI** lernen möchten, ist es viel besser, das [FastAPI-Tutorial](https://fastapi.tiangolo.com/tutorial/) zu lesen.
|
||||
|
||||
!!! note "Hinweis Deutsche Übersetzung"
|
||||
Die nachfolgende API wird aus der Quelltext-Dokumentation erstellt, daher sind nur die Einleitungen auf Deutsch.
|
||||
/// note | "Hinweis Deutsche Übersetzung"
|
||||
|
||||
Die nachfolgende API wird aus der Quelltext-Dokumentation erstellt, daher sind nur die Einleitungen auf Deutsch.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ Sie können es direkt von `fastapi` importieren:
|
|||
from fastapi import Request
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie Abhängigkeiten definieren möchten, die sowohl mit HTTP als auch mit WebSockets kompatibel sein sollen, können Sie einen Parameter definieren, der eine `HTTPConnection` anstelle eines `Request` oder eines `WebSocket` akzeptiert.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie Abhängigkeiten definieren möchten, die sowohl mit HTTP als auch mit WebSockets kompatibel sein sollen, können Sie einen Parameter definieren, der eine `HTTPConnection` anstelle eines `Request` oder eines `WebSocket` akzeptiert.
|
||||
|
||||
///
|
||||
|
||||
::: fastapi.Request
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ Bei der Definition von WebSockets deklarieren Sie normalerweise einen Parameter
|
|||
from fastapi import WebSocket
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie Abhängigkeiten definieren möchten, die sowohl mit HTTP als auch mit WebSockets kompatibel sein sollen, können Sie einen Parameter definieren, der eine `HTTPConnection` anstelle eines `Request` oder eines `WebSocket` akzeptiert.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie Abhängigkeiten definieren möchten, die sowohl mit HTTP als auch mit WebSockets kompatibel sein sollen, können Sie einen Parameter definieren, der eine `HTTPConnection` anstelle eines `Request` oder eines `WebSocket` akzeptiert.
|
||||
|
||||
///
|
||||
|
||||
::: fastapi.WebSocket
|
||||
options:
|
||||
|
|
|
|||
|
|
@ -57,41 +57,57 @@ Die Verwendung von `BackgroundTasks` funktioniert auch mit dem <abbr title="Einb
|
|||
|
||||
**FastAPI** weiß, was jeweils zu tun ist und wie dasselbe Objekt wiederverwendet werden kann, sodass alle Hintergrundtasks zusammengeführt und anschließend im Hintergrund ausgeführt werden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="14 16 23 26"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="14 16 23 26"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="11 13 20 23"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11 13 20 23"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="13 15 22 25"
|
||||
{!> ../../../docs_src/background_tasks/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In obigem Beispiel werden die Nachrichten, *nachdem* die Response gesendet wurde, in die Datei `log.txt` geschrieben.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@ Wenn Sie eine Anwendung oder eine Web-API erstellen, ist es selten der Fall, das
|
|||
|
||||
**FastAPI** bietet ein praktisches Werkzeug zur Strukturierung Ihrer Anwendung bei gleichzeitiger Wahrung der Flexibilität.
|
||||
|
||||
!!! info
|
||||
Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints.
|
||||
/// info
|
||||
|
||||
Wenn Sie von Flask kommen, wäre dies das Äquivalent zu Flasks Blueprints.
|
||||
|
||||
///
|
||||
|
||||
## Eine Beispiel-Dateistruktur
|
||||
|
||||
|
|
@ -26,16 +29,19 @@ Nehmen wir an, Sie haben eine Dateistruktur wie diese:
|
|||
│ └── admin.py
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Es gibt mehrere `__init__.py`-Dateien: eine in jedem Verzeichnis oder Unterverzeichnis.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Das ermöglicht den Import von Code aus einer Datei in eine andere.
|
||||
Es gibt mehrere `__init__.py`-Dateien: eine in jedem Verzeichnis oder Unterverzeichnis.
|
||||
|
||||
In `app/main.py` könnten Sie beispielsweise eine Zeile wie diese haben:
|
||||
Das ermöglicht den Import von Code aus einer Datei in eine andere.
|
||||
|
||||
```
|
||||
from app.routers import items
|
||||
```
|
||||
In `app/main.py` könnten Sie beispielsweise eine Zeile wie diese haben:
|
||||
|
||||
```
|
||||
from app.routers import items
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
* Das Verzeichnis `app` enthält alles. Und es hat eine leere Datei `app/__init__.py`, es handelt sich also um ein „Python-Package“ (eine Sammlung von „Python-Modulen“): `app`.
|
||||
* Es enthält eine Datei `app/main.py`. Da sie sich in einem Python-Package (einem Verzeichnis mit einer Datei `__init__.py`) befindet, ist sie ein „Modul“ dieses Packages: `app.main`.
|
||||
|
|
@ -99,8 +105,11 @@ Alle die gleichen Optionen werden unterstützt.
|
|||
|
||||
Alle die gleichen `parameters`, `responses`, `dependencies`, `tags`, usw.
|
||||
|
||||
!!! tip "Tipp"
|
||||
In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beliebigen Namen geben.
|
||||
/// tip | "Tipp"
|
||||
|
||||
In diesem Beispiel heißt die Variable `router`, aber Sie können ihr einen beliebigen Namen geben.
|
||||
|
||||
///
|
||||
|
||||
Wir werden diesen `APIRouter` in die Hauptanwendung `FastAPI` einbinden, aber zuerst kümmern wir uns um die Abhängigkeiten und einen anderen `APIRouter`.
|
||||
|
||||
|
|
@ -112,31 +121,43 @@ Also fügen wir sie in ihr eigenes `dependencies`-Modul (`app/dependencies.py`)
|
|||
|
||||
Wir werden nun eine einfache Abhängigkeit verwenden, um einen benutzerdefinierten `X-Token`-Header zu lesen:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="3 6-8" title="app/dependencies.py"
|
||||
{!> ../../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
|
||||
```
|
||||
```Python hl_lines="3 6-8" title="app/dependencies.py"
|
||||
{!> ../../../docs_src/bigger_applications/app_an_py39/dependencies.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 5-7" title="app/dependencies.py"
|
||||
{!> ../../../docs_src/bigger_applications/app_an/dependencies.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="1 5-7" title="app/dependencies.py"
|
||||
{!> ../../../docs_src/bigger_applications/app_an/dependencies.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="1 4-6" title="app/dependencies.py"
|
||||
{!> ../../../docs_src/bigger_applications/app/dependencies.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um dieses Beispiel zu vereinfachen, verwenden wir einen erfundenen Header.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](security/index.md){.internal-link target=_blank} bessere Ergebnisse erzielen.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 4-6" title="app/dependencies.py"
|
||||
{!> ../../../docs_src/bigger_applications/app/dependencies.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um dieses Beispiel zu vereinfachen, verwenden wir einen erfundenen Header.
|
||||
|
||||
Aber in der Praxis werden Sie mit den integrierten [Sicherheits-Werkzeugen](security/index.md){.internal-link target=_blank} bessere Ergebnisse erzielen.
|
||||
|
||||
///
|
||||
|
||||
## Ein weiteres Modul mit `APIRouter`.
|
||||
|
||||
|
|
@ -180,8 +201,11 @@ Wir können auch eine Liste von `tags` und zusätzliche `responses` hinzufügen,
|
|||
|
||||
Und wir können eine Liste von `dependencies` hinzufügen, die allen *Pfadoperationen* im Router hinzugefügt und für jeden an sie gerichteten Request ausgeführt/aufgelöst werden.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass ähnlich wie bei [Abhängigkeiten in *Pfadoperation-Dekoratoren*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} kein Wert an Ihre *Pfadoperation-Funktion* übergeben wird.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass ähnlich wie bei [Abhängigkeiten in *Pfadoperation-Dekoratoren*](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} kein Wert an Ihre *Pfadoperation-Funktion* übergeben wird.
|
||||
|
||||
///
|
||||
|
||||
Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten:
|
||||
|
||||
|
|
@ -198,11 +222,17 @@ Das Endergebnis ist, dass die Pfade für diese Artikel jetzt wie folgt lauten:
|
|||
* Zuerst werden die Router-Abhängigkeiten ausgeführt, dann die [`dependencies` im Dekorator](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} und dann die normalen Parameterabhängigkeiten.
|
||||
* Sie können auch [`Security`-Abhängigkeiten mit `scopes`](../advanced/security/oauth2-scopes.md){.internal-link target=_blank} hinzufügen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
`dependencies` im `APIRouter` können beispielsweise verwendet werden, um eine Authentifizierung für eine ganze Gruppe von *Pfadoperationen* zu erfordern. Selbst wenn die Abhängigkeiten nicht jeder einzeln hinzugefügt werden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! check
|
||||
Die Parameter `prefix`, `tags`, `responses` und `dependencies` sind (wie in vielen anderen Fällen) nur ein Feature von **FastAPI**, um Ihnen dabei zu helfen, Codeverdoppelung zu vermeiden.
|
||||
`dependencies` im `APIRouter` können beispielsweise verwendet werden, um eine Authentifizierung für eine ganze Gruppe von *Pfadoperationen* zu erfordern. Selbst wenn die Abhängigkeiten nicht jeder einzeln hinzugefügt werden.
|
||||
|
||||
///
|
||||
|
||||
/// check
|
||||
|
||||
Die Parameter `prefix`, `tags`, `responses` und `dependencies` sind (wie in vielen anderen Fällen) nur ein Feature von **FastAPI**, um Ihnen dabei zu helfen, Codeverdoppelung zu vermeiden.
|
||||
|
||||
///
|
||||
|
||||
### Die Abhängigkeiten importieren
|
||||
|
||||
|
|
@ -218,8 +248,11 @@ Daher verwenden wir einen relativen Import mit `..` für die Abhängigkeiten:
|
|||
|
||||
#### Wie relative Importe funktionieren
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie genau wissen, wie Importe funktionieren, fahren Sie mit dem nächsten Abschnitt unten fort.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie genau wissen, wie Importe funktionieren, fahren Sie mit dem nächsten Abschnitt unten fort.
|
||||
|
||||
///
|
||||
|
||||
Ein einzelner Punkt `.`, wie in:
|
||||
|
||||
|
|
@ -286,10 +319,13 @@ Aber wir können immer noch _mehr_ `tags` hinzufügen, die auf eine bestimmte *P
|
|||
{!../../../docs_src/bigger_applications/app/routers/items.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Diese letzte Pfadoperation wird eine Kombination von Tags haben: `["items", "custom"]`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`.
|
||||
Diese letzte Pfadoperation wird eine Kombination von Tags haben: `["items", "custom"]`.
|
||||
|
||||
Und sie wird auch beide Responses in der Dokumentation haben, eine für `404` und eine für `403`.
|
||||
|
||||
///
|
||||
|
||||
## Das Haupt-`FastAPI`.
|
||||
|
||||
|
|
@ -345,20 +381,23 @@ Wir könnten sie auch wie folgt importieren:
|
|||
from app.routers import items, users
|
||||
```
|
||||
|
||||
!!! info
|
||||
Die erste Version ist ein „relativer Import“:
|
||||
/// info
|
||||
|
||||
```Python
|
||||
from .routers import items, users
|
||||
```
|
||||
Die erste Version ist ein „relativer Import“:
|
||||
|
||||
Die zweite Version ist ein „absoluter Import“:
|
||||
```Python
|
||||
from .routers import items, users
|
||||
```
|
||||
|
||||
```Python
|
||||
from app.routers import items, users
|
||||
```
|
||||
Die zweite Version ist ein „absoluter Import“:
|
||||
|
||||
Um mehr über Python-Packages und -Module zu erfahren, lesen Sie <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">die offizielle Python-Dokumentation über Module</a>.
|
||||
```Python
|
||||
from app.routers import items, users
|
||||
```
|
||||
|
||||
Um mehr über Python-Packages und -Module zu erfahren, lesen Sie <a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">die offizielle Python-Dokumentation über Module</a>.
|
||||
|
||||
///
|
||||
|
||||
### Namenskollisionen vermeiden
|
||||
|
||||
|
|
@ -390,26 +429,35 @@ Inkludieren wir nun die `router` aus diesen Submodulen `users` und `items`:
|
|||
{!../../../docs_src/bigger_applications/app/main.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
`users.router` enthält den `APIRouter` in der Datei `app/routers/users.py`.
|
||||
/// info
|
||||
|
||||
Und `items.router` enthält den `APIRouter` in der Datei `app/routers/items.py`.
|
||||
`users.router` enthält den `APIRouter` in der Datei `app/routers/users.py`.
|
||||
|
||||
Und `items.router` enthält den `APIRouter` in der Datei `app/routers/items.py`.
|
||||
|
||||
///
|
||||
|
||||
Mit `app.include_router()` können wir jeden `APIRouter` zur Hauptanwendung `FastAPI` hinzufügen.
|
||||
|
||||
Es wird alle Routen von diesem Router als Teil von dieser inkludieren.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Tatsächlich wird intern eine *Pfadoperation* für jede *Pfadoperation* erstellt, die im `APIRouter` deklariert wurde.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles dieselbe einzige Anwendung wäre.
|
||||
Tatsächlich wird intern eine *Pfadoperation* für jede *Pfadoperation* erstellt, die im `APIRouter` deklariert wurde.
|
||||
|
||||
!!! check
|
||||
Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Performanz machen.
|
||||
Hinter den Kulissen wird es also tatsächlich so funktionieren, als ob alles dieselbe einzige Anwendung wäre.
|
||||
|
||||
Dies dauert Mikrosekunden und geschieht nur beim Start.
|
||||
///
|
||||
|
||||
Es hat also keinen Einfluss auf die Leistung. ⚡
|
||||
/// check
|
||||
|
||||
Bei der Einbindung von Routern müssen Sie sich keine Gedanken über die Performanz machen.
|
||||
|
||||
Dies dauert Mikrosekunden und geschieht nur beim Start.
|
||||
|
||||
Es hat also keinen Einfluss auf die Leistung. ⚡
|
||||
|
||||
///
|
||||
|
||||
### Einen `APIRouter` mit benutzerdefinierten `prefix`, `tags`, `responses` und `dependencies` einfügen
|
||||
|
||||
|
|
@ -456,16 +504,19 @@ Hier machen wir es ... nur um zu zeigen, dass wir es können 🤷:
|
|||
|
||||
und es wird korrekt funktionieren, zusammen mit allen anderen *Pfadoperationen*, die mit `app.include_router()` hinzugefügt wurden.
|
||||
|
||||
!!! info "Sehr technische Details"
|
||||
**Hinweis**: Dies ist ein sehr technisches Detail, das Sie wahrscheinlich **einfach überspringen** können.
|
||||
/// info | "Sehr technische Details"
|
||||
|
||||
---
|
||||
**Hinweis**: Dies ist ein sehr technisches Detail, das Sie wahrscheinlich **einfach überspringen** können.
|
||||
|
||||
Die `APIRouter` sind nicht „gemountet“, sie sind nicht vom Rest der Anwendung isoliert.
|
||||
---
|
||||
|
||||
Das liegt daran, dass wir deren *Pfadoperationen* in das OpenAPI-Schema und die Benutzeroberflächen einbinden möchten.
|
||||
Die `APIRouter` sind nicht „gemountet“, sie sind nicht vom Rest der Anwendung isoliert.
|
||||
|
||||
Da wir sie nicht einfach isolieren und unabhängig vom Rest „mounten“ können, werden die *Pfadoperationen* „geklont“ (neu erstellt) und nicht direkt einbezogen.
|
||||
Das liegt daran, dass wir deren *Pfadoperationen* in das OpenAPI-Schema und die Benutzeroberflächen einbinden möchten.
|
||||
|
||||
Da wir sie nicht einfach isolieren und unabhängig vom Rest „mounten“ können, werden die *Pfadoperationen* „geklont“ (neu erstellt) und nicht direkt einbezogen.
|
||||
|
||||
///
|
||||
|
||||
## Es in der automatischen API-Dokumentation ansehen
|
||||
|
||||
|
|
|
|||
|
|
@ -6,98 +6,139 @@ So wie Sie zusätzliche Validation und Metadaten in Parametern der **Pfadoperati
|
|||
|
||||
Importieren Sie es zuerst:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
|
||||
```
|
||||
```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!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fastapi`, wie die anderen (`Query`, `Path`, `Body`, usw.)
|
||||
///
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Beachten Sie, dass `Field` direkt von `pydantic` importiert wird, nicht von `fastapi`, wie die anderen (`Query`, `Path`, `Body`, usw.)
|
||||
|
||||
///
|
||||
|
||||
## Modellattribute deklarieren
|
||||
|
||||
Dann können Sie `Field` mit Modellattributen deklarieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py310.py!}
|
||||
```
|
||||
```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!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="12-15"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="12-15"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/body_fields/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11-14"
|
||||
{!> ../../../docs_src/body_fields/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
`Field` funktioniert genauso wie `Query`, `Path` und `Body`, es hat die gleichen Parameter, usw.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Tatsächlich erstellen `Query`, `Path` und andere, die sie kennenlernen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, die ihrerseits eine Unterklasse von Pydantics `FieldInfo`-Klasse ist.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück.
|
||||
Tatsächlich erstellen `Query`, `Path` und andere, die sie kennenlernen werden, Instanzen von Unterklassen einer allgemeinen Klasse `Param`, die ihrerseits eine Unterklasse von Pydantics `FieldInfo`-Klasse ist.
|
||||
|
||||
`Body` gibt auch Instanzen einer Unterklasse von `FieldInfo` zurück. Und später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind.
|
||||
Und Pydantics `Field` gibt ebenfalls eine Instanz von `FieldInfo` zurück.
|
||||
|
||||
Denken Sie daran, dass `Query`, `Path` und andere von `fastapi` tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
|
||||
`Body` gibt auch Instanzen einer Unterklasse von `FieldInfo` zurück. Und später werden Sie andere sehen, die Unterklassen der `Body`-Klasse sind.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass jedes Modellattribut mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer Pfadoperation-Funktion, nur mit `Field` statt `Path`, `Query`, `Body`.
|
||||
Denken Sie daran, dass `Query`, `Path` und andere von `fastapi` tatsächlich Funktionen sind, die spezielle Klassen zurückgeben.
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Beachten Sie, dass jedes Modellattribut mit einem Typ, Defaultwert und `Field` die gleiche Struktur hat wie ein Parameter einer Pfadoperation-Funktion, nur mit `Field` statt `Path`, `Query`, `Body`.
|
||||
|
||||
///
|
||||
|
||||
## Zusätzliche Information hinzufügen
|
||||
|
||||
|
|
@ -105,8 +146,11 @@ Sie können zusätzliche Information in `Field`, `Query`, `Body`, usw. deklarier
|
|||
|
||||
Sie werden später mehr darüber lernen, wie man zusätzliche Information unterbringt, wenn Sie lernen, Beispiele zu deklarieren.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel nicht notwendigerweise Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Extra-Schlüssel, die `Field` überreicht werden, werden auch im resultierenden OpenAPI-Schema Ihrer Anwendung gelistet. Da diese Schlüssel nicht notwendigerweise Teil der OpenAPI-Spezifikation sind, könnten einige OpenAPI-Tools, wie etwa [der OpenAPI-Validator](https://validator.swagger.io/), nicht mit Ihrem generierten Schema funktionieren.
|
||||
|
||||
///
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -8,44 +8,63 @@ Zuerst einmal, Sie können `Path`-, `Query`- und Requestbody-Parameter-Deklarati
|
|||
|
||||
Und Sie können auch Body-Parameter als optional kennzeichnen, indem Sie den Defaultwert auf `None` setzen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="18-20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="18-20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18-20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="18-20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="19-21"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="19-21"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17-19"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="19-21"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, optional ist. Da es `None` als Defaultwert hat.
|
||||
///
|
||||
|
||||
```Python hl_lines="17-19"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19-21"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// note | "Hinweis"
|
||||
|
||||
Beachten Sie, dass in diesem Fall das `item`, welches vom Body genommen wird, optional ist. Da es `None` als Defaultwert hat.
|
||||
|
||||
///
|
||||
|
||||
## Mehrere Body-Parameter
|
||||
|
||||
|
|
@ -62,17 +81,21 @@ Im vorherigen Beispiel erwartete die *Pfadoperation* einen JSON-Body mit den Att
|
|||
|
||||
Aber Sie können auch mehrere Body-Parameter deklarieren, z. B. `item` und `user`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall wird **FastAPI** bemerken, dass es mehr als einen Body-Parameter in der Funktion gibt (zwei Parameter, die Pydantic-Modelle sind).
|
||||
|
||||
|
|
@ -93,8 +116,11 @@ Es wird deshalb die Parameternamen als Schlüssel (Feldnamen) im Body verwenden,
|
|||
}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem Schlüssel `item` im Body erwartet wird.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Beachten Sie, dass, obwohl `item` wie zuvor deklariert wurde, es nun unter einem Schlüssel `item` im Body erwartet wird.
|
||||
|
||||
///
|
||||
|
||||
**FastAPI** wird die automatische Konvertierung des Requests übernehmen, sodass der Parameter `item` seinen spezifischen Inhalt bekommt, genau so wie der Parameter `user`.
|
||||
|
||||
|
|
@ -110,41 +136,57 @@ Wenn Sie diesen Parameter einfach so hinzufügen, wird **FastAPI** annehmen, das
|
|||
|
||||
Aber Sie können **FastAPI** instruieren, ihn als weiteren Body-Schlüssel zu erkennen, indem Sie `Body` verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall erwartet **FastAPI** einen Body wie:
|
||||
|
||||
|
|
@ -184,44 +226,63 @@ q: str | None = None
|
|||
|
||||
Zum Beispiel:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="28"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="28"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! info
|
||||
`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query` und `Path` und andere, die Sie später kennenlernen.
|
||||
///
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="27"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
`Body` hat die gleichen zusätzlichen Validierungs- und Metadaten-Parameter wie `Query` und `Path` und andere, die Sie später kennenlernen.
|
||||
|
||||
///
|
||||
|
||||
## Einen einzelnen Body-Parameter einbetten
|
||||
|
||||
|
|
@ -237,41 +298,57 @@ item: Item = Body(embed=True)
|
|||
|
||||
so wie in:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/body_multiple_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall erwartet **FastAPI** einen Body wie:
|
||||
|
||||
|
|
|
|||
|
|
@ -6,17 +6,21 @@ Mit **FastAPI** können Sie (dank Pydantic) beliebig tief verschachtelte Modelle
|
|||
|
||||
Sie können ein Attribut als Kindtyp definieren, zum Beispiel eine Python-`list`e.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das bewirkt, dass `tags` eine Liste ist, wenngleich es nichts über den Typ der Elemente der Liste aussagt.
|
||||
|
||||
|
|
@ -61,23 +65,29 @@ Verwenden Sie dieselbe Standardsyntax für Modellattribute mit inneren Typen.
|
|||
|
||||
In unserem Beispiel können wir also bewirken, dass `tags` spezifisch eine „Liste von Strings“ ist:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Set-Typen
|
||||
|
||||
|
|
@ -87,23 +97,29 @@ Python hat einen Datentyp speziell für Mengen eindeutiger Dinge: das <abbr titl
|
|||
|
||||
Deklarieren wir also `tags` als Set von Strings.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1 14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 14"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Jetzt, selbst wenn Sie einen Request mit duplizierten Daten erhalten, werden diese zu einem Set eindeutiger Dinge konvertiert.
|
||||
|
||||
|
|
@ -125,45 +141,57 @@ Alles das beliebig tief verschachtelt.
|
|||
|
||||
Wir können zum Beispiel ein `Image`-Modell definieren.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7-9"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7-9"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Das Kindmodell als Typ verwenden
|
||||
|
||||
Und dann können wir es als Typ eines Attributes verwenden.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das würde bedeuten, dass **FastAPI** einen Body erwartet wie:
|
||||
|
||||
|
|
@ -196,23 +224,29 @@ Um alle Optionen kennenzulernen, die Sie haben, schauen Sie sich <a href="https:
|
|||
|
||||
Da wir zum Beispiel im `Image`-Modell ein Feld `url` haben, können wir deklarieren, dass das eine Instanz von Pydantics `HttpUrl` sein soll, anstelle eines `str`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="2 8"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
|
||||
```
|
||||
```Python hl_lines="2 8"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="4 10"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="4 10"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="4 10"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="4 10"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in JSON Schema / OpenAPI dokumentiert.
|
||||
|
||||
|
|
@ -220,23 +254,29 @@ Es wird getestet, ob der String eine gültige URL ist, und als solche wird er in
|
|||
|
||||
Sie können Pydantic-Modelle auch als Typen innerhalb von `list`, `set`, usw. verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
|
||||
```
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial006_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial006_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie:
|
||||
|
||||
|
|
@ -264,33 +304,45 @@ Das wird einen JSON-Body erwarten (konvertieren, validieren, dokumentieren), wie
|
|||
}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat.
|
||||
/// info
|
||||
|
||||
Beachten Sie, dass der `images`-Schlüssel jetzt eine Liste von Bild-Objekten hat.
|
||||
|
||||
///
|
||||
|
||||
## Tief verschachtelte Modelle
|
||||
|
||||
Sie können beliebig tief verschachtelte Modelle definieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7 12 18 21 25"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7 12 18 21 25"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial007_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9 14 20 23 27"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9 14 20 23 27"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial007_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9 14 20 23 27"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! info
|
||||
Beachten Sie, wie `Offer` eine Liste von `Item`s hat, von denen jedes seinerseits eine optionale Liste von `Image`s hat.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9 14 20 23 27"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial007.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
Beachten Sie, wie `Offer` eine Liste von `Item`s hat, von denen jedes seinerseits eine optionale Liste von `Image`s hat.
|
||||
|
||||
///
|
||||
|
||||
## Bodys aus reinen Listen
|
||||
|
||||
|
|
@ -308,17 +360,21 @@ images: list[Image]
|
|||
|
||||
so wie in:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
|
||||
```
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial008_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial008.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Editor-Unterstützung überall
|
||||
|
||||
|
|
@ -348,26 +404,33 @@ Das schauen wir uns mal an.
|
|||
|
||||
Im folgenden Beispiel akzeptieren Sie irgendein `dict`, solange es `int`-Schlüssel und `float`-Werte hat.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
|
||||
```
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial009_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt.
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/body_nested_models/tutorial009.py!}
|
||||
```
|
||||
|
||||
Aber Pydantic hat automatische Datenkonvertierung.
|
||||
////
|
||||
|
||||
Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Und das `dict` welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben.
|
||||
Bedenken Sie, dass JSON nur `str` als Schlüssel unterstützt.
|
||||
|
||||
Aber Pydantic hat automatische Datenkonvertierung.
|
||||
|
||||
Das bedeutet, dass Ihre API-Clients nur Strings senden können, aber solange diese Strings nur Zahlen enthalten, wird Pydantic sie konvertieren und validieren.
|
||||
|
||||
Und das `dict` welches Sie als `weights` erhalten, wird `int`-Schlüssel und `float`-Werte haben.
|
||||
|
||||
///
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -6,23 +6,29 @@ Um einen Artikel zu aktualisieren, können Sie die <a href="https://developer.mo
|
|||
|
||||
Sie können den `jsonable_encoder` verwenden, um die empfangenen Daten in etwas zu konvertieren, das als JSON gespeichert werden kann (in z. B. einer NoSQL-Datenbank). Zum Beispiel, um ein `datetime` in einen `str` zu konvertieren.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="28-33"
|
||||
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="28-33"
|
||||
{!> ../../../docs_src/body_updates/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="30-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="30-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="30-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial001.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="30-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
`PUT` wird verwendet, um Daten zu empfangen, die die existierenden Daten ersetzen sollen.
|
||||
|
||||
|
|
@ -48,14 +54,17 @@ Sie können auch die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/
|
|||
|
||||
Das bedeutet, sie senden nur die Daten, die Sie aktualisieren wollen, der Rest bleibt unverändert.
|
||||
|
||||
!!! note "Hinweis"
|
||||
`PATCH` wird seltener verwendet und ist weniger bekannt als `PUT`.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Und viele Teams verwenden ausschließlich `PUT`, selbst für nur Teil-Aktualisierungen.
|
||||
`PATCH` wird seltener verwendet und ist weniger bekannt als `PUT`.
|
||||
|
||||
Es steht Ihnen **frei**, das zu verwenden, was Sie möchten, **FastAPI** legt Ihnen keine Einschränkungen auf.
|
||||
Und viele Teams verwenden ausschließlich `PUT`, selbst für nur Teil-Aktualisierungen.
|
||||
|
||||
Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweise verwendet werden.
|
||||
Es steht Ihnen **frei**, das zu verwenden, was Sie möchten, **FastAPI** legt Ihnen keine Einschränkungen auf.
|
||||
|
||||
Aber dieser Leitfaden zeigt Ihnen mehr oder weniger, wie die beiden normalerweise verwendet werden.
|
||||
|
||||
///
|
||||
|
||||
### Pydantics `exclude_unset`-Parameter verwenden
|
||||
|
||||
|
|
@ -63,61 +72,79 @@ Wenn Sie Teil-Aktualisierungen entgegennehmen, ist der `exclude_unset`-Parameter
|
|||
|
||||
Wie in `item.model_dump(exclude_unset=True)`.
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
|
||||
/// info
|
||||
|
||||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
|
||||
|
||||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
|
||||
///
|
||||
|
||||
Das wird ein `dict` erstellen, mit nur den Daten, die gesetzt wurden als das `item`-Modell erstellt wurde, Defaultwerte ausgeschlossen.
|
||||
|
||||
Sie können das verwenden, um ein `dict` zu erstellen, das nur die (im Request) gesendeten Daten enthält, ohne Defaultwerte:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="32"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="32"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="34"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="34"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="34"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="34"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Pydantics `update`-Parameter verwenden
|
||||
|
||||
Jetzt können Sie eine Kopie des existierenden Modells mittels `.model_copy()` erstellen, wobei Sie dem `update`-Parameter ein `dict` mit den zu ändernden Daten übergeben.
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_copy()` umbenannt.
|
||||
/// info
|
||||
|
||||
Die Beispiele hier verwenden `.copy()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_copy()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
In Pydantic v1 hieß diese Methode `.copy()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_copy()` umbenannt.
|
||||
|
||||
Die Beispiele hier verwenden `.copy()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_copy()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
|
||||
///
|
||||
|
||||
Wie in `stored_item_model.model_copy(update=update_data)`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="33"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="33"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Rekapitulation zum teilweisen Ersetzen
|
||||
|
||||
|
|
@ -134,32 +161,44 @@ Zusammengefasst, um Teil-Ersetzungen vorzunehmen:
|
|||
* Speichern Sie die Daten in Ihrer Datenbank.
|
||||
* Geben Sie das aktualisierte Modell zurück.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="28-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="28-35"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="30-37"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="30-37"
|
||||
{!> ../../../docs_src/body_updates/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="30-37"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können tatsächlich die gleiche Technik mit einer HTTP `PUT` Operation verwenden.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
Aber dieses Beispiel verwendet `PATCH`, da dieses für solche Anwendungsfälle geschaffen wurde.
|
||||
```Python hl_lines="30-37"
|
||||
{!> ../../../docs_src/body_updates/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass das hereinkommende Modell immer noch validiert wird.
|
||||
////
|
||||
|
||||
Wenn Sie also Teil-Aktualisierungen empfangen wollen, die alle Attribute auslassen können, müssen Sie ein Modell haben, dessen Attribute alle als optional gekennzeichnet sind (mit Defaultwerten oder `None`).
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um zu unterscheiden zwischen Modellen für **Aktualisierungen**, mit lauter optionalen Werten, und solchen für die **Erzeugung**, mit benötigten Werten, können Sie die Techniken verwenden, die in [Extramodelle](extra-models.md){.internal-link target=_blank} beschrieben wurden.
|
||||
Sie können tatsächlich die gleiche Technik mit einer HTTP `PUT` Operation verwenden.
|
||||
|
||||
Aber dieses Beispiel verwendet `PATCH`, da dieses für solche Anwendungsfälle geschaffen wurde.
|
||||
|
||||
///
|
||||
|
||||
/// note | "Hinweis"
|
||||
|
||||
Beachten Sie, dass das hereinkommende Modell immer noch validiert wird.
|
||||
|
||||
Wenn Sie also Teil-Aktualisierungen empfangen wollen, die alle Attribute auslassen können, müssen Sie ein Modell haben, dessen Attribute alle als optional gekennzeichnet sind (mit Defaultwerten oder `None`).
|
||||
|
||||
Um zu unterscheiden zwischen Modellen für **Aktualisierungen**, mit lauter optionalen Werten, und solchen für die **Erzeugung**, mit benötigten Werten, können Sie die Techniken verwenden, die in [Extramodelle](extra-models.md){.internal-link target=_blank} beschrieben wurden.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -8,28 +8,35 @@ Ihre API sendet fast immer einen **Response**body. Aber Clients senden nicht unb
|
|||
|
||||
Um einen **Request**body zu deklarieren, verwenden Sie <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>-Modelle mit allen deren Fähigkeiten und Vorzügen.
|
||||
|
||||
!!! info
|
||||
Um Daten zu versenden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden.
|
||||
/// info
|
||||
|
||||
Senden Sie einen Body mit einem `GET`-Request, dann führt das laut Spezifikation zu undefiniertem Verhalten. Trotzdem wird es von FastAPI unterstützt, für sehr komplexe/extreme Anwendungsfälle.
|
||||
Um Daten zu versenden, sollten Sie eines von: `POST` (meistverwendet), `PUT`, `DELETE` oder `PATCH` verwenden.
|
||||
|
||||
Da aber davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body auch nicht an, wenn `GET` verwendet wird. Dazwischengeschaltete Proxys unterstützen es möglicherweise auch nicht.
|
||||
Senden Sie einen Body mit einem `GET`-Request, dann führt das laut Spezifikation zu undefiniertem Verhalten. Trotzdem wird es von FastAPI unterstützt, für sehr komplexe/extreme Anwendungsfälle.
|
||||
|
||||
Da aber davon abgeraten wird, zeigt die interaktive Dokumentation mit Swagger-Benutzeroberfläche die Dokumentation für den Body auch nicht an, wenn `GET` verwendet wird. Dazwischengeschaltete Proxys unterstützen es möglicherweise auch nicht.
|
||||
|
||||
///
|
||||
|
||||
## Importieren Sie Pydantics `BaseModel`
|
||||
|
||||
Zuerst müssen Sie `BaseModel` von `pydantic` importieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="2"
|
||||
{!> ../../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="2"
|
||||
{!> ../../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="4"
|
||||
{!> ../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Erstellen Sie Ihr Datenmodell
|
||||
|
||||
|
|
@ -37,17 +44,21 @@ Dann deklarieren Sie Ihr Datenmodell als eine Klasse, die von `BaseModel` erbt.
|
|||
|
||||
Verwenden Sie Standard-Python-Typen für die Klassenattribute:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="5-9"
|
||||
{!> ../../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="5-9"
|
||||
{!> ../../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="7-11"
|
||||
{!> ../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="7-11"
|
||||
{!> ../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Wie auch bei Query-Parametern gilt, wenn ein Modellattribut einen Defaultwert hat, ist das Attribut nicht erforderlich. Ansonsten ist es erforderlich. Verwenden Sie `None`, um es als optional zu kennzeichnen.
|
||||
|
||||
|
|
@ -75,17 +86,21 @@ Da `description` und `tax` optional sind (mit `None` als Defaultwert), wäre fol
|
|||
|
||||
Um es zu Ihrer *Pfadoperation* hinzuzufügen, deklarieren Sie es auf die gleiche Weise, wie Sie Pfad- und Query-Parameter deklariert haben:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/body/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... und deklarieren Sie seinen Typ als das Modell, welches Sie erstellt haben, `Item`.
|
||||
|
||||
|
|
@ -134,32 +149,39 @@ Aber Sie bekommen die gleiche Editor-Unterstützung in <a href="https://www.jetb
|
|||
|
||||
<img src="/img/tutorial/body/image05.png">
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> als Ihren Editor verwenden, probieren Sie das <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a> aus.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit:
|
||||
Wenn Sie <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> als Ihren Editor verwenden, probieren Sie das <a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a> aus.
|
||||
|
||||
* Code-Vervollständigung
|
||||
* Typüberprüfungen
|
||||
* Refaktorisierung
|
||||
* Suchen
|
||||
* Inspektionen
|
||||
Es verbessert die Editor-Unterstützung für Pydantic-Modelle, mit:
|
||||
|
||||
* Code-Vervollständigung
|
||||
* Typüberprüfungen
|
||||
* Refaktorisierung
|
||||
* Suchen
|
||||
* Inspektionen
|
||||
|
||||
///
|
||||
|
||||
## Das Modell verwenden
|
||||
|
||||
Innerhalb der Funktion können Sie alle Attribute des Modells direkt verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/body/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/body/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/body/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/body/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Requestbody- + Pfad-Parameter
|
||||
|
||||
|
|
@ -167,17 +189,21 @@ Sie können Pfad- und Requestbody-Parameter gleichzeitig deklarieren.
|
|||
|
||||
**FastAPI** erkennt, dass Funktionsparameter, die mit Pfad-Parametern übereinstimmen, **vom Pfad genommen** werden sollen, und dass Funktionsparameter, welche Pydantic-Modelle sind, **vom Requestbody genommen** werden sollen.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="15-16"
|
||||
{!> ../../../docs_src/body/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="15-16"
|
||||
{!> ../../../docs_src/body/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!> ../../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!> ../../../docs_src/body/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Requestbody- + Pfad- + Query-Parameter
|
||||
|
||||
|
|
@ -185,17 +211,21 @@ Sie können auch zur gleichen Zeit **Body-**, **Pfad-** und **Query-Parameter**
|
|||
|
||||
**FastAPI** wird jeden Parameter korrekt erkennen und die Daten vom richtigen Ort holen.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/body/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/body/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body/tutorial004.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/body/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Die Funktionsparameter werden wie folgt erkannt:
|
||||
|
||||
|
|
@ -203,10 +233,13 @@ Die Funktionsparameter werden wie folgt erkannt:
|
|||
* Wenn der Parameter ein **einfacher Typ** ist (wie `int`, `float`, `str`, `bool`, usw.), wird er als **Query**-Parameter interpretiert.
|
||||
* Wenn der Parameter vom Typ eines **Pydantic-Modells** ist, wird er als Request**body** interpretiert.
|
||||
|
||||
!!! note "Hinweis"
|
||||
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, wegen des definierten Defaultwertes `= None`
|
||||
/// note | "Hinweis"
|
||||
|
||||
Das `Union` in `Union[str, None]` wird von FastAPI nicht verwendet, aber es erlaubt Ihrem Editor, Sie besser zu unterstützen und Fehler zu erkennen.
|
||||
FastAPI weiß, dass der Wert von `q` nicht erforderlich ist, wegen des definierten Defaultwertes `= None`
|
||||
|
||||
Das `Union` in `Union[str, None]` wird von FastAPI nicht verwendet, aber es erlaubt Ihrem Editor, Sie besser zu unterstützen und Fehler zu erkennen.
|
||||
|
||||
///
|
||||
|
||||
## Ohne Pydantic
|
||||
|
||||
|
|
|
|||
|
|
@ -6,41 +6,57 @@ So wie `Query`- und `Path`-Parameter können Sie auch <abbr title='Cookie –
|
|||
|
||||
Importieren Sie zuerst `Cookie`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `Cookie`-Parameter deklarieren
|
||||
|
||||
|
|
@ -48,49 +64,71 @@ Dann deklarieren Sie Ihre Cookie-Parameter, auf die gleiche Weise, wie Sie auch
|
|||
|
||||
Der erste Wert ist der Typ. Sie können `Cookie` die gehabten Extra Validierungs- und Beschreibungsparameter hinzufügen. Danach können Sie einen Defaultwert vergeben:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! note "Technische Details"
|
||||
`Cookie` ist eine Schwesterklasse von `Path` und `Query`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
|
||||
///
|
||||
|
||||
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/cookie_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// note | "Technische Details"
|
||||
|
||||
`Cookie` ist eine Schwesterklasse von `Path` und `Query`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
|
||||
|
||||
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Cookie` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
Um Cookies zu deklarieren, müssen Sie `Cookie` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
|
||||
|
||||
///
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -6,41 +6,57 @@ Bevor wir tiefer in das **Dependency Injection** System eintauchen, lassen Sie u
|
|||
|
||||
Im vorherigen Beispiel haben wir ein `dict` von unserer Abhängigkeit („Dependable“) zurückgegeben:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Aber dann haben wir ein `dict` im Parameter `commons` der *Pfadoperation-Funktion*.
|
||||
|
||||
|
|
@ -103,117 +119,165 @@ Das gilt auch für Callables ohne Parameter. So wie es auch für *Pfadoperation-
|
|||
|
||||
Dann können wir das „Dependable“ `common_parameters` der Abhängigkeit von oben in die Klasse `CommonQueryParams` ändern:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="12-16"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="12-16"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9-13"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9-13"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11-15"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Achten Sie auf die Methode `__init__`, die zum Erstellen der Instanz der Klasse verwendet wird:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... sie hat die gleichen Parameter wie unsere vorherige `common_parameters`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Diese Parameter werden von **FastAPI** verwendet, um die Abhängigkeit „aufzulösen“.
|
||||
|
||||
|
|
@ -229,41 +293,57 @@ In beiden Fällen werden die Daten konvertiert, validiert, im OpenAPI-Schema dok
|
|||
|
||||
Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
**FastAPI** ruft die Klasse `CommonQueryParams` auf. Dadurch wird eine „Instanz“ dieser Klasse erstellt und die Instanz wird als Parameter `commons` an Ihre Funktion überreicht.
|
||||
|
||||
|
|
@ -271,20 +351,27 @@ Jetzt können Sie Ihre Abhängigkeit mithilfe dieser Klasse deklarieren.
|
|||
|
||||
Beachten Sie, wie wir `CommonQueryParams` im obigen Code zweimal schreiben:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das letzte `CommonQueryParams`, in:
|
||||
|
||||
|
|
@ -300,77 +387,107 @@ Aus diesem extrahiert FastAPI die deklarierten Parameter, und dieses ist es, was
|
|||
|
||||
In diesem Fall hat das erste `CommonQueryParams` in:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, ...
|
||||
```
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, ...
|
||||
```
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams ...
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams ...
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... keine besondere Bedeutung für **FastAPI**. FastAPI verwendet es nicht für die Datenkonvertierung, -validierung, usw. (da es dafür `Depends(CommonQueryParams)` verwendet).
|
||||
|
||||
Sie könnten tatsächlich einfach schreiben:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||
```
|
||||
```Python
|
||||
commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
```Python
|
||||
commons = Depends(CommonQueryParams)
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... wie in:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was als Parameter `commons` übergeben wird, und Ihnen dann bei der Codevervollständigung, Typprüfungen, usw. helfen kann:
|
||||
|
||||
|
|
@ -380,20 +497,27 @@ Es wird jedoch empfohlen, den Typ zu deklarieren, da Ihr Editor so weiß, was al
|
|||
|
||||
Aber Sie sehen, dass wir hier etwas Codeduplizierung haben, indem wir `CommonQueryParams` zweimal schreiben:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
**FastAPI** bietet eine Abkürzung für diese Fälle, wo die Abhängigkeit *speziell* eine Klasse ist, welche **FastAPI** aufruft, um eine Instanz der Klasse selbst zu erstellen.
|
||||
|
||||
|
|
@ -401,81 +525,114 @@ In diesem speziellen Fall können Sie Folgendes tun:
|
|||
|
||||
Anstatt zu schreiben:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... schreiben Sie:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends()]
|
||||
```
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends()]
|
||||
```
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends()
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends()
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Sie deklarieren die Abhängigkeit als Typ des Parameters und verwenden `Depends()` ohne Parameter, anstatt die vollständige Klasse *erneut* in `Depends(CommonQueryParams)` schreiben zu müssen.
|
||||
|
||||
Dasselbe Beispiel würde dann so aussehen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="20"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... und **FastAPI** wird wissen, was zu tun ist.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie das eher verwirrt, als Ihnen zu helfen, ignorieren Sie es, Sie *brauchen* es nicht.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Es ist nur eine Abkürzung. Es geht **FastAPI** darum, Ihnen dabei zu helfen, Codeverdoppelung zu minimieren.
|
||||
Wenn Sie das eher verwirrt, als Ihnen zu helfen, ignorieren Sie es, Sie *brauchen* es nicht.
|
||||
|
||||
Es ist nur eine Abkürzung. Es geht **FastAPI** darum, Ihnen dabei zu helfen, Codeverdoppelung zu minimieren.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -14,40 +14,55 @@ Der *Pfadoperation-Dekorator* erhält ein optionales Argument `dependencies`.
|
|||
|
||||
Es sollte eine `list`e von `Depends()` sein:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Diese Abhängigkeiten werden auf die gleiche Weise wie normale Abhängigkeiten ausgeführt/aufgelöst. Aber ihr Wert (falls sie einen zurückgeben) wird nicht an Ihre *Pfadoperation-Funktion* übergeben.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Einige Editoren prüfen, ob Funktionsparameter nicht verwendet werden, und zeigen das als Fehler an.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie `dependencies` im *Pfadoperation-Dekorator* verwenden, stellen Sie sicher, dass sie ausgeführt werden, während gleichzeitig Ihr Editor/Ihre Tools keine Fehlermeldungen ausgeben.
|
||||
Einige Editoren prüfen, ob Funktionsparameter nicht verwendet werden, und zeigen das als Fehler an.
|
||||
|
||||
Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die einen nicht verwendeten Parameter in Ihrem Code sehen und ihn für unnötig halten könnten.
|
||||
Wenn Sie `dependencies` im *Pfadoperation-Dekorator* verwenden, stellen Sie sicher, dass sie ausgeführt werden, während gleichzeitig Ihr Editor/Ihre Tools keine Fehlermeldungen ausgeben.
|
||||
|
||||
!!! info
|
||||
In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`.
|
||||
Damit wird auch vermieden, neue Entwickler möglicherweise zu verwirren, die einen nicht verwendeten Parameter in Ihrem Code sehen und ihn für unnötig halten könnten.
|
||||
|
||||
Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr Vorteile durch die Verwendung der integrierten [Sicherheits-Werkzeuge (siehe nächstes Kapitel)](../security/index.md){.internal-link target=_blank} erzielen.
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
In diesem Beispiel verwenden wir zwei erfundene benutzerdefinierte Header `X-Key` und `X-Token`.
|
||||
|
||||
Aber in realen Fällen würden Sie bei der Implementierung von Sicherheit mehr Vorteile durch die Verwendung der integrierten [Sicherheits-Werkzeuge (siehe nächstes Kapitel)](../security/index.md){.internal-link target=_blank} erzielen.
|
||||
|
||||
///
|
||||
|
||||
## Abhängigkeitsfehler und -Rückgabewerte
|
||||
|
||||
|
|
@ -57,51 +72,69 @@ Sie können dieselben Abhängigkeits-*Funktionen* verwenden, die Sie normalerwei
|
|||
|
||||
Sie können Anforderungen für einen Request (wie Header) oder andere Unterabhängigkeiten deklarieren:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="7 12"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
```Python hl_lines="7 12"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="6 11"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Exceptions auslösen
|
||||
|
||||
Die Abhängigkeiten können Exceptions `raise`n, genau wie normale Abhängigkeiten:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
```Python hl_lines="9 14"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Rückgabewerte
|
||||
|
||||
|
|
@ -109,26 +142,35 @@ Und sie können Werte zurückgeben oder nicht, die Werte werden nicht verwendet.
|
|||
|
||||
Sie können also eine normale Abhängigkeit (die einen Wert zurückgibt), die Sie bereits an anderer Stelle verwenden, wiederverwenden, und auch wenn der Wert nicht verwendet wird, wird die Abhängigkeit ausgeführt:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/dependencies/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9 14"
|
||||
{!> ../../../docs_src/dependencies/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Abhängigkeiten für eine Gruppe von *Pfadoperationen*
|
||||
|
||||
|
|
|
|||
|
|
@ -4,18 +4,24 @@ FastAPI unterstützt Abhängigkeiten, die nach Abschluss einige <abbr title="Man
|
|||
|
||||
Verwenden Sie dazu `yield` statt `return` und schreiben Sie die zusätzlichen Schritte / den zusätzlichen Code danach.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Stellen Sie sicher, dass Sie `yield` nur einmal pro Abhängigkeit verwenden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! note "Technische Details"
|
||||
Jede Funktion, die dekoriert werden kann mit:
|
||||
Stellen Sie sicher, dass Sie `yield` nur einmal pro Abhängigkeit verwenden.
|
||||
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
|
||||
///
|
||||
|
||||
kann auch als gültige **FastAPI**-Abhängigkeit verwendet werden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern.
|
||||
Jede Funktion, die dekoriert werden kann mit:
|
||||
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
|
||||
|
||||
kann auch als gültige **FastAPI**-Abhängigkeit verwendet werden.
|
||||
|
||||
Tatsächlich verwendet FastAPI diese beiden Dekoratoren intern.
|
||||
|
||||
///
|
||||
|
||||
## Eine Datenbank-Abhängigkeit mit `yield`.
|
||||
|
||||
|
|
@ -39,10 +45,13 @@ Der auf die `yield`-Anweisung folgende Code wird ausgeführt, nachdem die Respon
|
|||
{!../../../docs_src/dependencies/tutorial007.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können `async`hrone oder reguläre Funktionen verwenden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
**FastAPI** wird bei jeder das Richtige tun, so wie auch bei normalen Abhängigkeiten.
|
||||
Sie können `async`hrone oder reguläre Funktionen verwenden.
|
||||
|
||||
**FastAPI** wird bei jeder das Richtige tun, so wie auch bei normalen Abhängigkeiten.
|
||||
|
||||
///
|
||||
|
||||
## Eine Abhängigkeit mit `yield` und `try`.
|
||||
|
||||
|
|
@ -66,26 +75,35 @@ Sie können Unterabhängigkeiten und „Bäume“ von Unterabhängigkeiten belie
|
|||
|
||||
Beispielsweise kann `dependency_c` von `dependency_b` und `dependency_b` von `dependency_a` abhängen:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="6 14 22"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="6 14 22"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="5 13 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="5 13 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="4 12 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial008.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4 12 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial008.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Und alle können `yield` verwenden.
|
||||
|
||||
|
|
@ -93,26 +111,35 @@ In diesem Fall benötigt `dependency_c` zum Ausführen seines Exit-Codes, dass d
|
|||
|
||||
Und wiederum benötigt `dependency_b` den Wert von `dependency_a` (hier `dep_a` genannt) für seinen Exit-Code.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="18-19 26-27"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="18-19 26-27"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17-18 25-26"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="17-18 25-26"
|
||||
{!> ../../../docs_src/dependencies/tutorial008_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="16-17 24-25"
|
||||
{!> ../../../docs_src/dependencies/tutorial008.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="16-17 24-25"
|
||||
{!> ../../../docs_src/dependencies/tutorial008.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Auf die gleiche Weise könnten Sie einige Abhängigkeiten mit `yield` und einige andere Abhängigkeiten mit `return` haben, und alle können beliebig voneinander abhängen.
|
||||
|
||||
|
|
@ -122,10 +149,13 @@ Sie können beliebige Kombinationen von Abhängigkeiten haben.
|
|||
|
||||
**FastAPI** stellt sicher, dass alles in der richtigen Reihenfolge ausgeführt wird.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Dieses funktioniert dank Pythons <a href="https://docs.python.org/3/library/contextlib.html" class="external-link" target="_blank">Kontextmanager</a>.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** verwendet sie intern, um das zu erreichen.
|
||||
Dieses funktioniert dank Pythons <a href="https://docs.python.org/3/library/contextlib.html" class="external-link" target="_blank">Kontextmanager</a>.
|
||||
|
||||
**FastAPI** verwendet sie intern, um das zu erreichen.
|
||||
|
||||
///
|
||||
|
||||
## Abhängigkeiten mit `yield` und `HTTPException`.
|
||||
|
||||
|
|
@ -133,32 +163,43 @@ Sie haben gesehen, dass Ihre Abhängigkeiten `yield` verwenden können und `try`
|
|||
|
||||
Auf die gleiche Weise könnten Sie im Exit-Code nach dem `yield` eine `HTTPException` oder ähnliches auslösen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
/// tip | "Tipp"
|
||||
|
||||
Dies ist eine etwas fortgeschrittene Technik, die Sie in den meisten Fällen nicht wirklich benötigen, da Sie Exceptions (einschließlich `HTTPException`) innerhalb des restlichen Anwendungscodes auslösen können, beispielsweise in der *Pfadoperation-Funktion*.
|
||||
Dies ist eine etwas fortgeschrittene Technik, die Sie in den meisten Fällen nicht wirklich benötigen, da Sie Exceptions (einschließlich `HTTPException`) innerhalb des restlichen Anwendungscodes auslösen können, beispielsweise in der *Pfadoperation-Funktion*.
|
||||
|
||||
Aber es ist für Sie da, wenn Sie es brauchen. 🤓
|
||||
Aber es ist für Sie da, wenn Sie es brauchen. 🤓
|
||||
|
||||
=== "Python 3.9+"
|
||||
///
|
||||
|
||||
```Python hl_lines="18-22 31"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="18-22 31"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17-21 30"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="17-21 30"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="16-20 29"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="16-20 29"
|
||||
{!> ../../../docs_src/dependencies/tutorial008b.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Eine Alternative zum Abfangen von Exceptions (und möglicherweise auch zum Auslösen einer weiteren `HTTPException`) besteht darin, einen [benutzerdefinierten Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} zu erstellen.
|
||||
|
||||
|
|
@ -201,22 +242,31 @@ participant tasks as Hintergrundtasks
|
|||
end
|
||||
```
|
||||
|
||||
!!! info
|
||||
Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein.
|
||||
/// info
|
||||
|
||||
Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesendet werden.
|
||||
Es wird nur **eine Response** an den Client gesendet. Es kann eine Error-Response oder die Response der *Pfadoperation* sein.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Obiges Diagramm verwendet `HTTPException`, aber Sie können auch jede andere Exception auslösen, die Sie in einer Abhängigkeit mit `yield` abfangen, oder mit einem [benutzerdefinierten Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} erstellt haben.
|
||||
Nachdem eine dieser Responses gesendet wurde, kann keine weitere Response gesendet werden.
|
||||
|
||||
Wenn Sie eine Exception auslösen, wird diese mit yield an die Abhängigkeiten übergeben, einschließlich `HTTPException`, und dann **erneut** an die Exceptionhandler. Wenn es für diese Exception keinen Exceptionhandler gibt, wird sie von der internen Default-`ServerErrorMiddleware` gehandhabt, was einen HTTP-Statuscode 500 zurückgibt, um den Client darüber zu informieren, dass ein Fehler auf dem Server aufgetreten ist.
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Obiges Diagramm verwendet `HTTPException`, aber Sie können auch jede andere Exception auslösen, die Sie in einer Abhängigkeit mit `yield` abfangen, oder mit einem [benutzerdefinierten Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} erstellt haben.
|
||||
|
||||
Wenn Sie eine Exception auslösen, wird diese mit yield an die Abhängigkeiten übergeben, einschließlich `HTTPException`, und dann **erneut** an die Exceptionhandler. Wenn es für diese Exception keinen Exceptionhandler gibt, wird sie von der internen Default-`ServerErrorMiddleware` gehandhabt, was einen HTTP-Statuscode 500 zurückgibt, um den Client darüber zu informieren, dass ein Fehler auf dem Server aufgetreten ist.
|
||||
|
||||
///
|
||||
|
||||
## Abhängigkeiten mit `yield`, `HTTPException` und Hintergrundtasks
|
||||
|
||||
!!! warning "Achtung"
|
||||
Sie benötigen diese technischen Details höchstwahrscheinlich nicht, Sie können diesen Abschnitt überspringen und weiter unten fortfahren.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Diese Details sind vor allem dann nützlich, wenn Sie eine Version von FastAPI vor 0.106.0 verwendet haben und Ressourcen aus Abhängigkeiten mit `yield` in Hintergrundtasks verwendet haben.
|
||||
Sie benötigen diese technischen Details höchstwahrscheinlich nicht, Sie können diesen Abschnitt überspringen und weiter unten fortfahren.
|
||||
|
||||
Diese Details sind vor allem dann nützlich, wenn Sie eine Version von FastAPI vor 0.106.0 verwendet haben und Ressourcen aus Abhängigkeiten mit `yield` in Hintergrundtasks verwendet haben.
|
||||
|
||||
///
|
||||
|
||||
Vor FastAPI 0.106.0 war das Auslösen von Exceptions nach `yield` nicht möglich, der Exit-Code in Abhängigkeiten mit `yield` wurde ausgeführt, *nachdem* die Response gesendet wurde, die [Exceptionhandler](../handling-errors.md#benutzerdefinierte-exceptionhandler-definieren){.internal-link target=_blank} wären also bereits ausgeführt worden.
|
||||
|
||||
|
|
@ -224,11 +274,13 @@ Dies wurde hauptsächlich so konzipiert, damit die gleichen Objekte, die durch A
|
|||
|
||||
Da dies jedoch bedeuten würde, darauf zu warten, dass die Response durch das Netzwerk reist, während eine Ressource unnötigerweise in einer Abhängigkeit mit yield gehalten wird (z. B. eine Datenbankverbindung), wurde dies in FastAPI 0.106.0 geändert.
|
||||
|
||||
!!! tip "Tipp"
|
||||
/// tip | "Tipp"
|
||||
|
||||
Darüber hinaus handelt es sich bei einem Hintergrundtask normalerweise um einen unabhängigen Satz von Logik, der separat behandelt werden sollte, mit eigenen Ressourcen (z. B. einer eigenen Datenbankverbindung).
|
||||
Darüber hinaus handelt es sich bei einem Hintergrundtask normalerweise um einen unabhängigen Satz von Logik, der separat behandelt werden sollte, mit eigenen Ressourcen (z. B. einer eigenen Datenbankverbindung).
|
||||
|
||||
Auf diese Weise erhalten Sie wahrscheinlich saubereren Code.
|
||||
Auf diese Weise erhalten Sie wahrscheinlich saubereren Code.
|
||||
|
||||
///
|
||||
|
||||
Wenn Sie sich früher auf dieses Verhalten verlassen haben, sollten Sie jetzt die Ressourcen für Hintergrundtasks innerhalb des Hintergrundtasks selbst erstellen und intern nur Daten verwenden, die nicht von den Ressourcen von Abhängigkeiten mit `yield` abhängen.
|
||||
|
||||
|
|
@ -256,10 +308,13 @@ Wenn Sie eine Abhängigkeit mit `yield` erstellen, erstellt **FastAPI** dafür i
|
|||
|
||||
### Kontextmanager in Abhängigkeiten mit `yield` verwenden
|
||||
|
||||
!!! warning "Achtung"
|
||||
Dies ist mehr oder weniger eine „fortgeschrittene“ Idee.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorerst überspringen.
|
||||
Dies ist mehr oder weniger eine „fortgeschrittene“ Idee.
|
||||
|
||||
Wenn Sie gerade erst mit **FastAPI** beginnen, möchten Sie das vielleicht vorerst überspringen.
|
||||
|
||||
///
|
||||
|
||||
In Python können Sie Kontextmanager erstellen, indem Sie <a href="https://docs.python.org/3/reference/datamodel.html#context-managers" class="external-link" target="_blank">eine Klasse mit zwei Methoden erzeugen: `__enter__()` und `__exit__()`</a>.
|
||||
|
||||
|
|
@ -269,16 +324,19 @@ Sie können solche auch innerhalb von **FastAPI**-Abhängigkeiten mit `yield` ve
|
|||
{!../../../docs_src/dependencies/tutorial010.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Andere Möglichkeiten, einen Kontextmanager zu erstellen, sind:
|
||||
/// tip | "Tipp"
|
||||
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
|
||||
Andere Möglichkeiten, einen Kontextmanager zu erstellen, sind:
|
||||
|
||||
Verwenden Sie diese, um eine Funktion zu dekorieren, die ein einziges `yield` hat.
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager" class="external-link" target="_blank">`@contextlib.contextmanager`</a> oder
|
||||
* <a href="https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager" class="external-link" target="_blank">`@contextlib.asynccontextmanager`</a>
|
||||
|
||||
Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet.
|
||||
Verwenden Sie diese, um eine Funktion zu dekorieren, die ein einziges `yield` hat.
|
||||
|
||||
Aber Sie müssen die Dekoratoren nicht für FastAPI-Abhängigkeiten verwenden (und das sollten Sie auch nicht).
|
||||
Das ist es auch, was **FastAPI** intern für Abhängigkeiten mit `yield` verwendet.
|
||||
|
||||
FastAPI erledigt das intern für Sie.
|
||||
Aber Sie müssen die Dekoratoren nicht für FastAPI-Abhängigkeiten verwenden (und das sollten Sie auch nicht).
|
||||
|
||||
FastAPI erledigt das intern für Sie.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -6,26 +6,35 @@ Bei einigen Anwendungstypen möchten Sie möglicherweise Abhängigkeiten zur ges
|
|||
|
||||
In diesem Fall werden sie auf alle *Pfadoperationen* in der Anwendung angewendet:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial012_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial012_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/dependencies/tutorial012_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/dependencies/tutorial012.py!}
|
||||
```
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="15"
|
||||
{!> ../../../docs_src/dependencies/tutorial012.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Und alle Ideen aus dem Abschnitt über das [Hinzufügen von `dependencies` zu den *Pfadoperation-Dekoratoren*](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} gelten weiterhin, aber in diesem Fall für alle *Pfadoperationen* in der Anwendung.
|
||||
|
||||
|
|
|
|||
|
|
@ -30,41 +30,57 @@ Aber so können wir uns besser auf die Funktionsweise des **Dependency Injection
|
|||
Konzentrieren wir uns zunächst auf die Abhängigkeit - die Dependency.
|
||||
|
||||
Es handelt sich einfach um eine Funktion, die die gleichen Parameter entgegennimmt wie eine *Pfadoperation-Funktion*:
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8-11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="8-11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="9-12"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="8-11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8-11"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das war's schon.
|
||||
|
||||
|
|
@ -84,90 +100,125 @@ In diesem Fall erwartet diese Abhängigkeit:
|
|||
|
||||
Und dann wird einfach ein `dict` zurückgegeben, welches diese Werte enthält.
|
||||
|
||||
!!! info
|
||||
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
|
||||
/// info
|
||||
|
||||
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
|
||||
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
|
||||
|
||||
Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
|
||||
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
|
||||
|
||||
Bitte [aktualisieren Sie FastAPI](../../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
|
||||
|
||||
///
|
||||
|
||||
### `Depends` importieren
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Deklarieren der Abhängigkeit im <abbr title="Das Abhängige, der Verwender der Abhängigkeit">„Dependant“</abbr>
|
||||
|
||||
So wie auch `Body`, `Query`, usw., verwenden Sie `Depends` mit den Parametern Ihrer *Pfadoperation-Funktion*:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="13 18"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="13 18"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="15 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="15 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="16 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="16 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="15 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="15 20"
|
||||
{!> ../../../docs_src/dependencies/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Obwohl Sie `Depends` in den Parametern Ihrer Funktion genauso verwenden wie `Body`, `Query`, usw., funktioniert `Depends` etwas anders.
|
||||
|
||||
|
|
@ -179,8 +230,11 @@ Sie **rufen diese nicht direkt auf** (fügen Sie am Ende keine Klammern hinzu),
|
|||
|
||||
Und diese Funktion akzeptiert Parameter auf die gleiche Weise wie *Pfadoperation-Funktionen*.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen, Sie als Abhängigkeiten verwenden können.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Im nächsten Kapitel erfahren Sie, welche anderen „Dinge“, außer Funktionen, Sie als Abhängigkeiten verwenden können.
|
||||
|
||||
///
|
||||
|
||||
Immer wenn ein neuer Request eintrifft, kümmert sich **FastAPI** darum:
|
||||
|
||||
|
|
@ -201,10 +255,13 @@ common_parameters --> read_users
|
|||
|
||||
Auf diese Weise schreiben Sie gemeinsam genutzten Code nur einmal, und **FastAPI** kümmert sich darum, ihn für Ihre *Pfadoperationen* aufzurufen.
|
||||
|
||||
!!! check
|
||||
Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich.
|
||||
/// check
|
||||
|
||||
Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erledigt wird.
|
||||
Beachten Sie, dass Sie keine spezielle Klasse erstellen und diese irgendwo an **FastAPI** übergeben müssen, um sie zu „registrieren“ oder so ähnlich.
|
||||
|
||||
Sie übergeben es einfach an `Depends` und **FastAPI** weiß, wie der Rest erledigt wird.
|
||||
|
||||
///
|
||||
|
||||
## `Annotated`-Abhängigkeiten wiederverwenden
|
||||
|
||||
|
|
@ -218,28 +275,37 @@ commons: Annotated[dict, Depends(common_parameters)]
|
|||
|
||||
Da wir jedoch `Annotated` verwenden, können wir diesen `Annotated`-Wert in einer Variablen speichern und an mehreren Stellen verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="12 16 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="12 16 21"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="14 18 23"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="14 18 23"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="15 19 24"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Das ist schlicht Standard-Python, es wird als „Typalias“ bezeichnet und ist eigentlich nicht **FastAPI**-spezifisch.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
Da **FastAPI** jedoch auf Standard-Python, einschließlich `Annotated`, basiert, können Sie diesen Trick in Ihrem Code verwenden. 😎
|
||||
```Python hl_lines="15 19 24"
|
||||
{!> ../../../docs_src/dependencies/tutorial001_02_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Das ist schlicht Standard-Python, es wird als „Typalias“ bezeichnet und ist eigentlich nicht **FastAPI**-spezifisch.
|
||||
|
||||
Da **FastAPI** jedoch auf Standard-Python, einschließlich `Annotated`, basiert, können Sie diesen Trick in Ihrem Code verwenden. 😎
|
||||
|
||||
///
|
||||
|
||||
Die Abhängigkeiten funktionieren weiterhin wie erwartet, und das **Beste daran** ist, dass die **Typinformationen erhalten bleiben**, was bedeutet, dass Ihr Editor Ihnen weiterhin **automatische Vervollständigung**, **Inline-Fehler**, usw. bieten kann. Das Gleiche gilt für andere Tools wie `mypy`.
|
||||
|
||||
|
|
@ -255,8 +321,11 @@ Und Sie können Abhängigkeiten mit `async def` innerhalb normaler `def`-*Pfadop
|
|||
|
||||
Es spielt keine Rolle. **FastAPI** weiß, was zu tun ist.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-eile){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Wenn Ihnen das nichts sagt, lesen Sie den [Async: *„In Eile?“*](../../async.md#in-eile){.internal-link target=_blank}-Abschnitt über `async` und `await` in der Dokumentation.
|
||||
|
||||
///
|
||||
|
||||
## Integriert in OpenAPI
|
||||
|
||||
|
|
|
|||
|
|
@ -10,41 +10,57 @@ Diese können so **tief** verschachtelt sein, wie nötig.
|
|||
|
||||
Sie könnten eine erste Abhängigkeit („Dependable“) wie folgt erstellen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9-10"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10 nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="9-10"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
//// tab | Python 3.10 nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="6-7"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8-9"
|
||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Diese deklariert einen optionalen Abfrageparameter `q` vom Typ `str` und gibt ihn dann einfach zurück.
|
||||
|
||||
|
|
@ -54,41 +70,57 @@ Das ist recht einfach (nicht sehr nützlich), hilft uns aber dabei, uns auf die
|
|||
|
||||
Dann können Sie eine weitere Abhängigkeitsfunktion (ein „Dependable“) erstellen, die gleichzeitig eine eigene Abhängigkeit deklariert (also auch ein „Dependant“ ist):
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10 nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
//// tab | Python 3.10 nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Betrachten wir die deklarierten Parameter:
|
||||
|
||||
|
|
@ -101,46 +133,65 @@ Betrachten wir die deklarierten Parameter:
|
|||
|
||||
Diese Abhängigkeit verwenden wir nun wie folgt:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10 nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
//// tab | Python 3.10 nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! info
|
||||
Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`.
|
||||
///
|
||||
|
||||
Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird.
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/dependencies/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/dependencies/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
Beachten Sie, dass wir in der *Pfadoperation-Funktion* nur eine einzige Abhängigkeit deklarieren, den `query_or_cookie_extractor`.
|
||||
|
||||
Aber **FastAPI** wird wissen, dass es zuerst `query_extractor` auflösen muss, um dessen Resultat `query_or_cookie_extractor` zu übergeben, wenn dieses aufgerufen wird.
|
||||
|
||||
///
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
|
|
@ -161,22 +212,29 @@ Und es speichert den zurückgegebenen Wert in einem <abbr title="Mechanismus, de
|
|||
|
||||
In einem fortgeschrittenen Szenario, bei dem Sie wissen, dass die Abhängigkeit bei jedem Schritt (möglicherweise mehrmals) in derselben Anfrage aufgerufen werden muss, anstatt den zwischengespeicherten Wert zu verwenden, können Sie den Parameter `use_cache=False` festlegen, wenn Sie `Depends` verwenden:
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
||||
return {"fresh_value": fresh_value}
|
||||
```
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
||||
return {"fresh_value": fresh_value}
|
||||
```
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
////
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
|
||||
return {"fresh_value": fresh_value}
|
||||
```
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
|
||||
return {"fresh_value": fresh_value}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
@ -186,9 +244,12 @@ Einfach Funktionen, die genauso aussehen wie *Pfadoperation-Funktionen*.
|
|||
|
||||
Dennoch ist es sehr mächtig und ermöglicht Ihnen die Deklaration beliebig tief verschachtelter Abhängigkeits-„Graphen“ (Bäume).
|
||||
|
||||
!!! tip "Tipp"
|
||||
All dies scheint angesichts dieser einfachen Beispiele möglicherweise nicht so nützlich zu sein.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Aber Sie werden in den Kapiteln über **Sicherheit** sehen, wie nützlich das ist.
|
||||
All dies scheint angesichts dieser einfachen Beispiele möglicherweise nicht so nützlich zu sein.
|
||||
|
||||
Und Sie werden auch sehen, wie viel Code Sie dadurch einsparen.
|
||||
Aber Sie werden in den Kapiteln über **Sicherheit** sehen, wie nützlich das ist.
|
||||
|
||||
Und Sie werden auch sehen, wie viel Code Sie dadurch einsparen.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -20,17 +20,21 @@ Sie können für diese Fälle `jsonable_encoder` verwenden.
|
|||
|
||||
Es nimmt ein Objekt entgegen, wie etwa ein Pydantic-Modell, und gibt eine JSON-kompatible Version zurück:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4 21"
|
||||
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="4 21"
|
||||
{!> ../../../docs_src/encoder/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="5 22"
|
||||
{!> ../../../docs_src/encoder/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="5 22"
|
||||
{!> ../../../docs_src/encoder/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Beispiel wird das Pydantic-Modell in ein `dict`, und das `datetime`-Objekt in ein `str` konvertiert.
|
||||
|
||||
|
|
@ -38,5 +42,8 @@ Das Resultat dieses Aufrufs ist etwas, das mit Pythons Standard-<a href="https:/
|
|||
|
||||
Es wird also kein großer `str` zurückgegeben, der die Daten im JSON-Format (als String) enthält. Es wird eine Python-Standarddatenstruktur (z. B. ein `dict`) zurückgegeben, mit Werten und Unterwerten, die alle mit JSON kompatibel sind.
|
||||
|
||||
!!! note "Hinweis"
|
||||
`jsonable_encoder` wird tatsächlich von **FastAPI** intern verwendet, um Daten zu konvertieren. Aber es ist in vielen anderen Szenarien hilfreich.
|
||||
/// note | "Hinweis"
|
||||
|
||||
`jsonable_encoder` wird tatsächlich von **FastAPI** intern verwendet, um Daten zu konvertieren. Aber es ist in vielen anderen Szenarien hilfreich.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -55,76 +55,108 @@ Hier sind einige der zusätzlichen Datentypen, die Sie verwenden können:
|
|||
|
||||
Hier ist ein Beispiel für eine *Pfadoperation* mit Parametern, die einige der oben genannten Typen verwenden.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1 3 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1 3 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 3 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="1 3 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1 3 13-17"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="1 3 13-17"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1 2 11-15"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip
|
||||
|
||||
```Python hl_lines="1 2 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 2 11-15"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 2 12-16"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Beachten Sie, dass die Parameter innerhalb der Funktion ihren natürlichen Datentyp haben und Sie beispielsweise normale Datumsmanipulationen durchführen können, wie zum Beispiel:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="19-20"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="19-20"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17-18"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/extra_data_types/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
|
|
|||
|
|
@ -8,31 +8,41 @@ Insbesondere Benutzermodelle, denn:
|
|||
* Das **herausgehende Modell** sollte kein Passwort haben.
|
||||
* Das **Datenbankmodell** sollte wahrscheinlich ein <abbr title='Ein aus scheinbar zufälligen Zeichen bestehender „Fingerabdruck“ eines Textes. Der Inhalt des Textes kann nicht eingesehen werden.'>gehashtes</abbr> Passwort haben.
|
||||
|
||||
!!! danger "Gefahr"
|
||||
Speichern Sie niemals das Klartext-Passwort eines Benutzers. Speichern Sie immer den „sicheren Hash“, den Sie verifizieren können.
|
||||
/// danger | "Gefahr"
|
||||
|
||||
Falls Ihnen das nichts sagt, in den [Sicherheits-Kapiteln](security/simple-oauth2.md#passwort-hashing){.internal-link target=_blank} werden Sie lernen, was ein „Passwort-Hash“ ist.
|
||||
Speichern Sie niemals das Klartext-Passwort eines Benutzers. Speichern Sie immer den „sicheren Hash“, den Sie verifizieren können.
|
||||
|
||||
Falls Ihnen das nichts sagt, in den [Sicherheits-Kapiteln](security/simple-oauth2.md#passwort-hashing){.internal-link target=_blank} werden Sie lernen, was ein „Passwort-Hash“ ist.
|
||||
|
||||
///
|
||||
|
||||
## Mehrere Modelle
|
||||
|
||||
Hier der generelle Weg, wie die Modelle mit ihren Passwort-Feldern aussehen könnten, und an welchen Orten sie verwendet werden würden.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
|
||||
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7 9 14 20 22 27-28 31-33 38-39"
|
||||
{!> ../../../docs_src/extra_models/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
|
||||
{!> ../../../docs_src/extra_models/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
|
||||
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
|
||||
{!> ../../../docs_src/extra_models/tutorial001.py!}
|
||||
```
|
||||
|
||||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
|
||||
|
||||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
|
||||
///
|
||||
|
||||
### Über `**user_in.dict()`
|
||||
|
||||
|
|
@ -144,8 +154,11 @@ UserInDB(
|
|||
)
|
||||
```
|
||||
|
||||
!!! warning "Achtung"
|
||||
Die Hilfsfunktionen `fake_password_hasher` und `fake_save_user` demonstrieren nur den möglichen Fluss der Daten und bieten natürlich keine echte Sicherheit.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Die Hilfsfunktionen `fake_password_hasher` und `fake_save_user` demonstrieren nur den möglichen Fluss der Daten und bieten natürlich keine echte Sicherheit.
|
||||
|
||||
///
|
||||
|
||||
## Verdopplung vermeiden
|
||||
|
||||
|
|
@ -163,17 +176,21 @@ Die ganze Datenkonvertierung, -validierung, -dokumentation, usw. wird immer noch
|
|||
|
||||
Auf diese Weise beschreiben wir nur noch die Unterschiede zwischen den Modellen (mit Klartext-`password`, mit `hashed_password`, und ohne Passwort):
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7 13-14 17-18 21-22"
|
||||
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7 13-14 17-18 21-22"
|
||||
{!> ../../../docs_src/extra_models/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9 15-16 19-20 23-24"
|
||||
{!> ../../../docs_src/extra_models/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9 15-16 19-20 23-24"
|
||||
{!> ../../../docs_src/extra_models/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `Union`, oder `anyOf`
|
||||
|
||||
|
|
@ -183,20 +200,27 @@ Das wird in OpenAPI mit `anyOf` angezeigt.
|
|||
|
||||
Um das zu tun, verwenden Sie Pythons Standard-Typhinweis <a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>:
|
||||
|
||||
!!! note "Hinweis"
|
||||
Listen Sie, wenn Sie eine <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a> definieren, denjenigen Typ zuerst, der am spezifischsten ist, gefolgt von den weniger spezifischen Typen. Im Beispiel oben, in `Union[PlaneItem, CarItem]` also den spezifischeren `PlaneItem` vor dem weniger spezifischen `CarItem`.
|
||||
/// note | "Hinweis"
|
||||
|
||||
=== "Python 3.10+"
|
||||
Listen Sie, wenn Sie eine <a href="https://pydantic-docs.helpmanual.io/usage/types/#unions" class="external-link" target="_blank">`Union`</a> definieren, denjenigen Typ zuerst, der am spezifischsten ist, gefolgt von den weniger spezifischen Typen. Im Beispiel oben, in `Union[PlaneItem, CarItem]` also den spezifischeren `PlaneItem` vor dem weniger spezifischen `CarItem`.
|
||||
|
||||
```Python hl_lines="1 14-15 18-20 33"
|
||||
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1 14-15 18-20 33"
|
||||
{!> ../../../docs_src/extra_models/tutorial003.py!}
|
||||
```
|
||||
```Python hl_lines="1 14-15 18-20 33"
|
||||
{!> ../../../docs_src/extra_models/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 14-15 18-20 33"
|
||||
{!> ../../../docs_src/extra_models/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### `Union` in Python 3.10
|
||||
|
||||
|
|
@ -218,17 +242,21 @@ Genauso können Sie eine Response deklarieren, die eine Liste von Objekten ist.
|
|||
|
||||
Verwenden Sie dafür Pythons Standard `typing.List` (oder nur `list` in Python 3.9 und darüber):
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
|
||||
```
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/extra_models/tutorial004_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 20"
|
||||
{!> ../../../docs_src/extra_models/tutorial004.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 20"
|
||||
{!> ../../../docs_src/extra_models/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Response mit beliebigem `dict`
|
||||
|
||||
|
|
@ -238,17 +266,21 @@ Das ist nützlich, wenn Sie die gültigen Feld-/Attribut-Namen von vorneherein n
|
|||
|
||||
In diesem Fall können Sie `typing.Dict` verwenden (oder nur `dict` in Python 3.9 und darüber):
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
|
||||
```
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/extra_models/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 8"
|
||||
{!> ../../../docs_src/extra_models/tutorial005.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="1 8"
|
||||
{!> ../../../docs_src/extra_models/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -24,12 +24,15 @@ $ uvicorn main:app --reload
|
|||
|
||||
</div>
|
||||
|
||||
!!! note "Hinweis"
|
||||
Der Befehl `uvicorn main:app` bezieht sich auf:
|
||||
/// note | "Hinweis"
|
||||
|
||||
* `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.
|
||||
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:
|
||||
|
||||
|
|
@ -136,10 +139,13 @@ Ebenfalls können Sie es verwenden, um automatisch Code für Clients zu generier
|
|||
|
||||
`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.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Sie können alle <a href="https://www.starlette.io/" class="external-link" target="_blank">Starlette</a>-Funktionalitäten auch mit `FastAPI` nutzen.
|
||||
`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“
|
||||
|
||||
|
|
@ -199,8 +205,11 @@ https://example.com/items/foo
|
|||
/items/foo
|
||||
```
|
||||
|
||||
!!! info
|
||||
Ein „Pfad“ wird häufig auch als „Endpunkt“ oder „Route“ bezeichnet.
|
||||
/// 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“.
|
||||
|
||||
|
|
@ -250,16 +259,19 @@ Das `@app.get("/")` sagt **FastAPI**, dass die Funktion direkt darunter für die
|
|||
* 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.
|
||||
/// info | "`@decorator` Information"
|
||||
|
||||
Sie platzieren ihn über einer Funktion. Wie ein hübscher, dekorativer Hut (daher kommt wohl der Begriff).
|
||||
Diese `@something`-Syntax wird in Python „Dekorator“ genannt.
|
||||
|
||||
Ein „Dekorator“ nimmt die darunter stehende Funktion und macht etwas damit.
|
||||
Sie platzieren ihn über einer Funktion. Wie ein hübscher, dekorativer Hut (daher kommt wohl der Begriff).
|
||||
|
||||
In unserem Fall teilt dieser Dekorator **FastAPI** mit, dass die folgende Funktion mit dem **Pfad** `/` und der **Operation** `get` zusammenhängt.
|
||||
Ein „Dekorator“ nimmt die darunter stehende Funktion und macht etwas damit.
|
||||
|
||||
Dies ist der „**Pfadoperation-Dekorator**“.
|
||||
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:
|
||||
|
||||
|
|
@ -274,14 +286,17 @@ Oder die exotischeren:
|
|||
* `@app.patch()`
|
||||
* `@app.trace()`
|
||||
|
||||
!!! tip "Tipp"
|
||||
Es steht Ihnen frei, jede Operation (HTTP-Methode) so zu verwenden, wie Sie es möchten.
|
||||
/// tip | "Tipp"
|
||||
|
||||
**FastAPI** erzwingt keine bestimmte Bedeutung.
|
||||
Es steht Ihnen frei, jede Operation (HTTP-Methode) so zu verwenden, wie Sie es möchten.
|
||||
|
||||
Die hier aufgeführten Informationen dienen als Leitfaden und sind nicht verbindlich.
|
||||
**FastAPI** erzwingt keine bestimmte Bedeutung.
|
||||
|
||||
Wenn Sie beispielsweise GraphQL verwenden, führen Sie normalerweise alle Aktionen nur mit „POST“-Operationen durch.
|
||||
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**
|
||||
|
||||
|
|
@ -309,8 +324,11 @@ Sie könnten sie auch als normale Funktion anstelle von `async def` definieren:
|
|||
{!../../../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}.
|
||||
/// 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
|
||||
|
||||
|
|
|
|||
|
|
@ -63,12 +63,15 @@ Aber wenn der Client `http://example.com/items/bar` anfragt (ein nicht-existiere
|
|||
}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der nach JSON konvertiert werden kann, nicht nur `str`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Zum Beispiel ein `dict`, eine `list`, usw.
|
||||
Wenn Sie eine `HTTPException` auslösen, können Sie dem Parameter `detail` jeden Wert übergeben, der nach JSON konvertiert werden kann, nicht nur `str`.
|
||||
|
||||
Das wird automatisch von **FastAPI** gehandhabt und der Wert nach JSON konvertiert.
|
||||
Zum Beispiel ein `dict`, eine `list`, usw.
|
||||
|
||||
Das wird automatisch von **FastAPI** gehandhabt und der Wert nach JSON konvertiert.
|
||||
|
||||
///
|
||||
|
||||
## Benutzerdefinierte Header hinzufügen
|
||||
|
||||
|
|
@ -106,10 +109,13 @@ Sie erhalten also einen sauberen Error mit einem Statuscode `418` und dem JSON-I
|
|||
{"message": "Oops! yolo did something. There goes a rainbow..."}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `Request`.
|
||||
Sie können auch `from starlette.requests import Request` und `from starlette.responses import JSONResponse` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette. Das Gleiche gilt für `Request`.
|
||||
|
||||
///
|
||||
|
||||
## Die Default-Exceptionhandler überschreiben
|
||||
|
||||
|
|
@ -160,8 +166,11 @@ path -> item_id
|
|||
|
||||
#### `RequestValidationError` vs. `ValidationError`
|
||||
|
||||
!!! warning "Achtung"
|
||||
Das folgende sind technische Details, die Sie überspringen können, wenn sie für Sie nicht wichtig sind.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Das folgende sind technische Details, die Sie überspringen können, wenn sie für Sie nicht wichtig sind.
|
||||
|
||||
///
|
||||
|
||||
`RequestValidationError` ist eine Unterklasse von Pydantics <a href="https://pydantic-docs.helpmanual.io/usage/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>.
|
||||
|
||||
|
|
@ -183,10 +192,13 @@ Zum Beispiel könnten Sie eine Klartext-Response statt JSON für diese Fehler zu
|
|||
{!../../../docs_src/handling_errors/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import PlainTextResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette.responses import PlainTextResponse` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
### Den `RequestValidationError`-Body verwenden
|
||||
|
||||
|
|
|
|||
|
|
@ -6,41 +6,57 @@ So wie `Query`-, `Path`-, und `Cookie`-Parameter können Sie auch <abbr title='H
|
|||
|
||||
Importieren Sie zuerst `Header`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `Header`-Parameter deklarieren
|
||||
|
||||
|
|
@ -48,49 +64,71 @@ Dann deklarieren Sie Ihre Header-Parameter, auf die gleiche Weise, wie Sie auch
|
|||
|
||||
Der erste Wert ist der Typ. Sie können `Header` die gehabten Extra Validierungs- und Beschreibungsparameter hinzufügen. Danach können Sie einen Defaultwert vergeben:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! note "Technische Details"
|
||||
`Header` ist eine Schwesterklasse von `Path`, `Query` und `Cookie`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
|
||||
///
|
||||
|
||||
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Header` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Um Header zu deklarieren, müssen Sie `Header` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// note | "Technische Details"
|
||||
|
||||
`Header` ist eine Schwesterklasse von `Path`, `Query` und `Cookie`. Sie erbt von derselben gemeinsamen `Param`-Elternklasse.
|
||||
|
||||
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `Header` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
Um Header zu deklarieren, müssen Sie `Header` verwenden, da diese Parameter sonst als Query-Parameter interpretiert werden würden.
|
||||
|
||||
///
|
||||
|
||||
## Automatische Konvertierung
|
||||
|
||||
|
|
@ -108,44 +146,63 @@ Sie können also `user_agent` schreiben, wie Sie es normalerweise in Python-Code
|
|||
|
||||
Wenn Sie aus irgendeinem Grund das automatische Konvertieren von Unterstrichen zu Bindestrichen abschalten möchten, setzen Sie den Parameter `convert_underscores` auf `False`.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/header_params/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HTTP-Proxys und Server die Verwendung von Headern mit Unterstrichen nicht erlauben.
|
||||
///
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/header_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Bevor Sie `convert_underscores` auf `False` setzen, bedenken Sie, dass manche HTTP-Proxys und Server die Verwendung von Headern mit Unterstrichen nicht erlauben.
|
||||
|
||||
///
|
||||
|
||||
## Doppelte Header
|
||||
|
||||
|
|
@ -157,50 +214,71 @@ Sie erhalten dann alle Werte von diesem doppelten Header als Python-`list`e.
|
|||
|
||||
Um zum Beispiel einen Header `X-Token` zu deklarieren, der mehrmals vorkommen kann, schreiben Sie:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/header_params/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/header_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Wenn Sie mit einer *Pfadoperation* kommunizieren, die zwei HTTP-Header sendet, wie:
|
||||
|
||||
|
|
|
|||
|
|
@ -52,22 +52,25 @@ $ pip install "fastapi[all]"
|
|||
|
||||
... das beinhaltet auch `uvicorn`, welchen Sie als Server verwenden können, der ihren Code ausführt.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Sie können die einzelnen Teile auch separat installieren.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Das folgende würden Sie wahrscheinlich tun, wenn Sie Ihre Anwendung in der Produktion einsetzen:
|
||||
Sie können die einzelnen Teile auch separat installieren.
|
||||
|
||||
```
|
||||
pip install fastapi
|
||||
```
|
||||
Das folgende würden Sie wahrscheinlich tun, wenn Sie Ihre Anwendung in der Produktion einsetzen:
|
||||
|
||||
Installieren Sie auch `uvicorn` als Server:
|
||||
```
|
||||
pip install fastapi
|
||||
```
|
||||
|
||||
```
|
||||
pip install "uvicorn[standard]"
|
||||
```
|
||||
Installieren Sie auch `uvicorn` als Server:
|
||||
|
||||
Das gleiche gilt für jede der optionalen Abhängigkeiten, die Sie verwenden möchten.
|
||||
```
|
||||
pip install "uvicorn[standard]"
|
||||
```
|
||||
|
||||
Das gleiche gilt für jede der optionalen Abhängigkeiten, die Sie verwenden möchten.
|
||||
|
||||
///
|
||||
|
||||
## Handbuch für fortgeschrittene Benutzer
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,11 @@ Sie können diese wie folgt setzen:
|
|||
{!../../../docs_src/metadata/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können Markdown in das Feld `description` schreiben und es wird in der Ausgabe gerendert.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können Markdown in das Feld `description` schreiben und es wird in der Ausgabe gerendert.
|
||||
|
||||
///
|
||||
|
||||
Mit dieser Konfiguration würde die automatische API-Dokumentation wie folgt aussehen:
|
||||
|
||||
|
|
@ -65,8 +68,11 @@ Erstellen Sie Metadaten für Ihre Tags und übergeben Sie sie an den Parameter `
|
|||
|
||||
Beachten Sie, dass Sie Markdown in den Beschreibungen verwenden können. Beispielsweise wird „login“ in Fettschrift (**login**) und „fancy“ in Kursivschrift (_fancy_) angezeigt.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie müssen nicht für alle von Ihnen verwendeten Tags Metadaten hinzufügen.
|
||||
|
||||
///
|
||||
|
||||
### Ihre Tags verwenden
|
||||
|
||||
|
|
@ -76,8 +82,11 @@ Verwenden Sie den Parameter `tags` mit Ihren *Pfadoperationen* (und `APIRouter`n
|
|||
{!../../../docs_src/metadata/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags){.internal-link target=_blank}.
|
||||
/// info
|
||||
|
||||
Lesen Sie mehr zu Tags unter [Pfadoperation-Konfiguration](path-operation-configuration.md#tags){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
### Die Dokumentation anschauen
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@ Eine „Middleware“ ist eine Funktion, die mit jedem **Request** arbeitet, bev
|
|||
* Sie kann etwas mit dieser **Response** tun oder beliebigen Code ausführen.
|
||||
* Dann gibt sie die **Response** zurück.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Wenn Sie Abhängigkeiten mit `yield` haben, wird der Exit-Code *nach* der Middleware ausgeführt.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Wenn es Hintergrundaufgaben gab (später dokumentiert), werden sie *nach* allen Middlewares ausgeführt.
|
||||
Wenn Sie Abhängigkeiten mit `yield` haben, wird der Exit-Code *nach* der Middleware ausgeführt.
|
||||
|
||||
Wenn es Hintergrundaufgaben gab (später dokumentiert), werden sie *nach* allen Middlewares ausgeführt.
|
||||
|
||||
///
|
||||
|
||||
## Erstellung einer Middleware
|
||||
|
||||
|
|
@ -32,15 +35,21 @@ Die Middleware-Funktion erhält:
|
|||
{!../../../docs_src/middleware/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">Verwenden Sie dafür das Präfix 'X-'</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfigurationen ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette-CORS-Dokumentation</a> dokumentiert ist.
|
||||
Beachten Sie, dass benutzerdefinierte proprietäre Header hinzugefügt werden können. <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">Verwenden Sie dafür das Präfix 'X-'</a>.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie könnten auch `from starlette.requests import Request` verwenden.
|
||||
Wenn Sie jedoch benutzerdefinierte Header haben, die ein Client in einem Browser sehen soll, müssen Sie sie zu Ihrer CORS-Konfigurationen ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank}) hinzufügen, indem Sie den Parameter `expose_headers` verwenden, der in der <a href="https://www.starlette.io/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette-CORS-Dokumentation</a> dokumentiert ist.
|
||||
|
||||
**FastAPI** bietet es als Komfort für Sie, den Entwickler, an. Aber es stammt direkt von Starlette.
|
||||
///
|
||||
|
||||
/// note | "Technische Details"
|
||||
|
||||
Sie könnten auch `from starlette.requests import Request` verwenden.
|
||||
|
||||
**FastAPI** bietet es als Komfort für Sie, den Entwickler, an. Aber es stammt direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
### Vor und nach der `response`
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
Es gibt mehrere Konfigurations-Parameter, die Sie Ihrem *Pfadoperation-Dekorator* übergeben können.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeben werden, nicht der *Pfadoperation-Funktion*.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Beachten Sie, dass diese Parameter direkt dem *Pfadoperation-Dekorator* übergeben werden, nicht der *Pfadoperation-Funktion*.
|
||||
|
||||
///
|
||||
|
||||
## Response-Statuscode
|
||||
|
||||
|
|
@ -13,52 +16,67 @@ Sie können direkt den `int`-Code übergeben, etwa `404`.
|
|||
|
||||
Aber falls Sie sich nicht mehr erinnern, wofür jede Nummer steht, können Sie die Abkürzungs-Konstanten in `status` verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1 15"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1 15"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="3 17"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="3 17"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3 17"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="3 17"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Dieser Statuscode wird in der Response verwendet und zum OpenAPI-Schema hinzugefügt.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette import status` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette import status` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
## Tags
|
||||
|
||||
Sie können Ihrer *Pfadoperation* Tags hinzufügen, mittels des Parameters `tags`, dem eine `list`e von `str`s übergeben wird (in der Regel nur ein `str`):
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="15 20 25"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="15 20 25"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17 22 27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="17 22 27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17 22 27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="17 22 27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Diese werden zum OpenAPI-Schema hinzugefügt und von den automatischen Dokumentations-Benutzeroberflächen verwendet:
|
||||
|
||||
|
|
@ -80,23 +98,29 @@ In diesem Fall macht es Sinn, die Tags in einem `Enum` zu speichern.
|
|||
|
||||
Sie können eine Zusammenfassung (`summary`) und eine Beschreibung (`description`) hinzufügen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="18-19"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="20-21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="20-21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20-21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="20-21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Beschreibung mittels Docstring
|
||||
|
||||
|
|
@ -104,23 +128,29 @@ Da Beschreibungen oft mehrere Zeilen lang sind, können Sie die Beschreibung der
|
|||
|
||||
Sie können im Docstring <a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a> schreiben, es wird korrekt interpretiert und angezeigt (die Einrückung des Docstring beachtend).
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="17-25"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="17-25"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="19-27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="19-27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial004_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="19-27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="19-27"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In der interaktiven Dokumentation sieht das dann so aus:
|
||||
|
||||
|
|
@ -130,31 +160,43 @@ In der interaktiven Dokumentation sieht das dann so aus:
|
|||
|
||||
Die Response können Sie mit dem Parameter `response_description` beschreiben:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial005_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! info
|
||||
beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! check
|
||||
OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt.
|
||||
```Python hl_lines="21"
|
||||
{!> ../../../docs_src/path_operation_configuration/tutorial005.py!}
|
||||
```
|
||||
|
||||
Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolgreiche Response“ erstellen.
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
beachten Sie, dass sich `response_description` speziell auf die Response bezieht, während `description` sich generell auf die *Pfadoperation* bezieht.
|
||||
|
||||
///
|
||||
|
||||
/// check
|
||||
|
||||
OpenAPI verlangt, dass jede *Pfadoperation* über eine Beschreibung der Response verfügt.
|
||||
|
||||
Daher, wenn Sie keine vergeben, wird **FastAPI** automatisch eine für „Erfolgreiche Response“ erstellen.
|
||||
|
||||
///
|
||||
|
||||
<img src="/img/tutorial/path-operation-configuration/image03.png">
|
||||
|
||||
|
|
|
|||
|
|
@ -6,48 +6,67 @@ So wie Sie mit `Query` für Query-Parameter zusätzliche Validierungen und Metad
|
|||
|
||||
Importieren Sie zuerst `Path` von `fastapi`, und importieren Sie `Annotated`.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="1 3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="1 3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1 3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="1 3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3-4"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="3-4"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! info
|
||||
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
|
||||
///
|
||||
|
||||
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
Bitte [aktualisieren Sie FastAPI](../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
FastAPI unterstützt (und empfiehlt die Verwendung von) `Annotated` seit Version 0.95.0.
|
||||
|
||||
Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, `Annotated` zu verwenden.
|
||||
|
||||
Bitte [aktualisieren Sie FastAPI](../deployment/versions.md#upgrade-der-fastapi-versionen){.internal-link target=_blank} daher mindestens zu Version 0.95.1, bevor Sie `Annotated` verwenden.
|
||||
|
||||
///
|
||||
|
||||
## Metadaten deklarieren
|
||||
|
||||
|
|
@ -55,53 +74,75 @@ Sie können die gleichen Parameter deklarieren wie für `Query`.
|
|||
|
||||
Um zum Beispiel einen `title`-Metadaten-Wert für den Pfad-Parameter `item_id` zu deklarieren, schreiben Sie:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Ein Pfad-Parameter ist immer erforderlich, weil er Teil des Pfads sein muss.
|
||||
///
|
||||
|
||||
Sie sollten ihn daher mit `...` deklarieren, um ihn als erforderlich auszuzeichnen.
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
Doch selbst wenn Sie ihn mit `None` deklarieren, oder einen Defaultwert setzen, bewirkt das nichts, er bleibt immer erforderlich.
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// note | "Hinweis"
|
||||
|
||||
Ein Pfad-Parameter ist immer erforderlich, weil er Teil des Pfads sein muss.
|
||||
|
||||
Sie sollten ihn daher mit `...` deklarieren, um ihn als erforderlich auszuzeichnen.
|
||||
|
||||
Doch selbst wenn Sie ihn mit `None` deklarieren, oder einen Defaultwert setzen, bewirkt das nichts, er bleibt immer erforderlich.
|
||||
|
||||
///
|
||||
|
||||
## Sortieren Sie die Parameter, wie Sie möchten
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
|
||||
|
||||
///
|
||||
|
||||
Nehmen wir an, Sie möchten den Query-Parameter `q` als erforderlichen `str` deklarieren.
|
||||
|
||||
|
|
@ -117,33 +158,45 @@ Für **FastAPI** ist es nicht wichtig. Es erkennt die Parameter anhand ihres Nam
|
|||
|
||||
Sie können Ihre Funktion also so deklarieren:
|
||||
|
||||
=== "Python 3.8 nicht annotiert"
|
||||
//// tab | Python 3.8 nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie `Annotated` verwenden, da Sie nicht die Funktions-Parameter-Defaultwerte für `Query()` oder `Path()` verwenden.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Sortieren Sie die Parameter wie Sie möchten: Tricks
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie `Annotated` verwenden, ist das folgende nicht so wichtig / nicht notwendig.
|
||||
|
||||
///
|
||||
|
||||
Hier ein **kleiner Trick**, der nützlich sein kann, aber Sie werden ihn nicht oft brauchen.
|
||||
|
||||
|
|
@ -168,43 +221,56 @@ Python macht nichts mit diesem `*`, aber es wird wissen, dass alle folgenden Par
|
|||
|
||||
Bedenken Sie, dass Sie, wenn Sie `Annotated` verwenden, dieses Problem nicht haben, weil Sie keine Defaultwerte für Ihre Funktionsparameter haben. Sie müssen daher wahrscheinlich auch nicht `*` verwenden.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Validierung von Zahlen: Größer oder gleich
|
||||
|
||||
Mit `Query` und `Path` (und anderen, die Sie später kennenlernen), können Sie Zahlenbeschränkungen deklarieren.
|
||||
|
||||
Hier, mit `ge=1`, wird festgelegt, dass `item_id` eine Ganzzahl benötigt, die größer oder gleich `1` ist (`g`reater than or `e`qual).
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Validierung von Zahlen: Größer und kleiner oder gleich
|
||||
|
||||
|
|
@ -213,26 +279,35 @@ Das Gleiche trifft zu auf:
|
|||
* `gt`: `g`reater `t`han – größer als
|
||||
* `le`: `l`ess than or `e`qual – kleiner oder gleich
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Validierung von Zahlen: Floats, größer und kleiner
|
||||
|
||||
|
|
@ -244,26 +319,35 @@ Hier wird es wichtig, in der Lage zu sein, <abbr title="greater than – größe
|
|||
|
||||
Das gleiche gilt für <abbr title="less than – kleiner als"><code>lt</code></abbr>.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial006_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/path_params_numeric_validations/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
@ -276,18 +360,24 @@ Und Sie können auch Validierungen für Zahlen deklarieren:
|
|||
* `lt`: `l`ess `t`han – kleiner als
|
||||
* `le`: `l`ess than or `e`qual – kleiner oder gleich
|
||||
|
||||
!!! info
|
||||
`Query`, `Path`, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen `Param`-Klasse.
|
||||
/// info
|
||||
|
||||
Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.
|
||||
`Query`, `Path`, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen `Param`-Klasse.
|
||||
|
||||
!!! note "Technische Details"
|
||||
`Query`, `Path` und andere, die Sie von `fastapi` importieren, sind tatsächlich Funktionen.
|
||||
Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.
|
||||
|
||||
Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben.
|
||||
///
|
||||
|
||||
Sie importieren also `Query`, welches eine Funktion ist. Aber wenn Sie es aufrufen, gibt es eine Instanz der Klasse zurück, die auch `Query` genannt wird.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt.
|
||||
`Query`, `Path` und andere, die Sie von `fastapi` importieren, sind tatsächlich Funktionen.
|
||||
|
||||
Auf diese Weise können Sie Ihren Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten.
|
||||
Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben.
|
||||
|
||||
Sie importieren also `Query`, welches eine Funktion ist. Aber wenn Sie es aufrufen, gibt es eine Instanz der Klasse zurück, die auch `Query` genannt wird.
|
||||
|
||||
Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt.
|
||||
|
||||
Auf diese Weise können Sie Ihren Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -24,8 +24,11 @@ Sie können den Typ eines Pfad-Parameters in der Argumentliste der Funktion dekl
|
|||
|
||||
In diesem Fall wird `item_id` als `int` deklariert, also als Ganzzahl.
|
||||
|
||||
!!! check
|
||||
Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw.
|
||||
/// check
|
||||
|
||||
Dadurch erhalten Sie Editor-Unterstützung innerhalb Ihrer Funktion, mit Fehlerprüfungen, Codevervollständigung, usw.
|
||||
|
||||
///
|
||||
|
||||
## Daten-<abbr title="Auch bekannt als: Serialisierung, Parsen, Marshalling">Konversion</abbr>
|
||||
|
||||
|
|
@ -35,10 +38,13 @@ Wenn Sie dieses Beispiel ausführen und Ihren Browser unter <a href="http://127.
|
|||
{"item_id":3}
|
||||
```
|
||||
|
||||
!!! check
|
||||
Beachten Sie, dass der Wert, den Ihre Funktion erhält und zurückgibt, die Zahl `3` ist, also ein `int`. Nicht der String `"3"`, also ein `str`.
|
||||
/// check
|
||||
|
||||
Sprich, mit dieser Typdeklaration wird **FastAPI** die Anfrage automatisch <abbr title="Den String, der von einer HTTP Anfrage kommt, in Python-Objekte konvertieren">„parsen“</abbr>.
|
||||
Beachten Sie, dass der Wert, den Ihre Funktion erhält und zurückgibt, die Zahl `3` ist, also ein `int`. Nicht der String `"3"`, also ein `str`.
|
||||
|
||||
Sprich, mit dieser Typdeklaration wird **FastAPI** die Anfrage automatisch <abbr title="Den String, der von einer HTTP Anfrage kommt, in Python-Objekte konvertieren">„parsen“</abbr>.
|
||||
|
||||
///
|
||||
|
||||
## Datenvalidierung
|
||||
|
||||
|
|
@ -65,12 +71,15 @@ Der Pfad-Parameter `item_id` hatte den Wert `"foo"`, was kein `int` ist.
|
|||
|
||||
Die gleiche Fehlermeldung würde angezeigt werden, wenn Sie ein `float` (also eine Kommazahl) statt eines `int`s übergeben würden, wie etwa in: <a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a>
|
||||
|
||||
!!! check
|
||||
Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung.
|
||||
/// check
|
||||
|
||||
Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war.
|
||||
Sprich, mit der gleichen Python-Typdeklaration gibt Ihnen **FastAPI** Datenvalidierung.
|
||||
|
||||
Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit ihrer API interagiert.
|
||||
Beachten Sie, dass die Fehlermeldung auch direkt die Stelle anzeigt, wo die Validierung nicht erfolgreich war.
|
||||
|
||||
Das ist unglaublich hilfreich, wenn Sie Code entwickeln und debuggen, welcher mit ihrer API interagiert.
|
||||
|
||||
///
|
||||
|
||||
## Dokumentation
|
||||
|
||||
|
|
@ -78,10 +87,13 @@ Wenn Sie die Seite <a href="http://127.0.0.1:8000/docs" class="external-link" ta
|
|||
|
||||
<img src="/img/tutorial/path-params/image01.png">
|
||||
|
||||
!!! check
|
||||
Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche).
|
||||
/// check
|
||||
|
||||
Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist.
|
||||
Wiederum, mit dieser gleichen Python-Typdeklaration gibt Ihnen **FastAPI** eine automatische, interaktive Dokumentation (verwendet die Swagger-Benutzeroberfläche).
|
||||
|
||||
Beachten Sie, dass der Pfad-Parameter dort als Ganzzahl deklariert ist.
|
||||
|
||||
///
|
||||
|
||||
## Nützliche Standards. Alternative Dokumentation
|
||||
|
||||
|
|
@ -141,11 +153,17 @@ Erstellen Sie dann Klassen-Attribute mit festgelegten Werten, welches die erlaub
|
|||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerationen (oder kurz Enums)</a> gibt es in Python seit Version 3.4.
|
||||
/// info
|
||||
|
||||
!!! tip "Tipp"
|
||||
Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das sind Namen von <abbr title="Genau genommen, Deep-Learning-Modellarchitekturen">Modellen</abbr> für maschinelles Lernen.
|
||||
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerationen (oder kurz Enums)</a> gibt es in Python seit Version 3.4.
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Falls Sie sich fragen, was „AlexNet“, „ResNet“ und „LeNet“ ist, das sind Namen von <abbr title="Genau genommen, Deep-Learning-Modellarchitekturen">Modellen</abbr> für maschinelles Lernen.
|
||||
|
||||
///
|
||||
|
||||
### Deklarieren Sie einen *Pfad-Parameter*
|
||||
|
||||
|
|
@ -181,8 +199,11 @@ Den tatsächlichen Wert (in diesem Fall ein `str`) erhalten Sie via `model_name.
|
|||
{!../../../docs_src/path_params/tutorial005.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können den Wert `"lenet"` außerdem mittels `ModelName.lenet.value` abrufen.
|
||||
|
||||
///
|
||||
|
||||
#### *Enum-Member* zurückgeben
|
||||
|
||||
|
|
@ -235,10 +256,13 @@ Sie verwenden das also wie folgt:
|
|||
{!../../../docs_src/path_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Der Parameter könnte einen führenden Schrägstrich (`/`) haben, wie etwa in `/home/johndoe/myfile.txt`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelten Schrägstrich (`//`) zwischen `files` und `home`.
|
||||
Der Parameter könnte einen führenden Schrägstrich (`/`) haben, wie etwa in `/home/johndoe/myfile.txt`.
|
||||
|
||||
In dem Fall wäre die URL: `/files//home/johndoe/myfile.txt`, mit einem doppelten Schrägstrich (`//`) zwischen `files` und `home`.
|
||||
|
||||
///
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -63,38 +63,49 @@ gehen, werden die Parameter-Werte Ihrer Funktion sein:
|
|||
|
||||
Auf die gleiche Weise können Sie optionale Query-Parameter deklarieren, indem Sie deren Defaultwert auf `None` setzen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall wird der Funktionsparameter `q` optional, und standardmäßig `None` sein.
|
||||
|
||||
!!! check
|
||||
Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein.
|
||||
/// check
|
||||
|
||||
Beachten Sie auch, dass **FastAPI** intelligent genug ist, um zu erkennen, dass `item_id` ein Pfad-Parameter ist und `q` keiner, daher muss letzteres ein Query-Parameter sein.
|
||||
|
||||
///
|
||||
|
||||
## Query-Parameter Typkonvertierung
|
||||
|
||||
Sie können auch `bool`-Typen deklarieren und sie werden konvertiert:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/query_params/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Wenn Sie nun zu:
|
||||
|
||||
|
|
@ -136,17 +147,21 @@ Und Sie müssen sie auch nicht in einer spezifischen Reihenfolge deklarieren.
|
|||
|
||||
Parameter werden anhand ihres Namens erkannt:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="6 8"
|
||||
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="6 8"
|
||||
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8 10"
|
||||
{!> ../../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="8 10"
|
||||
{!> ../../../docs_src/query_params/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Erforderliche Query-Parameter
|
||||
|
||||
|
|
@ -204,17 +219,21 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
|
|||
|
||||
Und natürlich können Sie einige Parameter als erforderlich, einige mit Defaultwert, und einige als vollständig optional definieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
|
||||
```
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/query_params/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/query_params/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
In diesem Fall gibt es drei Query-Parameter:
|
||||
|
||||
|
|
@ -222,5 +241,8 @@ In diesem Fall gibt es drei Query-Parameter:
|
|||
* `skip`, ein `int` mit einem Defaultwert `0`.
|
||||
* `limit`, ein optionales `int`.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#vordefinierte-parameterwerte){.internal-link target=_blank}.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können auch `Enum`s verwenden, auf die gleiche Weise wie mit [Pfad-Parametern](path-params.md#vordefinierte-parameterwerte){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -2,70 +2,97 @@
|
|||
|
||||
Mit `File` können sie vom Client hochzuladende Dateien definieren.
|
||||
|
||||
!!! info
|
||||
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
/// info
|
||||
|
||||
Z. B. `pip install python-multipart`.
|
||||
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Das, weil hochgeladene Dateien als „Formulardaten“ gesendet werden.
|
||||
Z. B. `pip install python-multipart`.
|
||||
|
||||
Das, weil hochgeladene Dateien als „Formulardaten“ gesendet werden.
|
||||
|
||||
///
|
||||
|
||||
## `File` importieren
|
||||
|
||||
Importieren Sie `File` und `UploadFile` von `fastapi`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `File`-Parameter definieren
|
||||
|
||||
Erstellen Sie Datei-Parameter, so wie Sie es auch mit `Body` und `Form` machen würden:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
!!! info
|
||||
`File` ist eine Klasse, die direkt von `Form` erbt.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
|
||||
///
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
`File` ist eine Klasse, die direkt von `Form` erbt.
|
||||
|
||||
Aber erinnern Sie sich, dass, wenn Sie `Query`, `Path`, `File` und andere von `fastapi` importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um Dateibodys zu deklarieren, müssen Sie `File` verwenden, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
|
||||
|
||||
///
|
||||
|
||||
Die Dateien werden als „Formulardaten“ hochgeladen.
|
||||
|
||||
|
|
@ -79,26 +106,35 @@ Aber es gibt viele Fälle, in denen Sie davon profitieren, `UploadFile` zu verwe
|
|||
|
||||
Definieren Sie einen Datei-Parameter mit dem Typ `UploadFile`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="13"
|
||||
{!> ../../../docs_src/request_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/request_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
`UploadFile` zu verwenden, hat mehrere Vorzüge gegenüber `bytes`:
|
||||
|
||||
|
|
@ -141,11 +177,17 @@ Wenn Sie sich innerhalb einer normalen `def`-*Pfadoperation-Funktion* befinden,
|
|||
contents = myfile.file.read()
|
||||
```
|
||||
|
||||
!!! note "Technische Details zu `async`"
|
||||
Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden in einem <abbr title="Mehrere unabhängige Kindprozesse">Threadpool</abbr> aus und erwartet sie.
|
||||
/// note | "Technische Details zu `async`"
|
||||
|
||||
!!! note "Technische Details zu Starlette"
|
||||
**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen.
|
||||
Wenn Sie die `async`-Methoden verwenden, führt **FastAPI** die Datei-Methoden in einem <abbr title="Mehrere unabhängige Kindprozesse">Threadpool</abbr> aus und erwartet sie.
|
||||
|
||||
///
|
||||
|
||||
/// note | "Technische Details zu Starlette"
|
||||
|
||||
**FastAPI**s `UploadFile` erbt direkt von **Starlette**s `UploadFile`, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit **Pydantic** und anderen Teilen von FastAPI zu machen.
|
||||
|
||||
///
|
||||
|
||||
## Was sind „Formulardaten“
|
||||
|
||||
|
|
@ -153,82 +195,113 @@ HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodi
|
|||
|
||||
**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss.
|
||||
Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
|
||||
|
||||
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
|
||||
Sollte das Formular aber Dateien enthalten, dann werden diese mit `multipart/form-data` kodiert. Wenn Sie `File` verwenden, wird **FastAPI** wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
|
||||
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
|
||||
|
||||
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
|
||||
///
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
|
||||
|
||||
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
|
||||
|
||||
///
|
||||
|
||||
## Optionaler Datei-Upload
|
||||
|
||||
Sie können eine Datei optional machen, indem Sie Standard-Typannotationen verwenden und den Defaultwert auf `None` setzen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an_py310.py!}
|
||||
```
|
||||
```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!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="10 18"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="10 18"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7 15"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7 15"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="9 17"
|
||||
{!> ../../../docs_src/request_files/tutorial001_02.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `UploadFile` mit zusätzlichen Metadaten
|
||||
|
||||
Sie können auch `File()` zusammen mit `UploadFile` verwenden, um zum Beispiel zusätzliche Metadaten zu setzen:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9 15"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="9 15"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8 14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="8 14"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="7 13"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7 13"
|
||||
{!> ../../../docs_src/request_files/tutorial001_03.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Mehrere Datei-Uploads
|
||||
|
||||
|
|
@ -238,76 +311,107 @@ Diese werden demselben Formularfeld zugeordnet, welches mit den Formulardaten ge
|
|||
|
||||
Um das zu machen, deklarieren Sie eine Liste von `bytes` oder `UploadFile`s:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/request_files/tutorial002_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
```Python hl_lines="11 16"
|
||||
{!> ../../../docs_src/request_files/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002.py!}
|
||||
```
|
||||
///
|
||||
|
||||
```Python hl_lines="8 13"
|
||||
{!> ../../../docs_src/request_files/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10 15"
|
||||
{!> ../../../docs_src/request_files/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Sie erhalten, wie deklariert, eine `list`e von `bytes` oder `UploadFile`s.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette.responses import HTMLResponse` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette.responses import HTMLResponse` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.responses` auch via `fastapi.responses` an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
### Mehrere Datei-Uploads mit zusätzlichen Metadaten
|
||||
|
||||
Und so wie zuvor können Sie `File()` verwenden, um zusätzliche Parameter zu setzen, sogar für `UploadFile`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="11 18-20"
|
||||
{!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="11 18-20"
|
||||
{!> ../../../docs_src/request_files/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="12 19-21"
|
||||
{!> ../../../docs_src/request_files/tutorial003_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.9+ nicht annotiert"
|
||||
```Python hl_lines="12 19-21"
|
||||
{!> ../../../docs_src/request_files/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="9 16"
|
||||
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+ nicht annotiert
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
/// tip | "Tipp"
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
```Python hl_lines="11 18"
|
||||
{!> ../../../docs_src/request_files/tutorial003.py!}
|
||||
```
|
||||
///
|
||||
|
||||
```Python hl_lines="9 16"
|
||||
{!> ../../../docs_src/request_files/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="11 18"
|
||||
{!> ../../../docs_src/request_files/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -2,67 +2,91 @@
|
|||
|
||||
Sie können gleichzeitig Dateien und Formulardaten mit `File` und `Form` definieren.
|
||||
|
||||
!!! info
|
||||
Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
/// info
|
||||
|
||||
Z. B. `pip install python-multipart`.
|
||||
Um hochgeladene Dateien und/oder Formulardaten zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Z. B. `pip install python-multipart`.
|
||||
|
||||
///
|
||||
|
||||
## `File` und `Form` importieren
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `File` und `Form`-Parameter definieren
|
||||
|
||||
Erstellen Sie Datei- und Formularparameter, so wie Sie es auch mit `Body` und `Query` machen würden:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="10-12"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="10-12"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="9-11"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_forms_and_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Die Datei- und Formularfelder werden als Formulardaten hochgeladen, und Sie erhalten diese Dateien und Formularfelder.
|
||||
|
||||
Und Sie können einige der Dateien als `bytes` und einige als `UploadFile` deklarieren.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
|
||||
/// warning | "Achtung"
|
||||
|
||||
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
|
||||
Sie können mehrere `File`- und `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `multipart/form-data` statt `application/json` kodiert.
|
||||
|
||||
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
|
||||
|
||||
///
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -2,60 +2,81 @@
|
|||
|
||||
Wenn Sie Felder aus Formularen statt JSON empfangen müssen, können Sie `Form` verwenden.
|
||||
|
||||
!!! info
|
||||
Um Formulare zu verwenden, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
/// info
|
||||
|
||||
Z. B. `pip install python-multipart`.
|
||||
Um Formulare zu verwenden, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Z. B. `pip install python-multipart`.
|
||||
|
||||
///
|
||||
|
||||
## `Form` importieren
|
||||
|
||||
Importieren Sie `Form` von `fastapi`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="3"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
{!> ../../../docs_src/request_forms/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `Form`-Parameter definieren
|
||||
|
||||
Erstellen Sie Formular-Parameter, so wie Sie es auch mit `Body` und `Query` machen würden:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/request_forms/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/request_forms/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/request_forms/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Zum Beispiel stellt eine der Möglichkeiten, die OAuth2 Spezifikation zu verwenden (genannt <abbr title='„Passwort-Fluss“'>„password flow“</abbr>), die Bedingung, einen `username` und ein `password` als Formularfelder zu senden.
|
||||
|
||||
|
|
@ -63,11 +84,17 @@ Die <abbr title="Specification – Spezifikation">Spec</abbr> erfordert, dass di
|
|||
|
||||
Mit `Form` haben Sie die gleichen Konfigurationsmöglichkeiten wie mit `Body` (und `Query`, `Path`, `Cookie`), inklusive Validierung, Beispielen, einem Alias (z. B. `user-name` statt `username`), usw.
|
||||
|
||||
!!! info
|
||||
`Form` ist eine Klasse, die direkt von `Body` erbt.
|
||||
/// info
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
|
||||
`Form` ist eine Klasse, die direkt von `Body` erbt.
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um Formularbodys zu deklarieren, verwenden Sie explizit `Form`, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
|
||||
|
||||
///
|
||||
|
||||
## Über „Formularfelder“
|
||||
|
||||
|
|
@ -75,17 +102,23 @@ HTML-Formulare (`<form></form>`) senden die Daten in einer „speziellen“ Kodi
|
|||
|
||||
**FastAPI** stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Daten aus Formularen werden normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien.
|
||||
Daten aus Formularen werden normalerweise mit dem <abbr title='Media type – Medientyp, Typ des Mediums'>„media type“</abbr> `application/x-www-form-urlencoded` kodiert.
|
||||
|
||||
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
|
||||
Wenn das Formular stattdessen Dateien enthält, werden diese mit `multipart/form-data` kodiert. Im nächsten Kapitel erfahren Sie mehr über die Handhabung von Dateien.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert.
|
||||
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr>-Webdokumentation für <code>POST</code></a>.
|
||||
|
||||
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
|
||||
///
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Sie können mehrere `Form`-Parameter in einer *Pfadoperation* deklarieren, aber Sie können nicht gleichzeitig auch `Body`-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels `application/x-www-form-urlencoded` statt `application/json` kodiert.
|
||||
|
||||
Das ist keine Limitation von **FastAPI**, sondern Teil des HTTP-Protokolls.
|
||||
|
||||
///
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -4,23 +4,29 @@ Sie können den Typ der <abbr title="Response – Antwort: Daten, die zum anfrag
|
|||
|
||||
Hierbei können Sie **Typannotationen** genauso verwenden, wie Sie es bei Werten von Funktions-**Parametern** machen; verwenden Sie Pydantic-Modelle, Listen, Dicts und skalare Werte wie Nummern, Booleans, usw.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="16 21"
|
||||
{!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
|
||||
```
|
||||
```Python hl_lines="16 21"
|
||||
{!> ../../../docs_src/response_model/tutorial001_01_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18 23"
|
||||
{!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="18 23"
|
||||
{!> ../../../docs_src/response_model/tutorial001_01_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="18 23"
|
||||
{!> ../../../docs_src/response_model/tutorial001_01.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="18 23"
|
||||
{!> ../../../docs_src/response_model/tutorial001_01.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
FastAPI wird diesen Rückgabetyp verwenden, um:
|
||||
|
||||
|
|
@ -53,35 +59,47 @@ Sie können `response_model` in jeder möglichen *Pfadoperation* verwenden:
|
|||
* `@app.delete()`
|
||||
* usw.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="17 22 24-27"
|
||||
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="17 22 24-27"
|
||||
{!> ../../../docs_src/response_model/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="17 22 24-27"
|
||||
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="17 22 24-27"
|
||||
{!> ../../../docs_src/response_model/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17 22 24-27"
|
||||
{!> ../../../docs_src/response_model/tutorial001.py!}
|
||||
```
|
||||
////
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="17 22 24-27"
|
||||
{!> ../../../docs_src/response_model/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// note | "Hinweis"
|
||||
|
||||
Beachten Sie, dass `response_model` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter.
|
||||
|
||||
///
|
||||
|
||||
`response_model` nimmt denselben Typ entgegen, den Sie auch für ein Pydantic-Modellfeld deklarieren würden, also etwa ein Pydantic-Modell, aber es kann auch z. B. eine `list`e von Pydantic-Modellen sein, wie etwa `List[Item]`.
|
||||
|
||||
FastAPI wird dieses `response_model` nehmen, um die Daten zu dokumentieren, validieren, usw. und auch, um **die Ausgabedaten** entsprechend der Typdeklaration **zu konvertieren und filtern**.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als <abbr title='„Irgend etwas“'>`Any`</abbr> deklarieren.
|
||||
/// tip | "Tipp"
|
||||
|
||||
So sagen Sie dem Editor, dass Sie absichtlich *irgendetwas* zurückgeben. Aber FastAPI wird trotzdem die Dokumentation, Validierung, Filterung, usw. der Daten übernehmen, via `response_model`.
|
||||
Wenn Sie in Ihrem Editor strikte Typchecks haben, mypy, usw., können Sie den Funktions-Rückgabetyp als <abbr title='„Irgend etwas“'>`Any`</abbr> deklarieren.
|
||||
|
||||
So sagen Sie dem Editor, dass Sie absichtlich *irgendetwas* zurückgeben. Aber FastAPI wird trotzdem die Dokumentation, Validierung, Filterung, usw. der Daten übernehmen, via `response_model`.
|
||||
|
||||
///
|
||||
|
||||
### `response_model`-Priorität
|
||||
|
||||
|
|
@ -95,37 +113,48 @@ Sie können auch `response_model=None` verwenden, um das Erstellen eines Respons
|
|||
|
||||
Im Folgenden deklarieren wir ein `UserIn`-Modell; es enthält ein Klartext-Passwort:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7 9"
|
||||
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7 9"
|
||||
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9 11"
|
||||
{!> ../../../docs_src/response_model/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! info
|
||||
Um `EmailStr` zu verwenden, installieren Sie zuerst <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email_validator`</a>.
|
||||
```Python hl_lines="9 11"
|
||||
{!> ../../../docs_src/response_model/tutorial002.py!}
|
||||
```
|
||||
|
||||
Z. B. `pip install email-validator`
|
||||
oder `pip install pydantic[email]`.
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
Um `EmailStr` zu verwenden, installieren Sie zuerst <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email_validator`</a>.
|
||||
|
||||
Z. B. `pip install email-validator`
|
||||
oder `pip install pydantic[email]`.
|
||||
|
||||
///
|
||||
|
||||
Wir verwenden dieses Modell, um sowohl unsere Eingabe- als auch Ausgabedaten zu deklarieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="16"
|
||||
{!> ../../../docs_src/response_model/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/response_model/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="18"
|
||||
{!> ../../../docs_src/response_model/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Immer wenn jetzt ein Browser einen Benutzer mit Passwort erzeugt, gibt die API dasselbe Passwort in der Response zurück.
|
||||
|
||||
|
|
@ -133,52 +162,67 @@ Hier ist das möglicherweise kein Problem, da es derselbe Benutzer ist, der das
|
|||
|
||||
Aber wenn wir dasselbe Modell für eine andere *Pfadoperation* verwenden, könnten wir das Passwort dieses Benutzers zu jedem Client schicken.
|
||||
|
||||
!!! danger "Gefahr"
|
||||
Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie es in einer Response wie dieser, wenn Sie sich nicht der resultierenden Gefahren bewusst sind und nicht wissen, was Sie tun.
|
||||
/// danger | "Gefahr"
|
||||
|
||||
Speichern Sie niemals das Klartext-Passwort eines Benutzers, oder versenden Sie es in einer Response wie dieser, wenn Sie sich nicht der resultierenden Gefahren bewusst sind und nicht wissen, was Sie tun.
|
||||
|
||||
///
|
||||
|
||||
## Ausgabemodell hinzufügen
|
||||
|
||||
Wir können stattdessen ein Eingabemodell mit dem Klartext-Passwort, und ein Ausgabemodell ohne das Passwort erstellen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9 11 16"
|
||||
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="9 11 16"
|
||||
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9 11 16"
|
||||
{!> ../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9 11 16"
|
||||
{!> ../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Obwohl unsere *Pfadoperation-Funktion* hier denselben `user` von der Eingabe zurückgibt, der das Passwort enthält:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... haben wir deklariert, dass `response_model` das Modell `UserOut` ist, welches das Passwort nicht enthält:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
|
||||
```
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/response_model/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/response_model/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Darum wird **FastAPI** sich darum kümmern, dass alle Daten, die nicht im Ausgabemodell deklariert sind, herausgefiltert werden (mittels Pydantic).
|
||||
|
||||
|
|
@ -202,17 +246,21 @@ Aber in den meisten Fällen, wenn wir so etwas machen, wollen wir nur, dass das
|
|||
|
||||
Und in solchen Fällen können wir Klassen und Vererbung verwenden, um Vorteil aus den Typannotationen in der Funktion zu ziehen, was vom Editor und von Tools besser unterstützt wird, während wir gleichzeitig FastAPIs **Datenfilterung** behalten.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7-10 13-14 18"
|
||||
{!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7-10 13-14 18"
|
||||
{!> ../../../docs_src/response_model/tutorial003_01_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9-13 15-16 20"
|
||||
{!> ../../../docs_src/response_model/tutorial003_01.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9-13 15-16 20"
|
||||
{!> ../../../docs_src/response_model/tutorial003_01.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Damit erhalten wir Tool-Unterstützung, vom Editor und mypy, da dieser Code hinsichtlich der Typen korrekt ist, aber wir erhalten auch die Datenfilterung von FastAPI.
|
||||
|
||||
|
|
@ -278,17 +326,21 @@ Aber wenn Sie ein beliebiges anderes Objekt zurückgeben, das kein gültiger Pyd
|
|||
|
||||
Das gleiche wird passieren, wenn Sie eine <abbr title='Eine Union mehrerer Typen bedeutet: „Irgendeiner dieser Typen“'>Union</abbr> mehrerer Typen haben, und einer oder mehrere sind nicht gültige Pydantic-Typen. Zum Beispiel funktioniert folgendes nicht 💥:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
|
||||
```
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/response_model/tutorial003_04_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/response_model/tutorial003_04.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/response_model/tutorial003_04.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
... das scheitert, da die Typannotation kein Pydantic-Typ ist, und auch keine einzelne `Response`-Klasse, oder -Unterklasse, es ist eine Union (eines von beiden) von `Response` und `dict`.
|
||||
|
||||
|
|
@ -300,17 +352,21 @@ Aber Sie möchten dennoch den Rückgabetyp in der Funktion annotieren, um Unters
|
|||
|
||||
In diesem Fall können Sie die Generierung des Responsemodells abschalten, indem Sie `response_model=None` setzen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/response_model/tutorial003_05_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/response_model/tutorial003_05.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="9"
|
||||
{!> ../../../docs_src/response_model/tutorial003_05.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Das bewirkt, dass FastAPI die Generierung des Responsemodells unterlässt, und damit können Sie jede gewünschte Rückgabetyp-Annotation haben, ohne dass es Ihre FastAPI-Anwendung beeinflusst. 🤓
|
||||
|
||||
|
|
@ -318,23 +374,29 @@ Das bewirkt, dass FastAPI die Generierung des Responsemodells unterlässt, und d
|
|||
|
||||
Ihr Responsemodell könnte Defaultwerte haben, wie:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="9 11-12"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="9 11-12"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11 13-14"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="11 13-14"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="11 13-14"
|
||||
{!> ../../../docs_src/response_model/tutorial004.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="11 13-14"
|
||||
{!> ../../../docs_src/response_model/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
* `description: Union[str, None] = None` (oder `str | None = None` in Python 3.10) hat einen Defaultwert `None`.
|
||||
* `tax: float = 10.5` hat einen Defaultwert `10.5`.
|
||||
|
|
@ -348,23 +410,29 @@ Wenn Sie zum Beispiel Modelle mit vielen optionalen Attributen in einer NoSQL-Da
|
|||
|
||||
Sie können den *Pfadoperation-Dekorator*-Parameter `response_model_exclude_unset=True` setzen:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
||||
```
|
||||
```Python hl_lines="22"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial004_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial004.py!}
|
||||
```
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="24"
|
||||
{!> ../../../docs_src/response_model/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Die Defaultwerte werden dann nicht in der Response enthalten sein, sondern nur die tatsächlich gesetzten Werte.
|
||||
|
||||
|
|
@ -377,21 +445,30 @@ Wenn Sie also den Artikel mit der ID `foo` bei der *Pfadoperation* anfragen, wir
|
|||
}
|
||||
```
|
||||
|
||||
!!! info
|
||||
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
|
||||
/// info
|
||||
|
||||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
In Pydantic v1 hieß diese Methode `.dict()`, in Pydantic v2 wurde sie deprecated (aber immer noch unterstützt) und in `.model_dump()` umbenannt.
|
||||
|
||||
!!! info
|
||||
FastAPI verwendet `.dict()` von Pydantic Modellen, <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">mit dessen `exclude_unset`-Parameter</a>, um das zu erreichen.
|
||||
Die Beispiele hier verwenden `.dict()` für die Kompatibilität mit Pydantic v1, Sie sollten jedoch stattdessen `.model_dump()` verwenden, wenn Sie Pydantic v2 verwenden können.
|
||||
|
||||
!!! info
|
||||
Sie können auch:
|
||||
///
|
||||
|
||||
* `response_model_exclude_defaults=True`
|
||||
* `response_model_exclude_none=True`
|
||||
/// info
|
||||
|
||||
verwenden, wie in der <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">Pydantic Dokumentation</a> für `exclude_defaults` und `exclude_none` beschrieben.
|
||||
FastAPI verwendet `.dict()` von Pydantic Modellen, <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">mit dessen `exclude_unset`-Parameter</a>, um das zu erreichen.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
Sie können auch:
|
||||
|
||||
* `response_model_exclude_defaults=True`
|
||||
* `response_model_exclude_none=True`
|
||||
|
||||
verwenden, wie in der <a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">Pydantic Dokumentation</a> für `exclude_defaults` und `exclude_none` beschrieben.
|
||||
|
||||
///
|
||||
|
||||
#### Daten mit Werten für Felder mit Defaultwerten
|
||||
|
||||
|
|
@ -426,10 +503,13 @@ dann ist FastAPI klug genug (tatsächlich ist Pydantic klug genug) zu erkennen,
|
|||
|
||||
Diese Felder werden also in der JSON-Response enthalten sein.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass Defaultwerte alles Mögliche sein können, nicht nur `None`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie können eine Liste (`[]`), ein `float` `10.5`, usw. sein.
|
||||
Beachten Sie, dass Defaultwerte alles Mögliche sein können, nicht nur `None`.
|
||||
|
||||
Sie können eine Liste (`[]`), ein `float` `10.5`, usw. sein.
|
||||
|
||||
///
|
||||
|
||||
### `response_model_include` und `response_model_exclude`
|
||||
|
||||
|
|
@ -439,45 +519,59 @@ Diese nehmen ein `set` von `str`s entgegen, welches Namen von Attributen sind, d
|
|||
|
||||
Das kann als schnelle Abkürzung verwendet werden, wenn Sie nur ein Pydantic-Modell haben und ein paar Daten von der Ausgabe ausschließen wollen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Es wird dennoch empfohlen, dass Sie die Ideen von oben verwenden, also mehrere Klassen statt dieser Parameter.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Der Grund ist, dass das das generierte JSON-Schema in der OpenAPI ihrer Anwendung (und deren Dokumentation) dennoch das komplette Modell abbildet, selbst wenn Sie `response_model_include` oder `response_model_exclude` verwenden, um einige Attribute auszuschließen.
|
||||
Es wird dennoch empfohlen, dass Sie die Ideen von oben verwenden, also mehrere Klassen statt dieser Parameter.
|
||||
|
||||
Das trifft auch auf `response_model_by_alias` zu, welches ähnlich funktioniert.
|
||||
Der Grund ist, dass das das generierte JSON-Schema in der OpenAPI ihrer Anwendung (und deren Dokumentation) dennoch das komplette Modell abbildet, selbst wenn Sie `response_model_include` oder `response_model_exclude` verwenden, um einige Attribute auszuschließen.
|
||||
|
||||
=== "Python 3.10+"
|
||||
Das trifft auch auf `response_model_by_alias` zu, welches ähnlich funktioniert.
|
||||
|
||||
```Python hl_lines="29 35"
|
||||
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.8+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="31 37"
|
||||
{!> ../../../docs_src/response_model/tutorial005.py!}
|
||||
```
|
||||
```Python hl_lines="29 35"
|
||||
{!> ../../../docs_src/response_model/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die Syntax `{"name", "description"}` erzeugt ein `set` mit diesen zwei Werten.
|
||||
////
|
||||
|
||||
Äquivalent zu `set(["name", "description"])`.
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="31 37"
|
||||
{!> ../../../docs_src/response_model/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Die Syntax `{"name", "description"}` erzeugt ein `set` mit diesen zwei Werten.
|
||||
|
||||
Äquivalent zu `set(["name", "description"])`.
|
||||
|
||||
///
|
||||
|
||||
#### `list`en statt `set`s verwenden
|
||||
|
||||
Wenn Sie vergessen, ein `set` zu verwenden, und stattdessen eine `list`e oder ein `tuple` übergeben, wird FastAPI die dennoch in ein `set` konvertieren, und es wird korrekt funktionieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="29 35"
|
||||
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
|
||||
```
|
||||
```Python hl_lines="29 35"
|
||||
{!> ../../../docs_src/response_model/tutorial006_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="31 37"
|
||||
{!> ../../../docs_src/response_model/tutorial006.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="31 37"
|
||||
{!> ../../../docs_src/response_model/tutorial006.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -12,13 +12,19 @@ So wie ein Responsemodell, können Sie auch einen HTTP-Statuscode für die Respo
|
|||
{!../../../docs_src/response_status_code/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Beachten Sie, dass `status_code` ein Parameter der „Dekorator“-Methode ist (`get`, `post`, usw.). Nicht der *Pfadoperation-Funktion*, so wie die anderen Parameter und der Body.
|
||||
|
||||
///
|
||||
|
||||
Dem `status_code`-Parameter wird eine Zahl mit dem HTTP-Statuscode übergeben.
|
||||
|
||||
!!! info
|
||||
Alternativ kann `status_code` auch ein `IntEnum` erhalten, so wie Pythons <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
|
||||
/// info
|
||||
|
||||
Alternativ kann `status_code` auch ein `IntEnum` erhalten, so wie Pythons <a href="https://docs.python.org/3/library/http.html#http.HTTPStatus" class="external-link" target="_blank">`http.HTTPStatus`</a>.
|
||||
|
||||
///
|
||||
|
||||
Das wird:
|
||||
|
||||
|
|
@ -27,15 +33,21 @@ Das wird:
|
|||
|
||||
<img src="/img/tutorial/response-status-code/image01.png">
|
||||
|
||||
!!! note "Hinweis"
|
||||
Einige Responsecodes (siehe nächster Abschnitt) kennzeichnen, dass die Response keinen Body hat.
|
||||
/// note | "Hinweis"
|
||||
|
||||
FastAPI versteht das und wird in der OpenAPI-Dokumentation anzeigen, dass es keinen Responsebody gibt.
|
||||
Einige Responsecodes (siehe nächster Abschnitt) kennzeichnen, dass die Response keinen Body hat.
|
||||
|
||||
FastAPI versteht das und wird in der OpenAPI-Dokumentation anzeigen, dass es keinen Responsebody gibt.
|
||||
|
||||
///
|
||||
|
||||
## Über HTTP-Statuscodes
|
||||
|
||||
!!! note "Hinweis"
|
||||
Wenn Sie bereits wissen, was HTTP-Statuscodes sind, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Wenn Sie bereits wissen, was HTTP-Statuscodes sind, überspringen Sie dieses Kapitel und fahren Sie mit dem nächsten fort.
|
||||
|
||||
///
|
||||
|
||||
In HTTP senden Sie als Teil der Response einen aus drei Ziffern bestehenden numerischen Statuscode.
|
||||
|
||||
|
|
@ -54,8 +66,11 @@ Kurz:
|
|||
* Für allgemeine Fehler beim Client können Sie einfach `400` verwenden.
|
||||
* `500` und darüber stehen für Server-Fehler. Diese verwenden Sie fast nie direkt. Wenn etwas an irgendeiner Stelle in Ihrem Anwendungscode oder im Server schiefläuft, wird automatisch einer dieser Fehler-Statuscodes zurückgegeben.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr> Dokumentation über HTTP-Statuscodes</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Um mehr über Statuscodes zu lernen, und welcher wofür verwendet wird, lesen Sie die <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network – Mozilla-Entwickler-Netzwerk">MDN</abbr> Dokumentation über HTTP-Statuscodes</a>.
|
||||
|
||||
///
|
||||
|
||||
## Abkürzung, um die Namen zu erinnern
|
||||
|
||||
|
|
@ -79,10 +94,13 @@ Diese sind nur eine Annehmlichkeit und enthalten dieselbe Nummer, aber auf diese
|
|||
|
||||
<img src="/img/tutorial/response-status-code/image02.png">
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie können auch `from starlette import status` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
|
||||
Sie können auch `from starlette import status` verwenden.
|
||||
|
||||
**FastAPI** bietet dieselben `starlette.status`-Codes auch via `fastapi.status` an, als Annehmlichkeit für Sie, den Entwickler. Sie kommen aber direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
## Den Defaultwert ändern
|
||||
|
||||
|
|
|
|||
|
|
@ -8,71 +8,93 @@ Hier sind mehrere Möglichkeiten, das zu tun.
|
|||
|
||||
Sie können `examples` („Beispiele“) für ein Pydantic-Modell deklarieren, welche dem generierten JSON-Schema hinzugefügt werden.
|
||||
|
||||
=== "Python 3.10+ Pydantic v2"
|
||||
//// tab | Python 3.10+ Pydantic v2
|
||||
|
||||
```Python hl_lines="13-24"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
|
||||
```
|
||||
```Python hl_lines="13-24"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.10+ Pydantic v1"
|
||||
////
|
||||
|
||||
```Python hl_lines="13-23"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_py310_pv1.py!}
|
||||
```
|
||||
//// tab | Python 3.10+ Pydantic v1
|
||||
|
||||
=== "Python 3.8+ Pydantic v2"
|
||||
```Python hl_lines="13-23"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_py310_pv1.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="15-26"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ Pydantic v1"
|
||||
//// tab | Python 3.8+ Pydantic v2
|
||||
|
||||
```Python hl_lines="15-25"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_pv1.py!}
|
||||
```
|
||||
```Python hl_lines="15-26"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ Pydantic v1
|
||||
|
||||
```Python hl_lines="15-25"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial001_pv1.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Diese zusätzlichen Informationen werden unverändert zum für dieses Modell ausgegebenen **JSON-Schema** hinzugefügt und in der API-Dokumentation verwendet.
|
||||
|
||||
=== "Pydantic v2"
|
||||
//// tab | Pydantic v2
|
||||
|
||||
In Pydantic Version 2 würden Sie das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Pydantic-Dokumentation: Configuration</a>.
|
||||
In Pydantic Version 2 würden Sie das Attribut `model_config` verwenden, das ein `dict` akzeptiert, wie beschrieben in <a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Pydantic-Dokumentation: Configuration</a>.
|
||||
|
||||
Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
|
||||
Sie können `json_schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
|
||||
|
||||
=== "Pydantic v1"
|
||||
////
|
||||
|
||||
In Pydantic Version 1 würden Sie eine interne Klasse `Config` und `schema_extra` verwenden, wie beschrieben in <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic-Dokumentation: Schema customization</a>.
|
||||
//// tab | Pydantic v1
|
||||
|
||||
Sie können `schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
|
||||
In Pydantic Version 1 würden Sie eine interne Klasse `Config` und `schema_extra` verwenden, wie beschrieben in <a href="https://docs.pydantic.dev/1.10/usage/schema/#schema-customization" class="external-link" target="_blank">Pydantic-Dokumentation: Schema customization</a>.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Mit derselben Technik können Sie das JSON-Schema erweitern und Ihre eigenen benutzerdefinierten Zusatzinformationen hinzufügen.
|
||||
Sie können `schema_extra` setzen, mit einem `dict`, das alle zusätzlichen Daten enthält, die im generierten JSON-Schema angezeigt werden sollen, einschließlich `examples`.
|
||||
|
||||
Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benutzeroberfläche usw. hinzuzufügen.
|
||||
////
|
||||
|
||||
!!! info
|
||||
OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr> und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓
|
||||
Mit derselben Technik können Sie das JSON-Schema erweitern und Ihre eigenen benutzerdefinierten Zusatzinformationen hinzufügen.
|
||||
|
||||
Mehr erfahren Sie am Ende dieser Seite.
|
||||
Sie könnten das beispielsweise verwenden, um Metadaten für eine Frontend-Benutzeroberfläche usw. hinzuzufügen.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
OpenAPI 3.1.0 (verwendet seit FastAPI 0.99.0) hat Unterstützung für `examples` hinzugefügt, was Teil des **JSON Schema** Standards ist.
|
||||
|
||||
Zuvor unterstützte es nur das Schlüsselwort `example` mit einem einzigen Beispiel. Dieses wird weiterhin von OpenAPI 3.1.0 unterstützt, ist jedoch <abbr title="deprecated – obsolet, veraltet: Es soll nicht mehr verwendet werden">deprecated</abbr> und nicht Teil des JSON Schema Standards. Wir empfehlen Ihnen daher, von `example` nach `examples` zu migrieren. 🤓
|
||||
|
||||
Mehr erfahren Sie am Ende dieser Seite.
|
||||
|
||||
///
|
||||
|
||||
## Zusätzliche Argumente für `Field`
|
||||
|
||||
Wenn Sie `Field()` mit Pydantic-Modellen verwenden, können Sie ebenfalls zusätzliche `examples` deklarieren:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="2 8-11"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
|
||||
```
|
||||
```Python hl_lines="2 8-11"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="4 10-13"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
```Python hl_lines="4 10-13"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## `examples` im JSON-Schema – OpenAPI
|
||||
|
||||
|
|
@ -92,41 +114,57 @@ können Sie auch eine Gruppe von `examples` mit zusätzlichen Informationen dekl
|
|||
|
||||
Hier übergeben wir `examples`, welches ein einzelnes Beispiel für die in `Body()` erwarteten Daten enthält:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="22-29"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="22-29"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="22-29"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="22-29"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="23-30"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="23-30"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="18-25"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="20-27"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="18-25"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="20-27"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Beispiel in der Dokumentations-Benutzeroberfläche
|
||||
|
||||
|
|
@ -138,41 +176,57 @@ Mit jeder der oben genannten Methoden würde es in `/docs` so aussehen:
|
|||
|
||||
Sie können natürlich auch mehrere `examples` übergeben:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="23-38"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="23-38"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="23-38"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="23-38"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="24-39"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="24-39"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="19-34"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="21-36"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19-34"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="21-36"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Wenn Sie das tun, werden die Beispiele Teil des internen **JSON-Schemas** für diese Body-Daten.
|
||||
|
||||
|
|
@ -213,41 +267,57 @@ Jedes spezifische Beispiel-`dict` in den `examples` kann Folgendes enthalten:
|
|||
|
||||
Sie können es so verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="23-49"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="23-49"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="23-49"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="23-49"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="24-50"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="24-50"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="19-45"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="21-47"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19-45"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="21-47"
|
||||
{!> ../../../docs_src/schema_extra_example/tutorial005.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### OpenAPI-Beispiele in der Dokumentations-Benutzeroberfläche
|
||||
|
||||
|
|
@ -257,17 +327,23 @@ Wenn `openapi_examples` zu `Body()` hinzugefügt wird, würde `/docs` so aussehe
|
|||
|
||||
## Technische Details
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie bereits **FastAPI** Version **0.99.0 oder höher** verwenden, können Sie diese Details wahrscheinlich **überspringen**.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie sind für ältere Versionen relevanter, bevor OpenAPI 3.1.0 verfügbar war.
|
||||
Wenn Sie bereits **FastAPI** Version **0.99.0 oder höher** verwenden, können Sie diese Details wahrscheinlich **überspringen**.
|
||||
|
||||
Sie können dies als eine kurze **Geschichtsstunde** zu OpenAPI und JSON Schema betrachten. 🤓
|
||||
Sie sind für ältere Versionen relevanter, bevor OpenAPI 3.1.0 verfügbar war.
|
||||
|
||||
!!! warning "Achtung"
|
||||
Dies sind sehr technische Details zu den Standards **JSON Schema** und **OpenAPI**.
|
||||
Sie können dies als eine kurze **Geschichtsstunde** zu OpenAPI und JSON Schema betrachten. 🤓
|
||||
|
||||
Wenn die oben genannten Ideen bereits für Sie funktionieren, reicht das möglicherweise aus und Sie benötigen diese Details wahrscheinlich nicht, überspringen Sie sie gerne.
|
||||
///
|
||||
|
||||
/// warning | "Achtung"
|
||||
|
||||
Dies sind sehr technische Details zu den Standards **JSON Schema** und **OpenAPI**.
|
||||
|
||||
Wenn die oben genannten Ideen bereits für Sie funktionieren, reicht das möglicherweise aus und Sie benötigen diese Details wahrscheinlich nicht, überspringen Sie sie gerne.
|
||||
|
||||
///
|
||||
|
||||
Vor OpenAPI 3.1.0 verwendete OpenAPI eine ältere und modifizierte Version von **JSON Schema**.
|
||||
|
||||
|
|
@ -285,8 +361,11 @@ OpenAPI fügte auch die Felder `example` und `examples` zu anderen Teilen der Sp
|
|||
* `File()`
|
||||
* `Form()`
|
||||
|
||||
!!! info
|
||||
Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`.
|
||||
/// info
|
||||
|
||||
Dieser alte, OpenAPI-spezifische `examples`-Parameter heißt seit FastAPI `0.103.0` jetzt `openapi_examples`.
|
||||
|
||||
///
|
||||
|
||||
### JSON Schemas Feld `examples`
|
||||
|
||||
|
|
@ -298,10 +377,13 @@ Und jetzt hat dieses neue `examples`-Feld Vorrang vor dem alten (und benutzerdef
|
|||
|
||||
Dieses neue `examples`-Feld in JSON Schema ist **nur eine `list`e** von Beispielen, kein Dict mit zusätzlichen Metadaten wie an den anderen Stellen in OpenAPI (oben beschrieben).
|
||||
|
||||
!!! info
|
||||
Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉).
|
||||
/// info
|
||||
|
||||
Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Versionen von OpenAPI vor 3.1.0.
|
||||
Selbst, nachdem OpenAPI 3.1.0 veröffentlicht wurde, mit dieser neuen, einfacheren Integration mit JSON Schema, unterstützte Swagger UI, das Tool, das die automatische Dokumentation bereitstellt, eine Zeit lang OpenAPI 3.1.0 nicht (das tut es seit Version 5.0.0 🎉).
|
||||
|
||||
Aus diesem Grund verwendeten Versionen von FastAPI vor 0.99.0 immer noch Versionen von OpenAPI vor 3.1.0.
|
||||
|
||||
///
|
||||
|
||||
### Pydantic- und FastAPI-`examples`
|
||||
|
||||
|
|
|
|||
|
|
@ -20,35 +20,47 @@ Lassen Sie uns zunächst einfach den Code verwenden und sehen, wie er funktionie
|
|||
|
||||
Kopieren Sie das Beispiel in eine Datei `main.py`:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Ausführen
|
||||
|
||||
!!! info
|
||||
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
/// info
|
||||
|
||||
Z. B. `pip install python-multipart`.
|
||||
Um hochgeladene Dateien zu empfangen, installieren Sie zuerst <a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>.
|
||||
|
||||
Das, weil **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet.
|
||||
Z. B. `pip install python-multipart`.
|
||||
|
||||
Das, weil **OAuth2** „Formulardaten“ zum Senden von `username` und `password` verwendet.
|
||||
|
||||
///
|
||||
|
||||
Führen Sie das Beispiel aus mit:
|
||||
|
||||
|
|
@ -70,17 +82,23 @@ Sie werden etwa Folgendes sehen:
|
|||
|
||||
<img src="/img/tutorial/security/image01.png">
|
||||
|
||||
!!! check "Authorize-Button!"
|
||||
Sie haben bereits einen glänzenden, neuen „Authorize“-Button.
|
||||
/// check | "Authorize-Button!"
|
||||
|
||||
Und Ihre *Pfadoperation* hat in der oberen rechten Ecke ein kleines Schloss, auf das Sie klicken können.
|
||||
Sie haben bereits einen glänzenden, neuen „Authorize“-Button.
|
||||
|
||||
Und Ihre *Pfadoperation* hat in der oberen rechten Ecke ein kleines Schloss, auf das Sie klicken können.
|
||||
|
||||
///
|
||||
|
||||
Und wenn Sie darauf klicken, erhalten Sie ein kleines Anmeldeformular zur Eingabe eines `username` und `password` (und anderer optionaler Felder):
|
||||
|
||||
<img src="/img/tutorial/security/image02.png">
|
||||
|
||||
!!! note "Hinweis"
|
||||
Es spielt keine Rolle, was Sie in das Formular eingeben, es wird noch nicht funktionieren. Wir kommen dahin.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Es spielt keine Rolle, was Sie in das Formular eingeben, es wird noch nicht funktionieren. Wir kommen dahin.
|
||||
|
||||
///
|
||||
|
||||
Dies ist natürlich nicht das Frontend für die Endbenutzer, aber es ist ein großartiges automatisches Tool, um Ihre gesamte API interaktiv zu dokumentieren.
|
||||
|
||||
|
|
@ -122,53 +140,71 @@ Betrachten wir es also aus dieser vereinfachten Sicht:
|
|||
|
||||
In diesem Beispiel verwenden wir **OAuth2** mit dem **Password**-Flow und einem **Bearer**-Token. Wir machen das mit der Klasse `OAuth2PasswordBearer`.
|
||||
|
||||
!!! info
|
||||
Ein „Bearer“-Token ist nicht die einzige Option.
|
||||
/// info
|
||||
|
||||
Aber es ist die beste für unseren Anwendungsfall.
|
||||
Ein „Bearer“-Token ist nicht die einzige Option.
|
||||
|
||||
Und es ist wahrscheinlich auch für die meisten anderen Anwendungsfälle die beste, es sei denn, Sie sind ein OAuth2-Experte und wissen genau, warum es eine andere Option gibt, die Ihren Anforderungen besser entspricht.
|
||||
Aber es ist die beste für unseren Anwendungsfall.
|
||||
|
||||
In dem Fall gibt Ihnen **FastAPI** ebenfalls die Tools, die Sie zum Erstellen brauchen.
|
||||
Und es ist wahrscheinlich auch für die meisten anderen Anwendungsfälle die beste, es sei denn, Sie sind ein OAuth2-Experte und wissen genau, warum es eine andere Option gibt, die Ihren Anforderungen besser entspricht.
|
||||
|
||||
In dem Fall gibt Ihnen **FastAPI** ebenfalls die Tools, die Sie zum Erstellen brauchen.
|
||||
|
||||
///
|
||||
|
||||
Wenn wir eine Instanz der Klasse `OAuth2PasswordBearer` erstellen, übergeben wir den Parameter `tokenUrl`. Dieser Parameter enthält die URL, die der Client (das Frontend, das im Browser des Benutzers ausgeführt wird) verwendet, wenn er den `username` und das `password` sendet, um einen Token zu erhalten.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="8"
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="7"
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Hier bezieht sich `tokenUrl="token"` auf eine relative URL `token`, die wir noch nicht erstellt haben. Da es sich um eine relative URL handelt, entspricht sie `./token`.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Da wir eine relative URL verwenden, würde sich das, wenn sich Ihre API unter `https://example.com/` befindet, auf `https://example.com/token` beziehen. Wenn sich Ihre API jedoch unter `https://example.com/api/v1/` befände, würde es sich auf `https://example.com/api/v1/token` beziehen.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
Die Verwendung einer relativen URL ist wichtig, um sicherzustellen, dass Ihre Anwendung auch in einem fortgeschrittenen Anwendungsfall, wie [hinter einem Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}, weiterhin funktioniert.
|
||||
///
|
||||
|
||||
```Python hl_lines="6"
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Hier bezieht sich `tokenUrl="token"` auf eine relative URL `token`, die wir noch nicht erstellt haben. Da es sich um eine relative URL handelt, entspricht sie `./token`.
|
||||
|
||||
Da wir eine relative URL verwenden, würde sich das, wenn sich Ihre API unter `https://example.com/` befindet, auf `https://example.com/token` beziehen. Wenn sich Ihre API jedoch unter `https://example.com/api/v1/` befände, würde es sich auf `https://example.com/api/v1/token` beziehen.
|
||||
|
||||
Die Verwendung einer relativen URL ist wichtig, um sicherzustellen, dass Ihre Anwendung auch in einem fortgeschrittenen Anwendungsfall, wie [hinter einem Proxy](../../advanced/behind-a-proxy.md){.internal-link target=_blank}, weiterhin funktioniert.
|
||||
|
||||
///
|
||||
|
||||
Dieser Parameter erstellt nicht diesen Endpunkt / diese *Pfadoperation*, sondern deklariert, dass die URL `/token` diejenige sein wird, die der Client verwenden soll, um den Token abzurufen. Diese Information wird in OpenAPI und dann in den interaktiven API-Dokumentationssystemen verwendet.
|
||||
|
||||
Wir werden demnächst auch die eigentliche Pfadoperation erstellen.
|
||||
|
||||
!!! info
|
||||
Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`.
|
||||
/// info
|
||||
|
||||
Das liegt daran, dass FastAPI denselben Namen wie in der OpenAPI-Spezifikation verwendet. Sodass Sie, wenn Sie mehr über eines dieser Sicherheitsschemas herausfinden möchten, den Namen einfach kopieren und einfügen können, um weitere Informationen darüber zu erhalten.
|
||||
Wenn Sie ein sehr strenger „Pythonista“ sind, missfällt Ihnen möglicherweise die Schreibweise des Parameternamens `tokenUrl` anstelle von `token_url`.
|
||||
|
||||
Das liegt daran, dass FastAPI denselben Namen wie in der OpenAPI-Spezifikation verwendet. Sodass Sie, wenn Sie mehr über eines dieser Sicherheitsschemas herausfinden möchten, den Namen einfach kopieren und einfügen können, um weitere Informationen darüber zu erhalten.
|
||||
|
||||
///
|
||||
|
||||
Die Variable `oauth2_scheme` ist eine Instanz von `OAuth2PasswordBearer`, aber auch ein „Callable“.
|
||||
|
||||
|
|
@ -184,35 +220,47 @@ Es kann also mit `Depends` verwendet werden.
|
|||
|
||||
Jetzt können Sie dieses `oauth2_scheme` als Abhängigkeit `Depends` übergeben.
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Diese Abhängigkeit stellt einen `str` bereit, der dem Parameter `token` der *Pfadoperation-Funktion* zugewiesen wird.
|
||||
|
||||
**FastAPI** weiß, dass es diese Abhängigkeit verwenden kann, um ein „Sicherheitsschema“ im OpenAPI-Schema (und der automatischen API-Dokumentation) zu definieren.
|
||||
|
||||
!!! info "Technische Details"
|
||||
**FastAPI** weiß, dass es die Klasse `OAuth2PasswordBearer` (deklariert in einer Abhängigkeit) verwenden kann, um das Sicherheitsschema in OpenAPI zu definieren, da es von `fastapi.security.oauth2.OAuth2` erbt, das wiederum von `fastapi.security.base.SecurityBase` erbt.
|
||||
/// info | "Technische Details"
|
||||
|
||||
Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische API-Dokumentation), erben von `SecurityBase`, so weiß **FastAPI**, wie es sie in OpenAPI integrieren muss.
|
||||
**FastAPI** weiß, dass es die Klasse `OAuth2PasswordBearer` (deklariert in einer Abhängigkeit) verwenden kann, um das Sicherheitsschema in OpenAPI zu definieren, da es von `fastapi.security.oauth2.OAuth2` erbt, das wiederum von `fastapi.security.base.SecurityBase` erbt.
|
||||
|
||||
Alle Sicherheits-Werkzeuge, die in OpenAPI integriert sind (und die automatische API-Dokumentation), erben von `SecurityBase`, so weiß **FastAPI**, wie es sie in OpenAPI integrieren muss.
|
||||
|
||||
///
|
||||
|
||||
## Was es macht
|
||||
|
||||
|
|
|
|||
|
|
@ -2,26 +2,35 @@
|
|||
|
||||
Im vorherigen Kapitel hat das Sicherheitssystem (das auf dem Dependency Injection System basiert) der *Pfadoperation-Funktion* einen `token` vom Typ `str` überreicht:
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="12"
|
||||
{!> ../../../docs_src/security/tutorial001_an_py39.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="11"
|
||||
{!> ../../../docs_src/security/tutorial001_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="10"
|
||||
{!> ../../../docs_src/security/tutorial001.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Aber das ist immer noch nicht so nützlich.
|
||||
|
||||
|
|
@ -33,41 +42,57 @@ Erstellen wir zunächst ein Pydantic-Benutzermodell.
|
|||
|
||||
So wie wir Pydantic zum Deklarieren von Bodys verwenden, können wir es auch überall sonst verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="5 12-16"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="5 12-16"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="5 12-16"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="5 12-16"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="5 13-17"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="5 13-17"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3 10-14"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="5 12-16"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="3 10-14"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="5 12-16"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Eine `get_current_user`-Abhängigkeit erstellen
|
||||
|
||||
|
|
@ -79,135 +104,189 @@ Erinnern Sie sich, dass Abhängigkeiten Unterabhängigkeiten haben können?
|
|||
|
||||
So wie wir es zuvor in der *Pfadoperation* direkt gemacht haben, erhält unsere neue Abhängigkeit `get_current_user` von der Unterabhängigkeit `oauth2_scheme` einen `token` vom Typ `str`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="26"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="26"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="23"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="25"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Den Benutzer holen
|
||||
|
||||
`get_current_user` wird eine von uns erstellte (gefakte) Hilfsfunktion verwenden, welche einen Token vom Typ `str` entgegennimmt und unser Pydantic-`User`-Modell zurückgibt:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="19-22 26-27"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="19-22 26-27"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="19-22 26-27"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="19-22 26-27"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="20-23 27-28"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="20-23 27-28"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="17-20 24-25"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="19-22 26-27"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="17-20 24-25"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="19-22 26-27"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Den aktuellen Benutzer einfügen
|
||||
|
||||
Und jetzt können wir wiederum `Depends` mit unserem `get_current_user` in der *Pfadoperation* verwenden:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="31"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="31"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="31"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="31"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="32"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="32"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="29"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="31"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="29"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="31"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
Beachten Sie, dass wir als Typ von `current_user` das Pydantic-Modell `User` deklarieren.
|
||||
|
||||
Das wird uns innerhalb der Funktion bei Codevervollständigung und Typprüfungen helfen.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt.
|
||||
Sie erinnern sich vielleicht, dass Requestbodys ebenfalls mit Pydantic-Modellen deklariert werden.
|
||||
|
||||
!!! check
|
||||
Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben.
|
||||
Weil Sie `Depends` verwenden, wird **FastAPI** hier aber nicht verwirrt.
|
||||
|
||||
Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen Typ von Daten zurückgeben kann.
|
||||
///
|
||||
|
||||
/// check
|
||||
|
||||
Die Art und Weise, wie dieses System von Abhängigkeiten konzipiert ist, ermöglicht es uns, verschiedene Abhängigkeiten (verschiedene „Dependables“) zu haben, die alle ein `User`-Modell zurückgeben.
|
||||
|
||||
Wir sind nicht darauf beschränkt, nur eine Abhängigkeit zu haben, die diesen Typ von Daten zurückgeben kann.
|
||||
|
||||
///
|
||||
|
||||
## Andere Modelle
|
||||
|
||||
|
|
@ -241,41 +320,57 @@ Und alle (oder beliebige Teile davon) können Vorteil ziehen aus der Wiederverwe
|
|||
|
||||
Und alle diese Tausenden von *Pfadoperationen* können nur drei Zeilen lang sein:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="30-32"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="30-32"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="30-32"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="30-32"
|
||||
{!> ../../../docs_src/security/tutorial002_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="31-33"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="31-33"
|
||||
{!> ../../../docs_src/security/tutorial002_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="28-30"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="30-32"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="28-30"
|
||||
{!> ../../../docs_src/security/tutorial002_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="30-32"
|
||||
{!> ../../../docs_src/security/tutorial002.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Zusammenfassung
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,11 @@ Heutzutage ist es nicht sehr populär und wird kaum verwendet.
|
|||
|
||||
OAuth2 spezifiziert nicht, wie die Kommunikation verschlüsselt werden soll, sondern erwartet, dass Ihre Anwendung mit HTTPS bereitgestellt wird.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traefik und Let's Encrypt kostenlos einrichten.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Im Abschnitt über **Deployment** erfahren Sie, wie Sie HTTPS mithilfe von Traefik und Let's Encrypt kostenlos einrichten.
|
||||
|
||||
///
|
||||
|
||||
## OpenID Connect
|
||||
|
||||
|
|
@ -87,10 +89,13 @@ OpenAPI definiert die folgenden Sicherheitsschemas:
|
|||
* Diese automatische Erkennung ist es, die in der OpenID Connect Spezifikation definiert ist.
|
||||
|
||||
|
||||
!!! tip "Tipp"
|
||||
Auch die Integration anderer Authentifizierungs-/Autorisierungsanbieter wie Google, Facebook, Twitter, GitHub, usw. ist möglich und relativ einfach.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsanbieter wie solche aufzubauen, aber **FastAPI** reicht Ihnen die Tools, das einfach zu erledigen, während Ihnen die schwere Arbeit abgenommen wird.
|
||||
Auch die Integration anderer Authentifizierungs-/Autorisierungsanbieter wie Google, Facebook, Twitter, GitHub, usw. ist möglich und relativ einfach.
|
||||
|
||||
Das komplexeste Problem besteht darin, einen Authentifizierungs-/Autorisierungsanbieter wie solche aufzubauen, aber **FastAPI** reicht Ihnen die Tools, das einfach zu erledigen, während Ihnen die schwere Arbeit abgenommen wird.
|
||||
|
||||
///
|
||||
|
||||
## **FastAPI** Tools
|
||||
|
||||
|
|
|
|||
|
|
@ -44,10 +44,13 @@ $ pip install "python-jose[cryptography]"
|
|||
|
||||
Hier verwenden wir das empfohlene: <a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Dieses Tutorial verwendete zuvor <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Es wurde jedoch aktualisiert, stattdessen python-jose zu verwenden, da dieses alle Funktionen von PyJWT sowie einige Extras bietet, die Sie später möglicherweise benötigen, wenn Sie Integrationen mit anderen Tools erstellen.
|
||||
Dieses Tutorial verwendete zuvor <a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>.
|
||||
|
||||
Es wurde jedoch aktualisiert, stattdessen python-jose zu verwenden, da dieses alle Funktionen von PyJWT sowie einige Extras bietet, die Sie später möglicherweise benötigen, wenn Sie Integrationen mit anderen Tools erstellen.
|
||||
|
||||
///
|
||||
|
||||
## Passwort-Hashing
|
||||
|
||||
|
|
@ -83,12 +86,15 @@ $ pip install "passlib[bcrypt]"
|
|||
|
||||
</div>
|
||||
|
||||
!!! tip "Tipp"
|
||||
Mit `passlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheit-Plugin, oder vielen anderen erstellt wurden.
|
||||
/// tip | "Tipp"
|
||||
|
||||
So könnten Sie beispielsweise die gleichen Daten aus einer Django-Anwendung in einer Datenbank mit einer FastAPI-Anwendung teilen. Oder schrittweise eine Django-Anwendung migrieren, während Sie dieselbe Datenbank verwenden.
|
||||
Mit `passlib` können Sie sogar konfigurieren, Passwörter zu lesen, die von **Django**, einem **Flask**-Sicherheit-Plugin, oder vielen anderen erstellt wurden.
|
||||
|
||||
Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ihre **FastAPI**-Anwendung anmelden.
|
||||
So könnten Sie beispielsweise die gleichen Daten aus einer Django-Anwendung in einer Datenbank mit einer FastAPI-Anwendung teilen. Oder schrittweise eine Django-Anwendung migrieren, während Sie dieselbe Datenbank verwenden.
|
||||
|
||||
Und Ihre Benutzer könnten sich gleichzeitig über Ihre Django-Anwendung oder Ihre **FastAPI**-Anwendung anmelden.
|
||||
|
||||
///
|
||||
|
||||
## Die Passwörter hashen und überprüfen
|
||||
|
||||
|
|
@ -96,12 +102,15 @@ Importieren Sie die benötigten Tools aus `passlib`.
|
|||
|
||||
Erstellen Sie einen PassLib-„Kontext“. Der wird für das Hashen und Verifizieren von Passwörtern verwendet.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Sie könnten ihn beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Bcrypt zu hashen.
|
||||
Der PassLib-Kontext kann auch andere Hashing-Algorithmen verwenden, einschließlich deprecateter Alter, um etwa nur eine Verifizierung usw. zu ermöglichen.
|
||||
|
||||
Und mit allen gleichzeitig kompatibel sein.
|
||||
Sie könnten ihn beispielsweise verwenden, um von einem anderen System (wie Django) generierte Passwörter zu lesen und zu verifizieren, aber alle neuen Passwörter mit einem anderen Algorithmus wie Bcrypt zu hashen.
|
||||
|
||||
Und mit allen gleichzeitig kompatibel sein.
|
||||
|
||||
///
|
||||
|
||||
Erstellen Sie eine Hilfsfunktion, um ein vom Benutzer stammendes Passwort zu hashen.
|
||||
|
||||
|
|
@ -109,44 +118,63 @@ Und eine weitere, um zu überprüfen, ob ein empfangenes Passwort mit dem gespei
|
|||
|
||||
Und noch eine, um einen Benutzer zu authentifizieren und zurückzugeben.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="7 49 56-57 60-61 70-76"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="7 49 56-57 60-61 70-76"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="6 47 54-55 58-59 68-74"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! note "Hinweis"
|
||||
Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
|
||||
///
|
||||
|
||||
```Python hl_lines="6 47 54-55 58-59 68-74"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="7 48 55-56 59-60 69-75"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// note | "Hinweis"
|
||||
|
||||
Wenn Sie sich die neue (gefakte) Datenbank `fake_users_db` anschauen, sehen Sie, wie das gehashte Passwort jetzt aussieht: `"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`.
|
||||
|
||||
///
|
||||
|
||||
## JWT-Token verarbeiten
|
||||
|
||||
|
|
@ -176,41 +204,57 @@ Definieren Sie ein Pydantic-Modell, das im Token-Endpunkt für die Response verw
|
|||
|
||||
Erstellen Sie eine Hilfsfunktion, um einen neuen Zugriffstoken zu generieren.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="6 13-15 29-31 79-87"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="6 13-15 29-31 79-87"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="5 11-13 27-29 77-85"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="5 11-13 27-29 77-85"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="6 12-14 28-30 78-86"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Die Abhängigkeiten aktualisieren
|
||||
|
||||
|
|
@ -220,41 +264,57 @@ Dekodieren Sie den empfangenen Token, validieren Sie ihn und geben Sie den aktue
|
|||
|
||||
Wenn der Token ungültig ist, geben Sie sofort einen HTTP-Fehler zurück.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="89-106"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="89-106"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="89-106"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="89-106"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="90-107"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="90-107"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="88-105"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="89-106"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="88-105"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="89-106"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
## Die *Pfadoperation* `/token` aktualisieren
|
||||
|
||||
|
|
@ -262,41 +322,57 @@ Erstellen Sie ein <abbr title="Zeitdifferenz">`timedelta`</abbr> mit der Ablaufz
|
|||
|
||||
Erstellen Sie einen echten JWT-Zugriffstoken und geben Sie ihn zurück.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="117-132"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="117-132"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="117-132"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="117-132"
|
||||
{!> ../../../docs_src/security/tutorial004_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="118-133"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="118-133"
|
||||
{!> ../../../docs_src/security/tutorial004_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="114-129"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="115-130"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="114-129"
|
||||
{!> ../../../docs_src/security/tutorial004_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="115-130"
|
||||
{!> ../../../docs_src/security/tutorial004.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Technische Details zum JWT-„Subjekt“ `sub`
|
||||
|
||||
|
|
@ -335,8 +411,11 @@ Verwenden Sie die Anmeldeinformationen:
|
|||
Benutzername: `johndoe`
|
||||
Passwort: `secret`.
|
||||
|
||||
!!! check
|
||||
Beachten Sie, dass im Code nirgendwo das Klartext-Passwort "`secret`" steht, wir haben nur die gehashte Version.
|
||||
/// check
|
||||
|
||||
Beachten Sie, dass im Code nirgendwo das Klartext-Passwort "`secret`" steht, wir haben nur die gehashte Version.
|
||||
|
||||
///
|
||||
|
||||
<img src="/img/tutorial/security/image08.png">
|
||||
|
||||
|
|
@ -357,8 +436,11 @@ Wenn Sie die Developer Tools öffnen, können Sie sehen, dass die gesendeten Dat
|
|||
|
||||
<img src="/img/tutorial/security/image10.png">
|
||||
|
||||
!!! note "Hinweis"
|
||||
Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer` beginnt.
|
||||
/// note | "Hinweis"
|
||||
|
||||
Beachten Sie den Header `Authorization` mit einem Wert, der mit `Bearer` beginnt.
|
||||
|
||||
///
|
||||
|
||||
## Fortgeschrittene Verwendung mit `scopes`
|
||||
|
||||
|
|
|
|||
|
|
@ -32,14 +32,17 @@ Diese werden normalerweise verwendet, um bestimmte Sicherheitsberechtigungen zu
|
|||
* `instagram_basic` wird von Facebook / Instagram verwendet.
|
||||
* `https://www.googleapis.com/auth/drive` wird von Google verwendet.
|
||||
|
||||
!!! info
|
||||
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
|
||||
/// info
|
||||
|
||||
Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist.
|
||||
In OAuth2 ist ein „Scope“ nur ein String, der eine bestimmte erforderliche Berechtigung deklariert.
|
||||
|
||||
Diese Details sind implementierungsspezifisch.
|
||||
Es spielt keine Rolle, ob er andere Zeichen wie `:` enthält oder ob es eine URL ist.
|
||||
|
||||
Für OAuth2 sind es einfach nur Strings.
|
||||
Diese Details sind implementierungsspezifisch.
|
||||
|
||||
Für OAuth2 sind es einfach nur Strings.
|
||||
|
||||
///
|
||||
|
||||
## Code, um `username` und `password` entgegenzunehmen.
|
||||
|
||||
|
|
@ -49,41 +52,57 @@ Lassen Sie uns nun die von **FastAPI** bereitgestellten Werkzeuge verwenden, um
|
|||
|
||||
Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als Abhängigkeit mit `Depends` in der *Pfadoperation* für `/token`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="4 78"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="4 78"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="4 78"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="4 78"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="4 79"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="4 79"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="2 74"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="4 76"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 74"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="4 76"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
`OAuth2PasswordRequestForm` ist eine Klassenabhängigkeit, die einen Formularbody deklariert mit:
|
||||
|
||||
|
|
@ -92,29 +111,38 @@ Importieren Sie zunächst `OAuth2PasswordRequestForm` und verwenden Sie es als A
|
|||
* Einem optionalen `scope`-Feld als langem String, bestehend aus durch Leerzeichen getrennten Strings.
|
||||
* Einem optionalen `grant_type` („Art der Anmeldung“).
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die OAuth2-Spezifikation *erfordert* tatsächlich ein Feld `grant_type` mit dem festen Wert `password`, aber `OAuth2PasswordRequestForm` erzwingt dies nicht.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` anstelle von `OAuth2PasswordRequestForm`.
|
||||
Die OAuth2-Spezifikation *erfordert* tatsächlich ein Feld `grant_type` mit dem festen Wert `password`, aber `OAuth2PasswordRequestForm` erzwingt dies nicht.
|
||||
|
||||
Wenn Sie es erzwingen müssen, verwenden Sie `OAuth2PasswordRequestFormStrict` anstelle von `OAuth2PasswordRequestForm`.
|
||||
|
||||
///
|
||||
|
||||
* Eine optionale `client_id` (benötigen wir für unser Beispiel nicht).
|
||||
* Ein optionales `client_secret` (benötigen wir für unser Beispiel nicht).
|
||||
|
||||
!!! info
|
||||
`OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`.
|
||||
/// info
|
||||
|
||||
`OAuth2PasswordBearer` lässt **FastAPI** wissen, dass es sich um ein Sicherheitsschema handelt. Daher wird es auf diese Weise zu OpenAPI hinzugefügt.
|
||||
`OAuth2PasswordRequestForm` ist keine spezielle Klasse für **FastAPI**, so wie `OAuth2PasswordBearer`.
|
||||
|
||||
Aber `OAuth2PasswordRequestForm` ist nur eine Klassenabhängigkeit, die Sie selbst hätten schreiben können, oder Sie hätten `Form`ular-Parameter direkt deklarieren können.
|
||||
`OAuth2PasswordBearer` lässt **FastAPI** wissen, dass es sich um ein Sicherheitsschema handelt. Daher wird es auf diese Weise zu OpenAPI hinzugefügt.
|
||||
|
||||
Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinfachung direkt von **FastAPI** bereitgestellt.
|
||||
Aber `OAuth2PasswordRequestForm` ist nur eine Klassenabhängigkeit, die Sie selbst hätten schreiben können, oder Sie hätten `Form`ular-Parameter direkt deklarieren können.
|
||||
|
||||
Da es sich jedoch um einen häufigen Anwendungsfall handelt, wird er zur Vereinfachung direkt von **FastAPI** bereitgestellt.
|
||||
|
||||
///
|
||||
|
||||
### Die Formulardaten verwenden
|
||||
|
||||
!!! tip "Tipp"
|
||||
Die Instanz der Klassenabhängigkeit `OAuth2PasswordRequestForm` verfügt, statt eines Attributs `scope` mit dem durch Leerzeichen getrennten langen String, über das Attribut `scopes` mit einer tatsächlichen Liste von Strings, einem für jeden gesendeten Scope.
|
||||
/// tip | "Tipp"
|
||||
|
||||
In diesem Beispiel verwenden wir keine `scopes`, aber die Funktionalität ist vorhanden, wenn Sie sie benötigen.
|
||||
Die Instanz der Klassenabhängigkeit `OAuth2PasswordRequestForm` verfügt, statt eines Attributs `scope` mit dem durch Leerzeichen getrennten langen String, über das Attribut `scopes` mit einer tatsächlichen Liste von Strings, einem für jeden gesendeten Scope.
|
||||
|
||||
In diesem Beispiel verwenden wir keine `scopes`, aber die Funktionalität ist vorhanden, wenn Sie sie benötigen.
|
||||
|
||||
///
|
||||
|
||||
Rufen Sie nun die Benutzerdaten aus der (gefakten) Datenbank ab, für diesen `username` aus dem Formularfeld.
|
||||
|
||||
|
|
@ -122,41 +150,57 @@ Wenn es keinen solchen Benutzer gibt, geben wir die Fehlermeldung „Incorrect u
|
|||
|
||||
Für den Fehler verwenden wir die Exception `HTTPException`:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="3 79-81"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="3 79-81"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="3 79-81"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="3 79-81"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="3 80-82"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="3 80-82"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="1 75-77"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="3 77-79"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1 75-77"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="3 77-79"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Das Passwort überprüfen
|
||||
|
||||
|
|
@ -182,41 +226,57 @@ Wenn Ihre Datenbank gestohlen wird, hat der Dieb nicht die Klartext-Passwörter
|
|||
|
||||
Der Dieb kann also nicht versuchen, die gleichen Passwörter in einem anderen System zu verwenden (da viele Benutzer überall das gleiche Passwort verwenden, wäre dies gefährlich).
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="82-85"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="82-85"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="82-85"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="82-85"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="83-86"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="83-86"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="78-81"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="80-83"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="78-81"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="80-83"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
#### Über `**user_dict`
|
||||
|
||||
|
|
@ -234,8 +294,11 @@ UserInDB(
|
|||
)
|
||||
```
|
||||
|
||||
!!! info
|
||||
Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#uber-user_indict){.internal-link target=_blank}.
|
||||
/// info
|
||||
|
||||
Eine ausführlichere Erklärung von `**user_dict` finden Sie in [der Dokumentation für **Extra Modelle**](../extra-models.md#uber-user_indict){.internal-link target=_blank}.
|
||||
|
||||
///
|
||||
|
||||
## Den Token zurückgeben
|
||||
|
||||
|
|
@ -247,55 +310,77 @@ Und es sollte einen `access_token` haben, mit einem String, der unseren Zugriffs
|
|||
|
||||
In diesem einfachen Beispiel gehen wir einfach völlig unsicher vor und geben denselben `username` wie der Token zurück.
|
||||
|
||||
!!! tip "Tipp"
|
||||
Im nächsten Kapitel sehen Sie eine wirklich sichere Implementierung mit Passwort-Hashing und <abbr title="JSON Web Tokens">JWT</abbr>-Tokens.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Aber konzentrieren wir uns zunächst auf die spezifischen Details, die wir benötigen.
|
||||
Im nächsten Kapitel sehen Sie eine wirklich sichere Implementierung mit Passwort-Hashing und <abbr title="JSON Web Tokens">JWT</abbr>-Tokens.
|
||||
|
||||
=== "Python 3.10+"
|
||||
Aber konzentrieren wir uns zunächst auf die spezifischen Details, die wir benötigen.
|
||||
|
||||
```Python hl_lines="87"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
///
|
||||
|
||||
=== "Python 3.9+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="87"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
```Python hl_lines="87"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.8+"
|
||||
////
|
||||
|
||||
```Python hl_lines="88"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
```Python hl_lines="87"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="83"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
//// tab | Python 3.8+
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
```Python hl_lines="88"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
////
|
||||
|
||||
```Python hl_lines="85"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Gemäß der Spezifikation sollten Sie ein JSON mit einem `access_token` und einem `token_type` zurückgeben, genau wie in diesem Beispiel.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Das müssen Sie selbst in Ihrem Code tun und sicherstellen, dass Sie diese JSON-Schlüssel verwenden.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
Es ist fast das Einzige, woran Sie denken müssen, es selbst richtigzumachen und die Spezifikationen einzuhalten.
|
||||
///
|
||||
|
||||
Den Rest erledigt **FastAPI** für Sie.
|
||||
```Python hl_lines="83"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="85"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Gemäß der Spezifikation sollten Sie ein JSON mit einem `access_token` und einem `token_type` zurückgeben, genau wie in diesem Beispiel.
|
||||
|
||||
Das müssen Sie selbst in Ihrem Code tun und sicherstellen, dass Sie diese JSON-Schlüssel verwenden.
|
||||
|
||||
Es ist fast das Einzige, woran Sie denken müssen, es selbst richtigzumachen und die Spezifikationen einzuhalten.
|
||||
|
||||
Den Rest erledigt **FastAPI** für Sie.
|
||||
|
||||
///
|
||||
|
||||
## Die Abhängigkeiten aktualisieren
|
||||
|
||||
|
|
@ -309,56 +394,75 @@ Beide Abhängigkeiten geben nur dann einen HTTP-Error zurück, wenn der Benutzer
|
|||
|
||||
In unserem Endpunkt erhalten wir also nur dann einen Benutzer, wenn der Benutzer existiert, korrekt authentifiziert wurde und aktiv ist:
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python hl_lines="58-66 69-74 94"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
```Python hl_lines="58-66 69-74 94"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py310.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python hl_lines="58-66 69-74 94"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python hl_lines="58-66 69-74 94"
|
||||
{!> ../../../docs_src/security/tutorial003_an_py39.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="59-67 70-75 95"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python hl_lines="59-67 70-75 95"
|
||||
{!> ../../../docs_src/security/tutorial003_an.py!}
|
||||
```
|
||||
|
||||
```Python hl_lines="56-64 67-70 88"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python hl_lines="58-66 69-72 90"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
!!! info
|
||||
Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation.
|
||||
///
|
||||
|
||||
Jeder HTTP-(Fehler-)Statuscode 401 „UNAUTHORIZED“ soll auch einen `WWW-Authenticate`-Header zurückgeben.
|
||||
```Python hl_lines="56-64 67-70 88"
|
||||
{!> ../../../docs_src/security/tutorial003_py310.py!}
|
||||
```
|
||||
|
||||
Im Fall von Bearer-Tokens (in unserem Fall) sollte der Wert dieses Headers `Bearer` lauten.
|
||||
////
|
||||
|
||||
Sie können diesen zusätzlichen Header tatsächlich weglassen und es würde trotzdem funktionieren.
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
Aber er wird hier bereitgestellt, um den Spezifikationen zu entsprechen.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Außerdem gibt es möglicherweise Tools, die ihn erwarten und verwenden (jetzt oder in der Zukunft) und das könnte für Sie oder Ihre Benutzer jetzt oder in der Zukunft nützlich sein.
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
Das ist der Vorteil von Standards ...
|
||||
///
|
||||
|
||||
```Python hl_lines="58-66 69-72 90"
|
||||
{!> ../../../docs_src/security/tutorial003.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
/// info
|
||||
|
||||
Der zusätzliche Header `WWW-Authenticate` mit dem Wert `Bearer`, den wir hier zurückgeben, ist ebenfalls Teil der Spezifikation.
|
||||
|
||||
Jeder HTTP-(Fehler-)Statuscode 401 „UNAUTHORIZED“ soll auch einen `WWW-Authenticate`-Header zurückgeben.
|
||||
|
||||
Im Fall von Bearer-Tokens (in unserem Fall) sollte der Wert dieses Headers `Bearer` lauten.
|
||||
|
||||
Sie können diesen zusätzlichen Header tatsächlich weglassen und es würde trotzdem funktionieren.
|
||||
|
||||
Aber er wird hier bereitgestellt, um den Spezifikationen zu entsprechen.
|
||||
|
||||
Außerdem gibt es möglicherweise Tools, die ihn erwarten und verwenden (jetzt oder in der Zukunft) und das könnte für Sie oder Ihre Benutzer jetzt oder in der Zukunft nützlich sein.
|
||||
|
||||
Das ist der Vorteil von Standards ...
|
||||
|
||||
///
|
||||
|
||||
## Es in Aktion sehen
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@ Mit `StaticFiles` können Sie statische Dateien aus einem Verzeichnis automatisc
|
|||
{!../../../docs_src/static_files/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden.
|
||||
/// note | "Technische Details"
|
||||
|
||||
**FastAPI** stellt dasselbe `starlette.staticfiles` auch via `fastapi.staticfiles` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
|
||||
Sie könnten auch `from starlette.staticfiles import StaticFiles` verwenden.
|
||||
|
||||
**FastAPI** stellt dasselbe `starlette.staticfiles` auch via `fastapi.staticfiles` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
### Was ist „Mounten“?
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,13 @@ Damit können Sie <a href="https://docs.pytest.org/" class="external-link" targe
|
|||
|
||||
## Verwendung von `TestClient`
|
||||
|
||||
!!! info
|
||||
Um `TestClient` zu verwenden, installieren Sie zunächst <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>.
|
||||
/// info
|
||||
|
||||
Z. B. `pip install httpx`.
|
||||
Um `TestClient` zu verwenden, installieren Sie zunächst <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a>.
|
||||
|
||||
Z. B. `pip install httpx`.
|
||||
|
||||
///
|
||||
|
||||
Importieren Sie `TestClient`.
|
||||
|
||||
|
|
@ -27,20 +30,29 @@ Schreiben Sie einfache `assert`-Anweisungen mit den Standard-Python-Ausdrücken,
|
|||
{!../../../docs_src/app_testing/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip "Tipp"
|
||||
Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind.
|
||||
/// tip | "Tipp"
|
||||
|
||||
Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht `await` verwenden.
|
||||
Beachten Sie, dass die Testfunktionen normal `def` und nicht `async def` sind.
|
||||
|
||||
Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen.
|
||||
Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht `await` verwenden.
|
||||
|
||||
!!! note "Technische Details"
|
||||
Sie könnten auch `from starlette.testclient import TestClient` verwenden.
|
||||
Dadurch können Sie `pytest` ohne Komplikationen direkt nutzen.
|
||||
|
||||
**FastAPI** stellt denselben `starlette.testclient` auch via `fastapi.testclient` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
|
||||
///
|
||||
|
||||
!!! tip "Tipp"
|
||||
Wenn Sie in Ihren Tests neben dem Senden von Anfragen an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md){.internal-link target=_blank} im Handbuch für fortgeschrittene Benutzer.
|
||||
/// note | "Technische Details"
|
||||
|
||||
Sie könnten auch `from starlette.testclient import TestClient` verwenden.
|
||||
|
||||
**FastAPI** stellt denselben `starlette.testclient` auch via `fastapi.testclient` bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
|
||||
|
||||
///
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Wenn Sie in Ihren Tests neben dem Senden von Anfragen an Ihre FastAPI-Anwendung auch `async`-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die [Async-Tests](../advanced/async-tests.md){.internal-link target=_blank} im Handbuch für fortgeschrittene Benutzer.
|
||||
|
||||
///
|
||||
|
||||
## Tests separieren
|
||||
|
||||
|
|
@ -110,41 +122,57 @@ Sie verfügt über eine `POST`-Operation, die mehrere Fehler zurückgeben könnt
|
|||
|
||||
Beide *Pfadoperationen* erfordern einen `X-Token`-Header.
|
||||
|
||||
=== "Python 3.10+"
|
||||
//// tab | Python 3.10+
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_an_py310/main.py!}
|
||||
```
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_an_py310/main.py!}
|
||||
```
|
||||
|
||||
=== "Python 3.9+"
|
||||
////
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_an_py39/main.py!}
|
||||
```
|
||||
//// tab | Python 3.9+
|
||||
|
||||
=== "Python 3.8+"
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_an_py39/main.py!}
|
||||
```
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_an/main.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.10+ nicht annotiert"
|
||||
//// tab | Python 3.8+
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_an/main.py!}
|
||||
```
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
|
||||
```
|
||||
////
|
||||
|
||||
=== "Python 3.8+ nicht annotiert"
|
||||
//// tab | Python 3.10+ nicht annotiert
|
||||
|
||||
!!! tip "Tipp"
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
/// tip | "Tipp"
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b/main.py!}
|
||||
```
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b_py310/main.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.8+ nicht annotiert
|
||||
|
||||
/// tip | "Tipp"
|
||||
|
||||
Bevorzugen Sie die `Annotated`-Version, falls möglich.
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
{!> ../../../docs_src/app_testing/app_b/main.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### Erweiterte Testdatei
|
||||
|
||||
|
|
@ -168,10 +196,13 @@ Z. B.:
|
|||
|
||||
Weitere Informationen zum Übergeben von Daten an das Backend (mithilfe von `httpx` oder dem `TestClient`) finden Sie in der <a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX-Dokumentation</a>.
|
||||
|
||||
!!! info
|
||||
Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle.
|
||||
/// info
|
||||
|
||||
Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des Testens an die Anwendung senden möchten, können Sie den `jsonable_encoder` verwenden, der in [JSON-kompatibler Encoder](encoder.md){.internal-link target=_blank} beschrieben wird.
|
||||
Beachten Sie, dass der `TestClient` Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle.
|
||||
|
||||
Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des Testens an die Anwendung senden möchten, können Sie den `jsonable_encoder` verwenden, der in [JSON-kompatibler Encoder](encoder.md){.internal-link target=_blank} beschrieben wird.
|
||||
|
||||
///
|
||||
|
||||
## Tests ausführen
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
# 🌖 📨 🗄
|
||||
|
||||
!!! warning
|
||||
👉 👍 🏧 ❔.
|
||||
/// warning
|
||||
|
||||
🚥 👆 ▶️ ⏮️ **FastAPI**, 👆 💪 🚫 💪 👉.
|
||||
👉 👍 🏧 ❔.
|
||||
|
||||
🚥 👆 ▶️ ⏮️ **FastAPI**, 👆 💪 🚫 💪 👉.
|
||||
|
||||
///
|
||||
|
||||
👆 💪 📣 🌖 📨, ⏮️ 🌖 👔 📟, 🔉 🆎, 📛, ♒️.
|
||||
|
||||
|
|
@ -27,20 +30,26 @@
|
|||
{!../../../docs_src/additional_responses/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
✔️ 🤯 👈 👆 ✔️ 📨 `JSONResponse` 🔗.
|
||||
/// note
|
||||
|
||||
!!! info
|
||||
`model` 🔑 🚫 🍕 🗄.
|
||||
✔️ 🤯 👈 👆 ✔️ 📨 `JSONResponse` 🔗.
|
||||
|
||||
**FastAPI** 🔜 ✊ Pydantic 🏷 ⚪️➡️ 📤, 🏗 `JSON Schema`, & 🚮 ⚫️ ☑ 🥉.
|
||||
///
|
||||
|
||||
☑ 🥉:
|
||||
/// info
|
||||
|
||||
* 🔑 `content`, 👈 ✔️ 💲 ➕1️⃣ 🎻 🎚 (`dict`) 👈 🔌:
|
||||
* 🔑 ⏮️ 📻 🆎, ✅ `application/json`, 👈 🔌 💲 ➕1️⃣ 🎻 🎚, 👈 🔌:
|
||||
* 🔑 `schema`, 👈 ✔️ 💲 🎻 🔗 ⚪️➡️ 🏷, 📥 ☑ 🥉.
|
||||
* **FastAPI** 🚮 🔗 📥 🌐 🎻 🔗 ➕1️⃣ 🥉 👆 🗄 ↩️ ✅ ⚫️ 🔗. 👉 🌌, 🎏 🈸 & 👩💻 💪 ⚙️ 👈 🎻 🔗 🔗, 🚚 👻 📟 ⚡ 🧰, ♒️.
|
||||
`model` 🔑 🚫 🍕 🗄.
|
||||
|
||||
**FastAPI** 🔜 ✊ Pydantic 🏷 ⚪️➡️ 📤, 🏗 `JSON Schema`, & 🚮 ⚫️ ☑ 🥉.
|
||||
|
||||
☑ 🥉:
|
||||
|
||||
* 🔑 `content`, 👈 ✔️ 💲 ➕1️⃣ 🎻 🎚 (`dict`) 👈 🔌:
|
||||
* 🔑 ⏮️ 📻 🆎, ✅ `application/json`, 👈 🔌 💲 ➕1️⃣ 🎻 🎚, 👈 🔌:
|
||||
* 🔑 `schema`, 👈 ✔️ 💲 🎻 🔗 ⚪️➡️ 🏷, 📥 ☑ 🥉.
|
||||
* **FastAPI** 🚮 🔗 📥 🌐 🎻 🔗 ➕1️⃣ 🥉 👆 🗄 ↩️ ✅ ⚫️ 🔗. 👉 🌌, 🎏 🈸 & 👩💻 💪 ⚙️ 👈 🎻 🔗 🔗, 🚚 👻 📟 ⚡ 🧰, ♒️.
|
||||
|
||||
///
|
||||
|
||||
🏗 📨 🗄 👉 *➡ 🛠️* 🔜:
|
||||
|
||||
|
|
@ -172,13 +181,19 @@
|
|||
{!../../../docs_src/additional_responses/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! note
|
||||
👀 👈 👆 ✔️ 📨 🖼 ⚙️ `FileResponse` 🔗.
|
||||
/// note
|
||||
|
||||
!!! info
|
||||
🚥 👆 ✔ 🎏 📻 🆎 🎯 👆 `responses` 🔢, FastAPI 🔜 🤔 📨 ✔️ 🎏 📻 🆎 👑 📨 🎓 (🔢 `application/json`).
|
||||
👀 👈 👆 ✔️ 📨 🖼 ⚙️ `FileResponse` 🔗.
|
||||
|
||||
✋️ 🚥 👆 ✔️ ✔ 🛃 📨 🎓 ⏮️ `None` 🚮 📻 🆎, FastAPI 🔜 ⚙️ `application/json` 🙆 🌖 📨 👈 ✔️ 👨💼 🏷.
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
🚥 👆 ✔ 🎏 📻 🆎 🎯 👆 `responses` 🔢, FastAPI 🔜 🤔 📨 ✔️ 🎏 📻 🆎 👑 📨 🎓 (🔢 `application/json`).
|
||||
|
||||
✋️ 🚥 👆 ✔️ ✔ 🛃 📨 🎓 ⏮️ `None` 🚮 📻 🆎, FastAPI 🔜 ⚙️ `application/json` 🙆 🌖 📨 👈 ✔️ 👨💼 🏷.
|
||||
|
||||
///
|
||||
|
||||
## 🌀 ℹ
|
||||
|
||||
|
|
|
|||
|
|
@ -18,17 +18,23 @@
|
|||
{!../../../docs_src/additional_status_codes/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! warning
|
||||
🕐❔ 👆 📨 `Response` 🔗, 💖 🖼 🔛, ⚫️ 🔜 📨 🔗.
|
||||
/// warning
|
||||
|
||||
⚫️ 🏆 🚫 🎻 ⏮️ 🏷, ♒️.
|
||||
🕐❔ 👆 📨 `Response` 🔗, 💖 🖼 🔛, ⚫️ 🔜 📨 🔗.
|
||||
|
||||
⚒ 💭 ⚫️ ✔️ 📊 👆 💚 ⚫️ ✔️, & 👈 💲 ☑ 🎻 (🚥 👆 ⚙️ `JSONResponse`).
|
||||
⚫️ 🏆 🚫 🎻 ⏮️ 🏷, ♒️.
|
||||
|
||||
!!! note "📡 ℹ"
|
||||
👆 💪 ⚙️ `from starlette.responses import JSONResponse`.
|
||||
⚒ 💭 ⚫️ ✔️ 📊 👆 💚 ⚫️ ✔️, & 👈 💲 ☑ 🎻 (🚥 👆 ⚙️ `JSONResponse`).
|
||||
|
||||
**FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃. 🎏 ⏮️ `status`.
|
||||
///
|
||||
|
||||
/// note | "📡 ℹ"
|
||||
|
||||
👆 💪 ⚙️ `from starlette.responses import JSONResponse`.
|
||||
|
||||
**FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃. 🎏 ⏮️ `status`.
|
||||
|
||||
///
|
||||
|
||||
## 🗄 & 🛠️ 🩺
|
||||
|
||||
|
|
|
|||
|
|
@ -60,11 +60,14 @@ checker(q="somequery")
|
|||
{!../../../docs_src/dependencies/tutorial011.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
🌐 👉 💪 😑 🎭. & ⚫️ 💪 🚫 📶 🆑 ❔ ⚫️ ⚠.
|
||||
/// tip
|
||||
|
||||
👫 🖼 😫 🙅, ✋️ 🎦 ❔ ⚫️ 🌐 👷.
|
||||
🌐 👉 💪 😑 🎭. & ⚫️ 💪 🚫 📶 🆑 ❔ ⚫️ ⚠.
|
||||
|
||||
📃 🔃 💂♂, 📤 🚙 🔢 👈 🛠️ 👉 🎏 🌌.
|
||||
👫 🖼 😫 🙅, ✋️ 🎦 ❔ ⚫️ 🌐 👷.
|
||||
|
||||
🚥 👆 🤔 🌐 👉, 👆 ⏪ 💭 ❔ 👈 🚙 🧰 💂♂ 👷 🔘.
|
||||
📃 🔃 💂♂, 📤 🚙 🔢 👈 🛠️ 👉 🎏 🌌.
|
||||
|
||||
🚥 👆 🤔 🌐 👉, 👆 ⏪ 💭 ❔ 👈 🚙 🧰 💂♂ 👷 🔘.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -64,8 +64,11 @@ $ pytest
|
|||
{!../../../docs_src/async_tests/test_main.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
🗒 👈 💯 🔢 🔜 `async def` ↩️ `def` ⏭ 🕐❔ ⚙️ `TestClient`.
|
||||
/// tip
|
||||
|
||||
🗒 👈 💯 🔢 🔜 `async def` ↩️ `def` ⏭ 🕐❔ ⚙️ `TestClient`.
|
||||
|
||||
///
|
||||
|
||||
⤴️ 👥 💪 ✍ `AsyncClient` ⏮️ 📱, & 📨 🔁 📨 ⚫️, ⚙️ `await`.
|
||||
|
||||
|
|
@ -81,12 +84,18 @@ response = client.get('/')
|
|||
|
||||
...👈 👥 ⚙️ ⚒ 👆 📨 ⏮️ `TestClient`.
|
||||
|
||||
!!! tip
|
||||
🗒 👈 👥 ⚙️ 🔁/⌛ ⏮️ 🆕 `AsyncClient` - 📨 🔁.
|
||||
/// tip
|
||||
|
||||
🗒 👈 👥 ⚙️ 🔁/⌛ ⏮️ 🆕 `AsyncClient` - 📨 🔁.
|
||||
|
||||
///
|
||||
|
||||
## 🎏 🔁 🔢 🤙
|
||||
|
||||
🔬 🔢 🔜 🔁, 👆 💪 🔜 🤙 (& `await`) 🎏 `async` 🔢 ↖️ ⚪️➡️ 📨 📨 👆 FastAPI 🈸 👆 💯, ⚫️❔ 👆 🔜 🤙 👫 🙆 🙆 👆 📟.
|
||||
|
||||
!!! tip
|
||||
🚥 👆 ⚔ `RuntimeError: Task attached to a different loop` 🕐❔ 🛠️ 🔁 🔢 🤙 👆 💯 (✅ 🕐❔ ⚙️ <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">✳ MotorClient</a>) 💭 🔗 🎚 👈 💪 🎉 ➰ 🕴 🏞 🔁 🔢, ✅ `'@app.on_event("startup")` ⏲.
|
||||
/// tip
|
||||
|
||||
🚥 👆 ⚔ `RuntimeError: Task attached to a different loop` 🕐❔ 🛠️ 🔁 🔢 🤙 👆 💯 (✅ 🕐❔ ⚙️ <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">✳ MotorClient</a>) 💭 🔗 🎚 👈 💪 🎉 ➰ 🕴 🏞 🔁 🔢, ✅ `'@app.on_event("startup")` ⏲.
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -39,8 +39,11 @@ browser --> proxy
|
|||
proxy --> server
|
||||
```
|
||||
|
||||
!!! tip
|
||||
📢 `0.0.0.0` 🛎 ⚙️ ⛓ 👈 📋 👂 🔛 🌐 📢 💪 👈 🎰/💽.
|
||||
/// tip
|
||||
|
||||
📢 `0.0.0.0` 🛎 ⚙️ ⛓ 👈 📋 👂 🔛 🌐 📢 💪 👈 🎰/💽.
|
||||
|
||||
///
|
||||
|
||||
🩺 🎚 🔜 💪 🗄 🔗 📣 👈 👉 🛠️ `server` 🔎 `/api/v1` (⛅ 🗳). 🖼:
|
||||
|
||||
|
|
@ -77,10 +80,13 @@ $ uvicorn main:app --root-path /api/v1
|
|||
|
||||
🚥 👆 ⚙️ Hypercorn, ⚫️ ✔️ 🎛 `--root-path`.
|
||||
|
||||
!!! note "📡 ℹ"
|
||||
🔫 🔧 🔬 `root_path` 👉 ⚙️ 💼.
|
||||
/// note | "📡 ℹ"
|
||||
|
||||
& `--root-path` 📋 ⏸ 🎛 🚚 👈 `root_path`.
|
||||
🔫 🔧 🔬 `root_path` 👉 ⚙️ 💼.
|
||||
|
||||
& `--root-path` 📋 ⏸ 🎛 🚚 👈 `root_path`.
|
||||
|
||||
///
|
||||
|
||||
### ✅ ⏮️ `root_path`
|
||||
|
||||
|
|
@ -168,8 +174,11 @@ Uvicorn 🔜 ⌛ 🗳 🔐 Uvicorn `http://127.0.0.1:8000/app`, & ⤴️ ⚫
|
|||
|
||||
👉 💬 Traefik 👂 🔛 ⛴ 9️⃣9️⃣9️⃣9️⃣ & ⚙️ ➕1️⃣ 📁 `routes.toml`.
|
||||
|
||||
!!! tip
|
||||
👥 ⚙️ ⛴ 9️⃣9️⃣9️⃣9️⃣ ↩️ 🐩 🇺🇸🔍 ⛴ 8️⃣0️⃣ 👈 👆 🚫 ✔️ 🏃 ⚫️ ⏮️ 📡 (`sudo`) 😌.
|
||||
/// tip
|
||||
|
||||
👥 ⚙️ ⛴ 9️⃣9️⃣9️⃣9️⃣ ↩️ 🐩 🇺🇸🔍 ⛴ 8️⃣0️⃣ 👈 👆 🚫 ✔️ 🏃 ⚫️ ⏮️ 📡 (`sudo`) 😌.
|
||||
|
||||
///
|
||||
|
||||
🔜 ✍ 👈 🎏 📁 `routes.toml`:
|
||||
|
||||
|
|
@ -235,8 +244,11 @@ $ uvicorn main:app --root-path /api/v1
|
|||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
👀 👈 ✋️ 👆 🔐 ⚫️ `http://127.0.0.1:8000/app` ⚫️ 🎦 `root_path` `/api/v1`, ✊ ⚪️➡️ 🎛 `--root-path`.
|
||||
/// tip
|
||||
|
||||
👀 👈 ✋️ 👆 🔐 ⚫️ `http://127.0.0.1:8000/app` ⚫️ 🎦 `root_path` `/api/v1`, ✊ ⚪️➡️ 🎛 `--root-path`.
|
||||
|
||||
///
|
||||
|
||||
& 🔜 📂 📛 ⏮️ ⛴ Traefik, ✅ ➡ 🔡: <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a>.
|
||||
|
||||
|
|
@ -279,8 +291,11 @@ $ uvicorn main:app --root-path /api/v1
|
|||
|
||||
## 🌖 💽
|
||||
|
||||
!!! warning
|
||||
👉 🌅 🏧 ⚙️ 💼. 💭 🆓 🚶 ⚫️.
|
||||
/// warning
|
||||
|
||||
👉 🌅 🏧 ⚙️ 💼. 💭 🆓 🚶 ⚫️.
|
||||
|
||||
///
|
||||
|
||||
🔢, **FastAPI** 🔜 ✍ `server` 🗄 🔗 ⏮️ 📛 `root_path`.
|
||||
|
||||
|
|
@ -319,15 +334,21 @@ $ uvicorn main:app --root-path /api/v1
|
|||
}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
👀 🚘-🏗 💽 ⏮️ `url` 💲 `/api/v1`, ✊ ⚪️➡️ `root_path`.
|
||||
/// tip
|
||||
|
||||
👀 🚘-🏗 💽 ⏮️ `url` 💲 `/api/v1`, ✊ ⚪️➡️ `root_path`.
|
||||
|
||||
///
|
||||
|
||||
🩺 🎚 <a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> ⚫️ 🔜 👀 💖:
|
||||
|
||||
<img src="/img/tutorial/behind-a-proxy/image03.png">
|
||||
|
||||
!!! tip
|
||||
🩺 🎚 🔜 🔗 ⏮️ 💽 👈 👆 🖊.
|
||||
/// tip
|
||||
|
||||
🩺 🎚 🔜 🔗 ⏮️ 💽 👈 👆 🖊.
|
||||
|
||||
///
|
||||
|
||||
### ❎ 🏧 💽 ⚪️➡️ `root_path`
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@
|
|||
|
||||
& 🚥 👈 `Response` ✔️ 🎻 📻 🆎 (`application/json`), 💖 💼 ⏮️ `JSONResponse` & `UJSONResponse`, 💽 👆 📨 🔜 🔁 🗜 (& ⛽) ⏮️ 🙆 Pydantic `response_model` 👈 👆 📣 *➡ 🛠️ 👨🎨*.
|
||||
|
||||
!!! note
|
||||
🚥 👆 ⚙️ 📨 🎓 ⏮️ 🙅♂ 📻 🆎, FastAPI 🔜 ⌛ 👆 📨 ✔️ 🙅♂ 🎚, ⚫️ 🔜 🚫 📄 📨 📁 🚮 🏗 🗄 🩺.
|
||||
/// note
|
||||
|
||||
🚥 👆 ⚙️ 📨 🎓 ⏮️ 🙅♂ 📻 🆎, FastAPI 🔜 ⌛ 👆 📨 ✔️ 🙅♂ 🎚, ⚫️ 🔜 🚫 📄 📨 📁 🚮 🏗 🗄 🩺.
|
||||
|
||||
///
|
||||
|
||||
## ⚙️ `ORJSONResponse`
|
||||
|
||||
|
|
@ -31,15 +34,21 @@
|
|||
{!../../../docs_src/custom_response/tutorial001b.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
🔢 `response_class` 🔜 ⚙️ 🔬 "📻 🆎" 📨.
|
||||
/// info
|
||||
|
||||
👉 💼, 🇺🇸🔍 🎚 `Content-Type` 🔜 ⚒ `application/json`.
|
||||
🔢 `response_class` 🔜 ⚙️ 🔬 "📻 🆎" 📨.
|
||||
|
||||
& ⚫️ 🔜 📄 ✅ 🗄.
|
||||
👉 💼, 🇺🇸🔍 🎚 `Content-Type` 🔜 ⚒ `application/json`.
|
||||
|
||||
!!! tip
|
||||
`ORJSONResponse` ⏳ 🕴 💪 FastAPI, 🚫 💃.
|
||||
& ⚫️ 🔜 📄 ✅ 🗄.
|
||||
|
||||
///
|
||||
|
||||
/// tip
|
||||
|
||||
`ORJSONResponse` ⏳ 🕴 💪 FastAPI, 🚫 💃.
|
||||
|
||||
///
|
||||
|
||||
## 🕸 📨
|
||||
|
||||
|
|
@ -52,12 +61,15 @@
|
|||
{!../../../docs_src/custom_response/tutorial002.py!}
|
||||
```
|
||||
|
||||
!!! info
|
||||
🔢 `response_class` 🔜 ⚙️ 🔬 "📻 🆎" 📨.
|
||||
/// info
|
||||
|
||||
👉 💼, 🇺🇸🔍 🎚 `Content-Type` 🔜 ⚒ `text/html`.
|
||||
🔢 `response_class` 🔜 ⚙️ 🔬 "📻 🆎" 📨.
|
||||
|
||||
& ⚫️ 🔜 📄 ✅ 🗄.
|
||||
👉 💼, 🇺🇸🔍 🎚 `Content-Type` 🔜 ⚒ `text/html`.
|
||||
|
||||
& ⚫️ 🔜 📄 ✅ 🗄.
|
||||
|
||||
///
|
||||
|
||||
### 📨 `Response`
|
||||
|
||||
|
|
@ -69,11 +81,17 @@
|
|||
{!../../../docs_src/custom_response/tutorial003.py!}
|
||||
```
|
||||
|
||||
!!! warning
|
||||
`Response` 📨 🔗 👆 *➡ 🛠️ 🔢* 🏆 🚫 📄 🗄 (🖼, `Content-Type` 🏆 🚫 📄) & 🏆 🚫 ⭐ 🏧 🎓 🩺.
|
||||
/// warning
|
||||
|
||||
!!! info
|
||||
↗️, ☑ `Content-Type` 🎚, 👔 📟, ♒️, 🔜 👟 ⚪️➡️ `Response` 🎚 👆 📨.
|
||||
`Response` 📨 🔗 👆 *➡ 🛠️ 🔢* 🏆 🚫 📄 🗄 (🖼, `Content-Type` 🏆 🚫 📄) & 🏆 🚫 ⭐ 🏧 🎓 🩺.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
↗️, ☑ `Content-Type` 🎚, 👔 📟, ♒️, 🔜 👟 ⚪️➡️ `Response` 🎚 👆 📨.
|
||||
|
||||
///
|
||||
|
||||
### 📄 🗄 & 🔐 `Response`
|
||||
|
||||
|
|
@ -103,10 +121,13 @@
|
|||
|
||||
✔️ 🤯 👈 👆 💪 ⚙️ `Response` 📨 🕳 🙆, ⚖️ ✍ 🛃 🎧-🎓.
|
||||
|
||||
!!! note "📡 ℹ"
|
||||
👆 💪 ⚙️ `from starlette.responses import HTMLResponse`.
|
||||
/// note | "📡 ℹ"
|
||||
|
||||
**FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
|
||||
👆 💪 ⚙️ `from starlette.responses import HTMLResponse`.
|
||||
|
||||
**FastAPI** 🚚 🎏 `starlette.responses` `fastapi.responses` 🏪 👆, 👩💻. ✋️ 🌅 💪 📨 👟 🔗 ⚪️➡️ 💃.
|
||||
|
||||
///
|
||||
|
||||
### `Response`
|
||||
|
||||
|
|
@ -153,15 +174,21 @@ FastAPI (🤙 💃) 🔜 🔁 🔌 🎚-📐 🎚. ⚫️ 🔜 🔌 🎚-🆎
|
|||
|
||||
🎛 🎻 📨 ⚙️ <a href="https://github.com/ultrajson/ultrajson" class="external-link" target="_blank">`ujson`</a>.
|
||||
|
||||
!!! warning
|
||||
`ujson` 🌘 💛 🌘 🐍 🏗-🛠️ ❔ ⚫️ 🍵 📐-💼.
|
||||
/// warning
|
||||
|
||||
`ujson` 🌘 💛 🌘 🐍 🏗-🛠️ ❔ ⚫️ 🍵 📐-💼.
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="2 7"
|
||||
{!../../../docs_src/custom_response/tutorial001.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
⚫️ 💪 👈 `ORJSONResponse` 💪 ⏩ 🎛.
|
||||
/// tip
|
||||
|
||||
⚫️ 💪 👈 `ORJSONResponse` 💪 ⏩ 🎛.
|
||||
|
||||
///
|
||||
|
||||
### `RedirectResponse`
|
||||
|
||||
|
|
@ -222,8 +249,11 @@ FastAPI (🤙 💃) 🔜 🔁 🔌 🎚-📐 🎚. ⚫️ 🔜 🔌 🎚-🆎
|
|||
|
||||
🔨 ⚫️ 👉 🌌, 👥 💪 🚮 ⚫️ `with` 🍫, & 👈 🌌, 🚚 👈 ⚫️ 📪 ⏮️ 🏁.
|
||||
|
||||
!!! tip
|
||||
👀 👈 📥 👥 ⚙️ 🐩 `open()` 👈 🚫 🐕🦺 `async` & `await`, 👥 📣 ➡ 🛠️ ⏮️ 😐 `def`.
|
||||
/// tip
|
||||
|
||||
👀 👈 📥 👥 ⚙️ 🐩 `open()` 👈 🚫 🐕🦺 `async` & `await`, 👥 📣 ➡ 🛠️ ⏮️ 😐 `def`.
|
||||
|
||||
///
|
||||
|
||||
### `FileResponse`
|
||||
|
||||
|
|
@ -292,8 +322,11 @@ FastAPI (🤙 💃) 🔜 🔁 🔌 🎚-📐 🎚. ⚫️ 🔜 🔌 🎚-🆎
|
|||
{!../../../docs_src/custom_response/tutorial010.py!}
|
||||
```
|
||||
|
||||
!!! tip
|
||||
👆 💪 🔐 `response_class` *➡ 🛠️* ⏭.
|
||||
/// tip
|
||||
|
||||
👆 💪 🔐 `response_class` *➡ 🛠️* ⏭.
|
||||
|
||||
///
|
||||
|
||||
## 🌖 🧾
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,15 @@ FastAPI 🏗 🔛 🔝 **Pydantic**, & 👤 ✔️ 🌏 👆 ❔ ⚙️ Pyda
|
|||
|
||||
👉 👷 🎏 🌌 ⏮️ Pydantic 🏷. & ⚫️ 🤙 🏆 🎏 🌌 🔘, ⚙️ Pydantic.
|
||||
|
||||
!!! info
|
||||
✔️ 🤯 👈 🎻 💪 🚫 🌐 Pydantic 🏷 💪.
|
||||
/// info
|
||||
|
||||
, 👆 5️⃣📆 💪 ⚙️ Pydantic 🏷.
|
||||
✔️ 🤯 👈 🎻 💪 🚫 🌐 Pydantic 🏷 💪.
|
||||
|
||||
✋️ 🚥 👆 ✔️ 📚 🎻 🤥 🤭, 👉 👌 🎱 ⚙️ 👫 🏋️ 🕸 🛠️ ⚙️ FastAPI. 👶
|
||||
, 👆 5️⃣📆 💪 ⚙️ Pydantic 🏷.
|
||||
|
||||
✋️ 🚥 👆 ✔️ 📚 🎻 🤥 🤭, 👉 👌 🎱 ⚙️ 👫 🏋️ 🕸 🛠️ ⚙️ FastAPI. 👶
|
||||
|
||||
///
|
||||
|
||||
## 🎻 `response_model`
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,13 @@
|
|||
|
||||
& ⤴️, ▶️️ ⏮️ `yield`, 👥 🚚 🏷. 👉 📟 🔜 🛠️ **⏮️** 🈸 **🏁 🚚 📨**, ▶️️ ⏭ *🤫*. 👉 💪, 🖼, 🚀 ℹ 💖 💾 ⚖️ 💻.
|
||||
|
||||
!!! tip
|
||||
`shutdown` 🔜 🔨 🕐❔ 👆 **⛔️** 🈸.
|
||||
/// tip
|
||||
|
||||
🎲 👆 💪 ▶️ 🆕 ⏬, ⚖️ 👆 🤚 🎡 🏃 ⚫️. 🤷
|
||||
`shutdown` 🔜 🔨 🕐❔ 👆 **⛔️** 🈸.
|
||||
|
||||
🎲 👆 💪 ▶️ 🆕 ⏬, ⚖️ 👆 🤚 🎡 🏃 ⚫️. 🤷
|
||||
|
||||
///
|
||||
|
||||
### 🔆 🔢
|
||||
|
||||
|
|
@ -91,10 +94,13 @@ async with lifespan(app):
|
|||
|
||||
## 🎛 🎉 (😢)
|
||||
|
||||
!!! warning
|
||||
👍 🌌 🍵 *🕴* & *🤫* ⚙️ `lifespan` 🔢 `FastAPI` 📱 🔬 🔛.
|
||||
/// warning
|
||||
|
||||
👆 💪 🎲 🚶 👉 🍕.
|
||||
👍 🌌 🍵 *🕴* & *🤫* ⚙️ `lifespan` 🔢 `FastAPI` 📱 🔬 🔛.
|
||||
|
||||
👆 💪 🎲 🚶 👉 🍕.
|
||||
|
||||
///
|
||||
|
||||
📤 🎛 🌌 🔬 👉 ⚛ 🛠️ ⏮️ *🕴* & ⏮️ *🤫*.
|
||||
|
||||
|
|
@ -126,20 +132,29 @@ async with lifespan(app):
|
|||
|
||||
📥, `shutdown` 🎉 🐕🦺 🔢 🔜 ✍ ✍ ⏸ `"Application shutdown"` 📁 `log.txt`.
|
||||
|
||||
!!! info
|
||||
`open()` 🔢, `mode="a"` ⛓ "🎻",, ⏸ 🔜 🚮 ⏮️ ⚫️❔ 🔛 👈 📁, 🍵 📁 ⏮️ 🎚.
|
||||
/// info
|
||||
|
||||
!!! tip
|
||||
👀 👈 👉 💼 👥 ⚙️ 🐩 🐍 `open()` 🔢 👈 🔗 ⏮️ 📁.
|
||||
`open()` 🔢, `mode="a"` ⛓ "🎻",, ⏸ 🔜 🚮 ⏮️ ⚫️❔ 🔛 👈 📁, 🍵 📁 ⏮️ 🎚.
|
||||
|
||||
, ⚫️ 🔌 👤/🅾 (🔢/🔢), 👈 🚚 "⌛" 👜 ✍ 💾.
|
||||
///
|
||||
|
||||
✋️ `open()` 🚫 ⚙️ `async` & `await`.
|
||||
/// tip
|
||||
|
||||
, 👥 📣 🎉 🐕🦺 🔢 ⏮️ 🐩 `def` ↩️ `async def`.
|
||||
👀 👈 👉 💼 👥 ⚙️ 🐩 🐍 `open()` 🔢 👈 🔗 ⏮️ 📁.
|
||||
|
||||
!!! info
|
||||
👆 💪 ✍ 🌅 🔃 👫 🎉 🐕🦺 <a href="https://www.starlette.io/events/" class="external-link" target="_blank">💃 🎉' 🩺</a>.
|
||||
, ⚫️ 🔌 👤/🅾 (🔢/🔢), 👈 🚚 "⌛" 👜 ✍ 💾.
|
||||
|
||||
✋️ `open()` 🚫 ⚙️ `async` & `await`.
|
||||
|
||||
, 👥 📣 🎉 🐕🦺 🔢 ⏮️ 🐩 `def` ↩️ `async def`.
|
||||
|
||||
///
|
||||
|
||||
/// info
|
||||
|
||||
👆 💪 ✍ 🌅 🔃 👫 🎉 🐕🦺 <a href="https://www.starlette.io/events/" class="external-link" target="_blank">💃 🎉' 🩺</a>.
|
||||
|
||||
///
|
||||
|
||||
### `startup` & `shutdown` 👯♂️
|
||||
|
||||
|
|
|
|||
|
|
@ -16,17 +16,21 @@
|
|||
|
||||
➡️ ▶️ ⏮️ 🙅 FastAPI 🈸:
|
||||
|
||||
=== "🐍 3️⃣.6️⃣ & 🔛"
|
||||
//// tab | 🐍 3️⃣.6️⃣ & 🔛
|
||||
|
||||
```Python hl_lines="9-11 14-15 18 19 23"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001.py!}
|
||||
```
|
||||
```Python hl_lines="9-11 14-15 18 19 23"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001.py!}
|
||||
```
|
||||
|
||||
=== "🐍 3️⃣.9️⃣ & 🔛"
|
||||
////
|
||||
|
||||
```Python hl_lines="7-9 12-13 16-17 21"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
|
||||
```
|
||||
//// tab | 🐍 3️⃣.9️⃣ & 🔛
|
||||
|
||||
```Python hl_lines="7-9 12-13 16-17 21"
|
||||
{!> ../../../docs_src/generate_clients/tutorial001_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
👀 👈 *➡ 🛠️* 🔬 🏷 👫 ⚙️ 📨 🚀 & 📨 🚀, ⚙️ 🏷 `Item` & `ResponseMessage`.
|
||||
|
||||
|
|
@ -111,8 +115,11 @@ frontend-app@1.0.0 generate-client /home/user/code/frontend-app
|
|||
|
||||
<img src="/img/tutorial/generate-clients/image03.png">
|
||||
|
||||
!!! tip
|
||||
👀 ✍ `name` & `price`, 👈 🔬 FastAPI 🈸, `Item` 🏷.
|
||||
/// tip
|
||||
|
||||
👀 ✍ `name` & `price`, 👈 🔬 FastAPI 🈸, `Item` 🏷.
|
||||
|
||||
///
|
||||
|
||||
👆 🔜 ✔️ ⏸ ❌ 📊 👈 👆 📨:
|
||||
|
||||
|
|
@ -129,17 +136,21 @@ frontend-app@1.0.0 generate-client /home/user/code/frontend-app
|
|||
🖼, 👆 💪 ✔️ 📄 **🏬** & ➕1️⃣ 📄 **👩💻**, & 👫 💪 👽 🔖:
|
||||
|
||||
|
||||
=== "🐍 3️⃣.6️⃣ & 🔛"
|
||||
//// tab | 🐍 3️⃣.6️⃣ & 🔛
|
||||
|
||||
```Python hl_lines="23 28 36"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002.py!}
|
||||
```
|
||||
```Python hl_lines="23 28 36"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002.py!}
|
||||
```
|
||||
|
||||
=== "🐍 3️⃣.9️⃣ & 🔛"
|
||||
////
|
||||
|
||||
```Python hl_lines="21 26 34"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
|
||||
```
|
||||
//// tab | 🐍 3️⃣.9️⃣ & 🔛
|
||||
|
||||
```Python hl_lines="21 26 34"
|
||||
{!> ../../../docs_src/generate_clients/tutorial002_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### 🏗 📕 👩💻 ⏮️ 🔖
|
||||
|
||||
|
|
@ -186,17 +197,21 @@ FastAPI ⚙️ **😍 🆔** 🔠 *➡ 🛠️*, ⚫️ ⚙️ **🛠️ 🆔**
|
|||
|
||||
👆 💪 ⤴️ 🚶♀️ 👈 🛃 🔢 **FastAPI** `generate_unique_id_function` 🔢:
|
||||
|
||||
=== "🐍 3️⃣.6️⃣ & 🔛"
|
||||
//// tab | 🐍 3️⃣.6️⃣ & 🔛
|
||||
|
||||
```Python hl_lines="8-9 12"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003.py!}
|
||||
```
|
||||
```Python hl_lines="8-9 12"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003.py!}
|
||||
```
|
||||
|
||||
=== "🐍 3️⃣.9️⃣ & 🔛"
|
||||
////
|
||||
|
||||
```Python hl_lines="6-7 10"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
|
||||
```
|
||||
//// tab | 🐍 3️⃣.9️⃣ & 🔛
|
||||
|
||||
```Python hl_lines="6-7 10"
|
||||
{!> ../../../docs_src/generate_clients/tutorial003_py39.py!}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
### 🏗 📕 👩💻 ⏮️ 🛃 🛠️ 🆔
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue