diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c7cee518..21413fc66 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,7 +14,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.10 + rev: v0.11.12 hooks: - id: ruff args: diff --git a/README.md b/README.md index 78ae6b10e..da9446e2b 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ The key features are: + diff --git a/docs/bn/docs/environment-variables.md b/docs/bn/docs/environment-variables.md new file mode 100644 index 000000000..9122ca5bf --- /dev/null +++ b/docs/bn/docs/environment-variables.md @@ -0,0 +1,298 @@ +# এনভায়রনমেন্ট ভেরিয়েবলস + +/// tip + +আপনি যদি "এনভায়রনমেন্ট ভেরিয়েবলস" কী এবং সেগুলো কীভাবে ব্যবহার করতে হয় সেটা জানেন, তাহলে এই অংশটি স্কিপ করে যেতে পারেন। + +/// + +এনভায়রনমেন্ট ভেরিয়েবল (সংক্ষেপে "**env var**" নামেও পরিচিত) হলো এমন একটি ভেরিয়েবল যা পাইথন কোডের **বাইরে**, **অপারেটিং সিস্টেমে** থাকে এবং আপনার পাইথন কোড (বা অন্যান্য প্রোগ্রাম) দ্বারা যাকে রিড করা যায়। + +এনভায়রনমেন্ট ভেরিয়েবলস অ্যাপ্লিকেশনের **সেটিংস** পরিচালনা করতে, পাইথনের **ইনস্টলেশন** প্রক্রিয়ার অংশ হিসেবে, ইত্যাদি কাজে উপযোগী হতে পারে। + +## Env Vars তৈরী এবং ব্যবহার + +আপনি **শেল (টার্মিনাল)**-এ, পাইথনের প্রয়োজন ছাড়াই, এনভায়রনমেন্ট ভেরিয়েবলস **তৈরি** এবং ব্যবহার করতে পারবেনঃ + +//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash + +
+ +```console +// আপনি চাইলে MY_NAME নামে একটি env var তৈরি করতে পারেন +$ export MY_NAME="Wade Wilson" + +// তারপরে এটিকে চাইলে অন্যান্য প্রোগ্রামে ব্যবহার করতে পারেন +$ echo "Hello $MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +//// tab | উইন্ডোজ পাওয়ারশেল + +
+ +```console +// MY_NAME নামে env var তৈরি +$ $Env:MY_NAME = "Wade Wilson" + +// অন্যান্য প্রোগ্রামে এটিকে ব্যবহার +$ echo "Hello $Env:MY_NAME" + +Hello Wade Wilson +``` + +
+ +//// + +## পাইথনে env vars রিড করা + +আপনি চাইলে পাইথনের **বাইরে**, টার্মিনালে (বা অন্য কোনো উপায়ে) এনভায়রনমেন্ট ভেরিয়েবলস তৈরি করতে পারেন, এবং পরে সেগুলো **পাইথনে রিড** (অ্যাক্সেস করতে) পারেন। + +উদাহরণস্বরূপ, আপনার `main.py` নামে একটি ফাইল থাকতে পারেঃ + +```Python hl_lines="3" +import os + +name = os.getenv("MY_NAME", "World") +print(f"Hello {name} from Python") +``` + +/// tip + +`os.getenv()` এর দ্বিতীয় আর্গুমেন্টটি হলো এর ডিফল্ট ভ্যালু যা রিটার্ন করা হবে। + +যদি এটি দেওয়া না হয়, ডিফল্টভাবে `None` ব্যবহৃত হবে, এখানে আমরা ডিফল্ট ভ্যালু হিসেবে `"World"` ব্যবহার করেছি। + +/// + +তারপরে পাইথন প্রোগ্রামটিকে নিম্নোক্তভাবে কল করা যাবেঃ + +//// tab | লিনাক্স, ম্যাকওএস, উইন্ডোজ Bash + +
+ +```console +// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি +$ python main.py + +// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি + +Hello World from Python + +// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই +$ export MY_NAME="Wade Wilson" + +// এবং তারপর আবার প্রোগ্রাটিকে কল করি +$ python main.py + +// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে + +Hello Wade Wilson from Python +``` + +
+ +//// + +//// tab | উইন্ডোজ পাওয়ারশেল + +
+ +```console +// এখনো আমরা এনভায়রনমেন্ট ভেরিয়েবল সেট করিনি +$ python main.py + +// যেহেতু env var সেট করা হয়নি, তাই আমরা ডিফল্ট ভ্যালু পাচ্ছি + +Hello World from Python + +// কিন্তু আমরা প্রথমে যদি একটা এনভায়রনমেন্ট ভারিয়েবল তৈরি করে নেই +$ $Env:MY_NAME = "Wade Wilson" + +// এবং তারপর আবার প্রোগ্রাটিকে কল করি +$ python main.py + +// এখন এটি এনভায়রনমেন্ট ভেরিয়েবল রিড করতে পারবে + +Hello Wade Wilson from Python +``` + +
+ +//// + +যেহেতু এনভায়রনমেন্ট ভেরিয়েবলস কোডের বাইরে সেট করা যায়, কিন্তু পরবর্তীতে কোড দ্বারা রিড করা যায়, এবং বাকি ফাইলগুলোর সাথে রাখতে (`git` এ কমিট) হয় না, তাই কনফিগারেশনস বা **সেটিংস** এর জন্য এগুলো সাধারণত ব্যবহৃত হয়ে থাকে। + +আপনি একটি এনভায়রনমেন্ট ভেরিয়েবল শুধুমাত্র একটি **নির্দিষ্ট প্রোগ্রাম ইনভোকেশনের** জন্যও তৈরি করতে পারেন, যা শুধুমাত্র সেই প্রোগ্রামের জন্যই এভেইলেবল থাকবে এবং শুধুমাত্র তার চলাকালীন সময় পর্যন্তই সক্রিয় থাকবে। + +এটি করতে, প্রোগ্রামটি রান করার ঠিক আগেই, একই লাইনে এনভায়রনমেন্ট ভেরিয়েবল তৈরি করুন: + +
+ +```console +// প্রোগ্রামটি কল করার সময় একই লাইনে MY_NAME এনভায়রনমেন্ট ভেরিয়েবল তৈরি করুন +$ MY_NAME="Wade Wilson" python main.py + +// এখন এটি এনভায়রনমেন্ট ভ্যরিয়েবলটিকে রিড করতে পারবে + +Hello Wade Wilson from Python + +// পরবর্তীতে এনভায়রনমেন্ট ভেরিয়েবলটিকে আর ব্যবহার করা যাচ্ছে না +$ python main.py + +Hello World from Python +``` + +
+ +/// tip + +এটি নিয়ে আরো বিস্তারিত পড়তে পারেন এখানে The Twelve-Factor App: Config। + +/// + +## টাইপস এবং ভ্যালিডেশন + +এই এনভায়রনমেন্ট ভেরিয়েবলগুলো শুধুমাত্র **টেক্সট স্ট্রিংস** হ্যান্ডেল করতে পারে, যেহেতু এগুলো পাইথনের বাইরে অবস্থিত এবং অন্যান্য প্রোগ্রাম এবং সিস্টেমের বাকি অংশের (এমনকি বিভিন্ন অপারেটিং সিস্টেম যেমন লিনাক্স, উইন্ডোজ, ম্যাকওএস) সাথে সামঞ্জস্যপূর্ণ হতে হয়। + +এর অর্থ হচ্ছে পাইথনে এনভায়রনমেন্ট ভেরিয়েবল থেকে রিড করা **যেকোনো ভ্যালু** একটি `str` হবে, এবং অন্য কোনো টাইপে কনভার্সন বা যেকোনো ভেলিডেশন কোডে আলাদাভাবে করতে হবে। + +এনভায়রনমেন্ট ভেরিয়েবল ব্যবহার করে **এপ্লিকেশন সেটিংস** হ্যান্ডেল করা নিয়ে আরো বিস্তারিত জানা যাবে [Advanced User Guide - Settings and Environment Variables](./advanced/settings.md){.internal-link target=_blank}. + +## `PATH` এনভায়রনমেন্ট ভেরিয়েবল + +**`PATH`** নামে একটি **বিশেষ** এনভায়রনমেন্ট ভেরিয়েবল রয়েছে, যেটি প্রোগ্রাম রান করার জন্য অপারেটিং সিস্টেমস (লিনাক্স, ম্যাকওএস, উইন্ডোজ) দ্বারা ব্যবহৃত হয়। + +`PATH` ভেরিয়েবল এর ভ্যালু হচ্ছে একটি বিশাল স্ট্রিং যা ডিরেক্টরিকে কোলন `:` দিয়ে আলাদা করার মাধ্যমে লিনাক্সে ও ম্যাকওএস এ, এবং সেমিকোলন `;` এর মাধ্যমে উইন্ডোজ এ তৈরি করা থাকে। + +উদাহরণস্বরূপ, `PATH` ভেরিয়েবল নিচের মতো দেখতে হতে পারেঃ + +//// tab | লিনাক্স, ম্যাকওএস + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +তারমানে হলো সিস্টেম প্রোগ্রামগুলোকে নিচের ডিরেক্টরিগুলোতে খুঁজবেঃ + +* `/usr/local/bin` +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | উইন্ডোজ + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32 +``` + +তারমানে হলো সিস্টেম প্রোগ্রামগুলোকে নিচের ডিরেক্টরিগুলোতে খুঁজবেঃ + +* `C:\Program Files\Python312\Scripts` +* `C:\Program Files\Python312` +* `C:\Windows\System32` + +//// + +যখন আপনি টার্মিনালে কোনো **কমান্ড** লিখবেন, অপারেটিং সিস্টেম **প্রত্যেকটি ডিরেক্টরিতে** প্রোগ্রামটি **খুঁজবে** যেগুলো `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ লিস্ট করা আছে। + +উদাহরণস্বরূপ, যখন আপনি টার্মিনালে `python` টাইপ করবেন, অপারেটিং সিস্টেম এই লিস্ট এর **প্রথম ডিরেক্টরিতে** `python` নামের একটি প্রোগ্রাম খুঁজবে। + +যদি এটি খুঁজে পায়, তাহলে এটি প্রোগ্রামটিকে ব্যবহার করবে। অন্যথায় এটি **অন্যান্য ডিরেক্টরিগুলোতে** এটিকে খুঁজতে থাকবে। + +### পাইথন ইনস্টল এবং `PATH` আপডেট + +যখন আপনি পাইথন ইনস্টল করেন, আপনি `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান কিনা সেটা জিজ্ঞেস করা হতে পারে। + +//// tab | লিনাক্স, ম্যাকওএস + +ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `/opt/custompython/bin` ডিরেক্টরিতে ইনস্টল হচ্ছে। + +যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `/opt/custompython/bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে। + +এটা দেখতে এমনটা হতে পারেঃ + +```plaintext +/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin +``` + +এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `/opt/custompython/bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে। + +//// + +//// tab | উইন্ডোজ + +ধরা যাক আপনি পাইথন ইনস্টল করলেন এবং এটি `C:\opt\custompython\bin` ডিরেক্টরিতে ইনস্টল হচ্ছে। + +যদি আপনি "Yes" সিলেক্ট করে `PATH` এনভায়রনমেন্ট ভেরিয়েবল আপডেট করতে চান, তাহলে ইনস্টলার `C:\opt\custompython\bin` কে `PATH` এনভায়রনমেন্ট ভেরিয়েবল এ এড করে দিবে। + +```plaintext +C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin +``` + +এইভাবে, আপনি যখন টার্মিনালে `python` টাইপ করেন, সিস্টেম পাইথন প্রোগ্রামটিকে `C:\opt\custompython\bin` (সর্বশেষ ডিরেক্টরি) তে খুঁজে পাবে এবং এটাকে ব্যবহার করবে। + +//// + +তাই, আপনি যদি টাইপ করেনঃ + +
+ +```console +$ python +``` + +
+ +//// tab | লিনাক্স, ম্যাকওএস + +সিস্টেম `python` প্রোগ্রামকে `/opt/custompython/bin` এ **খুঁজে পাবে** এবং এটাকে রান করবে। + +এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ + +
+ +```console +$ /opt/custompython/bin/python +``` + +
+ +//// + +//// tab | উইন্ডোজ + +সিস্টেম `python` প্রোগ্রামকে `C:\opt\custompython\bin\python` এ **খুঁজে পাবে** এবং এটাকে রান করবে। + +এটা মোটামুটিভাবে নিচের মতো করে লেখার সমান হবেঃ + +
+ +```console +$ C:\opt\custompython\bin\python +``` + +
+ +//// + +এই তথ্যগুলো [ভার্চুয়াল এনভায়রনমেন্টস](virtual-environments.md){.internal-link target=_blank} শেখার ক্ষেত্রে সহায়ক হবে। + +## উপসংহার + +এর মাধ্যমে আপনি **এনভায়রনমেন্ট ভেরিয়েবলস** কি এবং এটিকে পাইথনে কিভাবে ব্যবহার করতে হয় তার সম্পর্কে বেসিক ধারনা পেলেন। + +চাইলে এই সম্পর্কে আরো বিস্তারিত পড়তে পারেন Wikipedia for Environment Variable এ। + +অনেক ক্ষেত্রে, দেখা মাত্রই এনভায়রনমেন্ট ভেরিয়েবল কীভাবে প্রয়োজন হবে তা স্পষ্ট হয় না। কিন্তু ডেভেলপমেন্টের সময় আপনি নানা রকম পরিস্থিতিতে এগুলোর সম্মুখীন হবেন, তাই এগুলো সম্পর্কে জেনে রাখা ভালো। + +উদাহরণস্বরূপ, আপনার এই ইনফরমেশনটি পরবর্তী, [ভার্চুয়াল এনভায়রনমেন্টস](virtual-environments.md) অংশে দরকার হবে। diff --git a/docs/en/data/contributors.yml b/docs/en/data/contributors.yml index 7da07d8a1..f3f7c9133 100644 --- a/docs/en/data/contributors.yml +++ b/docs/en/data/contributors.yml @@ -1,11 +1,11 @@ tiangolo: login: tiangolo - count: 734 + count: 747 avatarUrl: https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4 url: https://github.com/tiangolo dependabot: login: dependabot - count: 100 + count: 102 avatarUrl: https://avatars.githubusercontent.com/in/29110?v=4 url: https://github.com/apps/dependabot alejsdev: @@ -15,7 +15,7 @@ alejsdev: url: https://github.com/alejsdev pre-commit-ci: login: pre-commit-ci - count: 27 + count: 30 avatarUrl: https://avatars.githubusercontent.com/in/68672?v=4 url: https://github.com/apps/pre-commit-ci github-actions: diff --git a/docs/en/data/github_sponsors.yml b/docs/en/data/github_sponsors.yml index e24f64edc..efc5cbfcc 100644 --- a/docs/en/data/github_sponsors.yml +++ b/docs/en/data/github_sponsors.yml @@ -2,6 +2,9 @@ sponsors: - - login: renderinc avatarUrl: https://avatars.githubusercontent.com/u/36424661?v=4 url: https://github.com/renderinc + - login: Nixtla + avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 + url: https://github.com/Nixtla - login: andrew-propelauth avatarUrl: https://avatars.githubusercontent.com/u/89474256?u=c98993dec8553c09d424ede67bbe86e5c35f48c9&v=4 url: https://github.com/andrew-propelauth @@ -14,19 +17,22 @@ sponsors: - login: coderabbitai avatarUrl: https://avatars.githubusercontent.com/u/132028505?v=4 url: https://github.com/coderabbitai + - login: subtotal + avatarUrl: https://avatars.githubusercontent.com/u/176449348?v=4 + url: https://github.com/subtotal - login: porter-dev avatarUrl: https://avatars.githubusercontent.com/u/62078005?v=4 url: https://github.com/porter-dev - - login: Nixtla - avatarUrl: https://avatars.githubusercontent.com/u/79945230?v=4 - url: https://github.com/Nixtla - login: scalar avatarUrl: https://avatars.githubusercontent.com/u/301879?v=4 url: https://github.com/scalar - - login: ObliviousAI avatarUrl: https://avatars.githubusercontent.com/u/65656077?v=4 url: https://github.com/ObliviousAI -- - login: svix +- - login: dribia + avatarUrl: https://avatars.githubusercontent.com/u/41189616?v=4 + url: https://github.com/dribia + - login: svix avatarUrl: https://avatars.githubusercontent.com/u/80175132?v=4 url: https://github.com/svix - login: stainless-api @@ -35,6 +41,9 @@ sponsors: - login: speakeasy-api avatarUrl: https://avatars.githubusercontent.com/u/91446104?v=4 url: https://github.com/speakeasy-api + - login: snapit-cypher + avatarUrl: https://avatars.githubusercontent.com/u/115662654?v=4 + url: https://github.com/snapit-cypher - login: databento avatarUrl: https://avatars.githubusercontent.com/u/64141749?v=4 url: https://github.com/databento @@ -68,6 +77,9 @@ sponsors: - - login: takashi-yoneya avatarUrl: https://avatars.githubusercontent.com/u/33813153?u=2d0522bceba0b8b69adf1f2db866503bd96f944e&v=4 url: https://github.com/takashi-yoneya + - login: Doist + avatarUrl: https://avatars.githubusercontent.com/u/2565372?v=4 + url: https://github.com/Doist - - login: mainframeindustries avatarUrl: https://avatars.githubusercontent.com/u/55092103?v=4 url: https://github.com/mainframeindustries @@ -83,18 +95,9 @@ sponsors: - - login: upciti avatarUrl: https://avatars.githubusercontent.com/u/43346262?v=4 url: https://github.com/upciti - - login: f4rk4sh - avatarUrl: https://avatars.githubusercontent.com/u/90454259?v=4 - url: https://github.com/f4rk4sh - - login: freddiev4 - avatarUrl: https://avatars.githubusercontent.com/u/8339018?u=1aad5b4f5a04cb750852b843d5e1d8f4ce339c2e&v=4 - url: https://github.com/freddiev4 - - login: samuelcolvin avatarUrl: https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4 url: https://github.com/samuelcolvin - - login: vincentkoc - avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 - url: https://github.com/vincentkoc - login: otosky avatarUrl: https://avatars.githubusercontent.com/u/42260747?u=69d089387c743d89427aa4ad8740cfb34045a9e0&v=4 url: https://github.com/otosky @@ -104,9 +107,6 @@ sponsors: - login: ashi-agrawal avatarUrl: https://avatars.githubusercontent.com/u/17105294?u=99c7a854035e5398d8e7b674f2d42baae6c957f8&v=4 url: https://github.com/ashi-agrawal - - login: sepsi77 - avatarUrl: https://avatars.githubusercontent.com/u/18682303?v=4 - url: https://github.com/sepsi77 - login: RaamEEIL avatarUrl: https://avatars.githubusercontent.com/u/20320552?v=4 url: https://github.com/RaamEEIL @@ -125,9 +125,6 @@ sponsors: - login: ProteinQure avatarUrl: https://avatars.githubusercontent.com/u/33707203?v=4 url: https://github.com/ProteinQure - - login: roboflow - avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 - url: https://github.com/roboflow - login: kaoru0310 avatarUrl: https://avatars.githubusercontent.com/u/80977929?u=1b61d10142b490e56af932ddf08a390fae8ee94f&v=4 url: https://github.com/kaoru0310 @@ -146,6 +143,9 @@ sponsors: - login: logic-automation avatarUrl: https://avatars.githubusercontent.com/u/144732884?v=4 url: https://github.com/logic-automation + - login: roboflow + avatarUrl: https://avatars.githubusercontent.com/u/53104118?v=4 + url: https://github.com/roboflow - login: dudikbender avatarUrl: https://avatars.githubusercontent.com/u/53487583?u=3a57542938ebfd57579a0111db2b297e606d9681&v=4 url: https://github.com/dudikbender @@ -185,15 +185,18 @@ sponsors: - login: anomaly avatarUrl: https://avatars.githubusercontent.com/u/3654837?v=4 url: https://github.com/anomaly + - login: mj0331 + avatarUrl: https://avatars.githubusercontent.com/u/3890353?u=1c627ac1a024515b4871de5c3ebbfaa1a57f65d4&v=4 + url: https://github.com/mj0331 - login: gorhack avatarUrl: https://avatars.githubusercontent.com/u/4141690?u=ec119ebc4bdf00a7bc84657a71aa17834f4f27f3&v=4 url: https://github.com/gorhack - login: Ryandaydev avatarUrl: https://avatars.githubusercontent.com/u/4292423?u=679ff84cb7b988c5795a5fa583857f574a055763&v=4 url: https://github.com/Ryandaydev - - login: jaredtrog - avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 - url: https://github.com/jaredtrog + - login: vincentkoc + avatarUrl: https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4 + url: https://github.com/vincentkoc - login: jstanden avatarUrl: https://avatars.githubusercontent.com/u/63288?u=c3658d57d2862c607a0e19c2101c3c51876e36ad&v=4 url: https://github.com/jstanden @@ -215,9 +218,6 @@ sponsors: - login: wshayes avatarUrl: https://avatars.githubusercontent.com/u/365303?u=07ca03c5ee811eb0920e633cc3c3db73dbec1aa5&v=4 url: https://github.com/wshayes - - login: gaetanBloch - avatarUrl: https://avatars.githubusercontent.com/u/583199?u=50c49e83d6b4feb78a091901ea02ead1462f442b&v=4 - url: https://github.com/gaetanBloch - login: koxudaxi avatarUrl: https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4 url: https://github.com/koxudaxi @@ -227,9 +227,6 @@ sponsors: - login: mintuhouse avatarUrl: https://avatars.githubusercontent.com/u/769950?u=ecfbd79a97d33177e0d093ddb088283cf7fe8444&v=4 url: https://github.com/mintuhouse - - login: oliverxchen - avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 - url: https://github.com/oliverxchen - login: TrevorBenson avatarUrl: https://avatars.githubusercontent.com/u/9167887?u=dccbea3327a57750923333d8ebf1a0b3f1948949&v=4 url: https://github.com/TrevorBenson @@ -254,6 +251,12 @@ sponsors: - login: mjohnsey avatarUrl: https://avatars.githubusercontent.com/u/16784016?u=38fad2e6b411244560b3af99c5f5a4751bc81865&v=4 url: https://github.com/mjohnsey + - login: jaredtrog + avatarUrl: https://avatars.githubusercontent.com/u/4381365?v=4 + url: https://github.com/jaredtrog + - login: oliverxchen + avatarUrl: https://avatars.githubusercontent.com/u/4471774?u=534191f25e32eeaadda22dfab4b0a428733d5489&v=4 + url: https://github.com/oliverxchen - login: ternaus avatarUrl: https://avatars.githubusercontent.com/u/5481618?u=513a26b02a39e7a28d587cd37c6cc877ea368e6e&v=4 url: https://github.com/ternaus @@ -263,9 +266,6 @@ sponsors: - login: FernandoCelmer avatarUrl: https://avatars.githubusercontent.com/u/6262214?u=58ba6d5888fa7f355934e52db19f950e20b38162&v=4 url: https://github.com/FernandoCelmer - - login: simw - avatarUrl: https://avatars.githubusercontent.com/u/6322526?v=4 - url: https://github.com/simw - login: Rehket avatarUrl: https://avatars.githubusercontent.com/u/7015688?u=3afb0ba200feebbc7f958950e92db34df2a3c172&v=4 url: https://github.com/Rehket @@ -299,6 +299,9 @@ sponsors: - login: hgalytoby avatarUrl: https://avatars.githubusercontent.com/u/50397689?u=62c7ff3519858423579676cd0efbd7e3f1ffe63a&v=4 url: https://github.com/hgalytoby + - login: browniebroke + avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 + url: https://github.com/browniebroke - login: joshuatz avatarUrl: https://avatars.githubusercontent.com/u/17817563?u=f1bf05b690d1fc164218f0b420cdd3acb7913e21&v=4 url: https://github.com/joshuatz @@ -317,12 +320,12 @@ sponsors: - login: rlnchow avatarUrl: https://avatars.githubusercontent.com/u/28018479?u=a93ca9cf1422b9ece155784a72d5f2fdbce7adff&v=4 url: https://github.com/rlnchow - - login: dvlpjrs - avatarUrl: https://avatars.githubusercontent.com/u/32254642?u=fbd6ad0324d4f1eb6231cf775be1c7bd4404e961&v=4 - url: https://github.com/dvlpjrs - login: engineerjoe440 avatarUrl: https://avatars.githubusercontent.com/u/33275230?u=eb223cad27017bb1e936ee9b429b450d092d0236&v=4 url: https://github.com/engineerjoe440 + - login: lukzmu + avatarUrl: https://avatars.githubusercontent.com/u/175964415?u=83ea9b0b7b7b0f15bcb5747d93f303447a19a00b&v=4 + url: https://github.com/lukzmu - login: conservative-dude avatarUrl: https://avatars.githubusercontent.com/u/55538308?u=f250c44942ea6e73a6bd90739b381c470c192c11&v=4 url: https://github.com/conservative-dude @@ -335,12 +338,6 @@ sponsors: - login: PelicanQ avatarUrl: https://avatars.githubusercontent.com/u/77930606?v=4 url: https://github.com/PelicanQ - - login: tochikuji - avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 - url: https://github.com/tochikuji - - login: browniebroke - avatarUrl: https://avatars.githubusercontent.com/u/861044?u=5abfca5588f3e906b31583d7ee62f6de4b68aa24&v=4 - url: https://github.com/browniebroke - login: miguelgr avatarUrl: https://avatars.githubusercontent.com/u/1484589?u=54556072b8136efa12ae3b6902032ea2a39ace4b&v=4 url: https://github.com/miguelgr @@ -368,6 +365,9 @@ sponsors: - login: ceb10n avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n + - login: tochikuji + avatarUrl: https://avatars.githubusercontent.com/u/851759?v=4 + url: https://github.com/tochikuji - login: moonape1226 avatarUrl: https://avatars.githubusercontent.com/u/8532038?u=d9f8b855a429fff9397c3833c2ff83849ebf989d&v=4 url: https://github.com/moonape1226 @@ -428,10 +428,7 @@ sponsors: - login: hcristea avatarUrl: https://avatars.githubusercontent.com/u/7814406?u=19092923a4ea5b338567961c8270b9206a6d81bb&v=4 url: https://github.com/hcristea -- - login: larsyngvelundin - avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 - url: https://github.com/larsyngvelundin - - login: andrecorumba +- - login: andrecorumba avatarUrl: https://avatars.githubusercontent.com/u/37807517?u=9b9be3b41da9bda60957da9ef37b50dbf65baa61&v=4 url: https://github.com/andrecorumba - login: rwxd @@ -446,27 +443,18 @@ sponsors: - login: Olegt0rr avatarUrl: https://avatars.githubusercontent.com/u/25399456?u=3e87b5239a2f4600975ba13be73054f8567c6060&v=4 url: https://github.com/Olegt0rr - - login: Miles-Arts - avatarUrl: https://avatars.githubusercontent.com/u/82297475?u=c41881e4b386d9dbf737218542b120336b5731a1&v=4 - url: https://github.com/Miles-Arts - - login: sandeepsalwan1 - avatarUrl: https://avatars.githubusercontent.com/u/118837112?u=fc9b0330fa4791950661b7decd9bf56f07599b43&v=4 - url: https://github.com/sandeepsalwan1 - - login: fabioantonioastore - avatarUrl: https://avatars.githubusercontent.com/u/132024075?u=b3a267f2e2c7ce2379f82163f88111bd2a2a2f1e&v=4 - url: https://github.com/fabioantonioastore - - login: zhandos256 - avatarUrl: https://avatars.githubusercontent.com/u/60260671?u=aa9ed698bc3cd06fb553d2ef91d3895bbb00cce1&v=4 - url: https://github.com/zhandos256 + - login: larsyngvelundin + avatarUrl: https://avatars.githubusercontent.com/u/34173819?u=74958599695bf83ac9f1addd935a51548a10c6b0&v=4 + url: https://github.com/larsyngvelundin - login: one-st-one avatarUrl: https://avatars.githubusercontent.com/u/62360849?u=746dd21c34e7e06eefb11b03e8bb01aaae3c2a4f&v=4 url: https://github.com/one-st-one + - login: federicsp + avatarUrl: https://avatars.githubusercontent.com/u/62903636?u=05004f4a2c590f1d18c200e17978bf2e17acb632&v=4 + url: https://github.com/federicsp - login: Toothwitch avatarUrl: https://avatars.githubusercontent.com/u/1710406?u=5eebb23b46cd26e48643b9e5179536cad491c17a&v=4 url: https://github.com/Toothwitch - - login: ssbarnea - avatarUrl: https://avatars.githubusercontent.com/u/102495?u=c7bd9ddf127785286fc939dd18cb02db0a453bce&v=4 - url: https://github.com/ssbarnea - login: andreagrandi avatarUrl: https://avatars.githubusercontent.com/u/636391?u=13d90cb8ec313593a5b71fbd4e33b78d6da736f5&v=4 url: https://github.com/andreagrandi diff --git a/docs/en/data/sponsors.yml b/docs/en/data/sponsors.yml index 14a1f3cf3..897ca7b8d 100644 --- a/docs/en/data/sponsors.yml +++ b/docs/en/data/sponsors.yml @@ -48,6 +48,9 @@ silver: - url: https://www.interviewpal.com/?utm_source=fastapi&utm_medium=open-source&utm_campaign=dev-hiring title: InterviewPal - AI Interview Coach for Engineers and Devs img: https://fastapi.tiangolo.com/img/sponsors/interviewpal.png + - url: https://dribia.com/en/ + title: Dribia - Data Science within your reach + img: https://fastapi.tiangolo.com/img/sponsors/dribia.png bronze: - url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source title: Biosecurity risk assessments made easy. diff --git a/docs/en/data/sponsors_badge.yml b/docs/en/data/sponsors_badge.yml index fd34019b3..d145e7372 100644 --- a/docs/en/data/sponsors_badge.yml +++ b/docs/en/data/sponsors_badge.yml @@ -42,3 +42,4 @@ logins: - coderabbitai - permitio - LambdaTest-Inc + - dribia diff --git a/docs/en/data/topic_repos.yml b/docs/en/data/topic_repos.yml index 169b62694..1f6ae55bd 100644 --- a/docs/en/data/topic_repos.yml +++ b/docs/en/data/topic_repos.yml @@ -1,266 +1,266 @@ - name: full-stack-fastapi-template html_url: https://github.com/fastapi/full-stack-fastapi-template - stars: 32337 + stars: 33079 owner_login: fastapi owner_html_url: https://github.com/fastapi - name: Hello-Python html_url: https://github.com/mouredev/Hello-Python - stars: 29833 + stars: 30350 owner_login: mouredev owner_html_url: https://github.com/mouredev - name: serve html_url: https://github.com/jina-ai/serve - stars: 21544 + stars: 21593 owner_login: jina-ai owner_html_url: https://github.com/jina-ai -- name: sqlmodel - html_url: https://github.com/fastapi/sqlmodel - stars: 15799 - owner_login: fastapi - owner_html_url: https://github.com/fastapi - name: HivisionIDPhotos html_url: https://github.com/Zeyi-Lin/HivisionIDPhotos - stars: 15676 + stars: 17229 owner_login: Zeyi-Lin owner_html_url: https://github.com/Zeyi-Lin +- name: sqlmodel + html_url: https://github.com/fastapi/sqlmodel + stars: 16068 + owner_login: fastapi + owner_html_url: https://github.com/fastapi - name: Douyin_TikTok_Download_API html_url: https://github.com/Evil0ctal/Douyin_TikTok_Download_API - stars: 12183 + stars: 12689 owner_login: Evil0ctal owner_html_url: https://github.com/Evil0ctal - name: fastapi-best-practices html_url: https://github.com/zhanymkanov/fastapi-best-practices - stars: 11594 + stars: 11965 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov - name: awesome-fastapi html_url: https://github.com/mjhea0/awesome-fastapi - stars: 9586 + stars: 9773 owner_login: mjhea0 owner_html_url: https://github.com/mjhea0 - name: FastUI html_url: https://github.com/pydantic/FastUI - stars: 8804 + stars: 8829 owner_login: pydantic owner_html_url: https://github.com/pydantic - name: nonebot2 html_url: https://github.com/nonebot/nonebot2 - stars: 6688 + stars: 6779 owner_login: nonebot owner_html_url: https://github.com/nonebot - name: FileCodeBox html_url: https://github.com/vastsa/FileCodeBox - stars: 6502 + stars: 6652 owner_login: vastsa owner_html_url: https://github.com/vastsa - name: serge html_url: https://github.com/serge-chat/serge - stars: 5720 + stars: 5722 owner_login: serge-chat owner_html_url: https://github.com/serge-chat - name: hatchet html_url: https://github.com/hatchet-dev/hatchet - stars: 5515 + stars: 5607 owner_login: hatchet-dev owner_html_url: https://github.com/hatchet-dev -- name: fastapi-users - html_url: https://github.com/fastapi-users/fastapi-users - stars: 5162 - owner_login: fastapi-users - owner_html_url: https://github.com/fastapi-users - name: polar html_url: https://github.com/polarsource/polar - stars: 5119 + stars: 5327 owner_login: polarsource owner_html_url: https://github.com/polarsource +- name: fastapi-users + html_url: https://github.com/fastapi-users/fastapi-users + stars: 5235 + owner_login: fastapi-users + owner_html_url: https://github.com/fastapi-users +- name: fastapi_mcp + html_url: https://github.com/tadata-org/fastapi_mcp + stars: 5193 + owner_login: tadata-org + owner_html_url: https://github.com/tadata-org +- name: SurfSense + html_url: https://github.com/MODSetter/SurfSense + stars: 4833 + owner_login: MODSetter + owner_html_url: https://github.com/MODSetter - name: chatgpt-web-share html_url: https://github.com/chatpire/chatgpt-web-share - stars: 4302 + stars: 4307 owner_login: chatpire owner_html_url: https://github.com/chatpire - name: strawberry html_url: https://github.com/strawberry-graphql/strawberry - stars: 4244 + stars: 4281 owner_login: strawberry-graphql owner_html_url: https://github.com/strawberry-graphql -- name: fastapi_mcp - html_url: https://github.com/tadata-org/fastapi_mcp - stars: 4178 - owner_login: tadata-org - owner_html_url: https://github.com/tadata-org - name: atrilabs-engine html_url: https://github.com/Atri-Labs/atrilabs-engine - stars: 4112 + stars: 4110 owner_login: Atri-Labs owner_html_url: https://github.com/Atri-Labs - name: dynaconf html_url: https://github.com/dynaconf/dynaconf - stars: 3985 + stars: 4008 owner_login: dynaconf owner_html_url: https://github.com/dynaconf - name: poem html_url: https://github.com/poem-web/poem - stars: 3918 + stars: 3977 owner_login: poem-web owner_html_url: https://github.com/poem-web - name: farfalle html_url: https://github.com/rashadphz/farfalle - stars: 3287 + stars: 3317 owner_login: rashadphz owner_html_url: https://github.com/rashadphz - name: fastapi-admin html_url: https://github.com/fastapi-admin/fastapi-admin - stars: 3192 + stars: 3253 owner_login: fastapi-admin owner_html_url: https://github.com/fastapi-admin - name: datamodel-code-generator html_url: https://github.com/koxudaxi/datamodel-code-generator - stars: 3141 + stars: 3228 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi -- name: opyrator - html_url: https://github.com/ml-tooling/opyrator - stars: 3116 - owner_login: ml-tooling - owner_html_url: https://github.com/ml-tooling - name: LitServe html_url: https://github.com/Lightning-AI/LitServe - stars: 3088 + stars: 3175 owner_login: Lightning-AI owner_html_url: https://github.com/Lightning-AI - name: logfire html_url: https://github.com/pydantic/logfire - stars: 3059 + stars: 3172 owner_login: pydantic owner_html_url: https://github.com/pydantic -- name: docarray - html_url: https://github.com/docarray/docarray - stars: 3052 - owner_login: docarray - owner_html_url: https://github.com/docarray +- name: opyrator + html_url: https://github.com/ml-tooling/opyrator + stars: 3122 + owner_login: ml-tooling + owner_html_url: https://github.com/ml-tooling - name: huma html_url: https://github.com/danielgtaylor/huma - stars: 3025 + stars: 3110 owner_login: danielgtaylor owner_html_url: https://github.com/danielgtaylor +- name: docarray + html_url: https://github.com/docarray/docarray + stars: 3068 + owner_login: docarray + owner_html_url: https://github.com/docarray - name: fastapi-realworld-example-app html_url: https://github.com/nsidnev/fastapi-realworld-example-app - stars: 2883 + stars: 2892 owner_login: nsidnev owner_html_url: https://github.com/nsidnev +- name: Kokoro-FastAPI + html_url: https://github.com/remsky/Kokoro-FastAPI + stars: 2883 + owner_login: remsky + owner_html_url: https://github.com/remsky - name: uvicorn-gunicorn-fastapi-docker html_url: https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker - stars: 2756 + stars: 2770 owner_login: tiangolo owner_html_url: https://github.com/tiangolo - name: tracecat html_url: https://github.com/TracecatHQ/tracecat - stars: 2587 + stars: 2740 owner_login: TracecatHQ owner_html_url: https://github.com/TracecatHQ - name: best-of-web-python html_url: https://github.com/ml-tooling/best-of-web-python - stars: 2502 + stars: 2517 owner_login: ml-tooling owner_html_url: https://github.com/ml-tooling -- name: Kokoro-FastAPI - html_url: https://github.com/remsky/Kokoro-FastAPI - stars: 2500 - owner_login: remsky - owner_html_url: https://github.com/remsky - name: RasaGPT html_url: https://github.com/paulpierre/RasaGPT - stars: 2419 + stars: 2423 owner_login: paulpierre owner_html_url: https://github.com/paulpierre - name: fastapi-react html_url: https://github.com/Buuntu/fastapi-react - stars: 2350 + stars: 2376 owner_login: Buuntu owner_html_url: https://github.com/Buuntu -- name: nextpy - html_url: https://github.com/dot-agent/nextpy - stars: 2277 - owner_login: dot-agent - owner_html_url: https://github.com/dot-agent - name: FastAPI-template html_url: https://github.com/s3rius/FastAPI-template - stars: 2273 + stars: 2301 owner_login: s3rius owner_html_url: https://github.com/s3rius -- name: 30-Days-of-Python - html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python - stars: 2183 - owner_login: codingforentrepreneurs - owner_html_url: https://github.com/codingforentrepreneurs +- name: nextpy + html_url: https://github.com/dot-agent/nextpy + stars: 2289 + owner_login: dot-agent + owner_html_url: https://github.com/dot-agent - name: sqladmin html_url: https://github.com/aminalaee/sqladmin - stars: 2141 + stars: 2196 owner_login: aminalaee owner_html_url: https://github.com/aminalaee +- name: 30-Days-of-Python + html_url: https://github.com/codingforentrepreneurs/30-Days-of-Python + stars: 2179 + owner_login: codingforentrepreneurs + owner_html_url: https://github.com/codingforentrepreneurs - name: langserve html_url: https://github.com/langchain-ai/langserve - stars: 2070 + stars: 2098 owner_login: langchain-ai owner_html_url: https://github.com/langchain-ai - name: fastapi-utils html_url: https://github.com/fastapiutils/fastapi-utils - stars: 2063 + stars: 2077 owner_login: fastapiutils owner_html_url: https://github.com/fastapiutils -- name: solara - html_url: https://github.com/widgetti/solara - stars: 2028 - owner_login: widgetti - owner_html_url: https://github.com/widgetti - name: supabase-py html_url: https://github.com/supabase/supabase-py - stars: 1996 + stars: 2047 owner_login: supabase owner_html_url: https://github.com/supabase +- name: solara + html_url: https://github.com/widgetti/solara + stars: 2044 + owner_login: widgetti + owner_html_url: https://github.com/widgetti - name: mangum html_url: https://github.com/Kludex/mangum - stars: 1870 + stars: 1905 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: python-week-2022 html_url: https://github.com/rochacbruno/python-week-2022 - stars: 1827 + stars: 1823 owner_login: rochacbruno owner_html_url: https://github.com/rochacbruno -- name: SurfSense - html_url: https://github.com/MODSetter/SurfSense - stars: 1763 - owner_login: MODSetter - owner_html_url: https://github.com/MODSetter - name: manage-fastapi html_url: https://github.com/ycd/manage-fastapi - stars: 1743 + stars: 1754 owner_login: ycd owner_html_url: https://github.com/ycd - name: agentkit html_url: https://github.com/BCG-X-Official/agentkit - stars: 1741 + stars: 1746 owner_login: BCG-X-Official owner_html_url: https://github.com/BCG-X-Official - name: ormar html_url: https://github.com/collerek/ormar - stars: 1730 + stars: 1742 owner_login: collerek owner_html_url: https://github.com/collerek - name: langchain-serve html_url: https://github.com/jina-ai/langchain-serve - stars: 1631 + stars: 1630 owner_login: jina-ai owner_html_url: https://github.com/jina-ai - name: termpair html_url: https://github.com/cs01/termpair - stars: 1610 + stars: 1611 owner_login: cs01 owner_html_url: https://github.com/cs01 - name: piccolo html_url: https://github.com/piccolo-orm/piccolo - stars: 1588 + stars: 1609 owner_login: piccolo-orm owner_html_url: https://github.com/piccolo-orm - name: coronavirus-tracker-api @@ -270,137 +270,152 @@ owner_html_url: https://github.com/ExpDev07 - name: fastapi-cache html_url: https://github.com/long2ice/fastapi-cache - stars: 1552 + stars: 1575 owner_login: long2ice owner_html_url: https://github.com/long2ice - name: openapi-python-client html_url: https://github.com/openapi-generators/openapi-python-client - stars: 1536 + stars: 1568 owner_login: openapi-generators owner_html_url: https://github.com/openapi-generators - name: fastapi-crudrouter html_url: https://github.com/awtkns/fastapi-crudrouter - stars: 1491 + stars: 1508 owner_login: awtkns owner_html_url: https://github.com/awtkns - name: slowapi html_url: https://github.com/laurentS/slowapi - stars: 1450 + stars: 1501 owner_login: laurentS owner_html_url: https://github.com/laurentS - name: awesome-fastapi-projects html_url: https://github.com/Kludex/awesome-fastapi-projects - stars: 1443 + stars: 1453 owner_login: Kludex owner_html_url: https://github.com/Kludex - name: awesome-python-resources html_url: https://github.com/DjangoEx/awesome-python-resources - stars: 1387 + stars: 1390 owner_login: DjangoEx owner_html_url: https://github.com/DjangoEx -- name: budgetml - html_url: https://github.com/ebhy/budgetml - stars: 1341 - owner_login: ebhy - owner_html_url: https://github.com/ebhy - name: fastapi-pagination html_url: https://github.com/uriyyo/fastapi-pagination - stars: 1331 + stars: 1353 owner_login: uriyyo owner_html_url: https://github.com/uriyyo +- name: budgetml + html_url: https://github.com/ebhy/budgetml + stars: 1342 + owner_login: ebhy + owner_html_url: https://github.com/ebhy - name: fastapi-boilerplate html_url: https://github.com/teamhide/fastapi-boilerplate - stars: 1299 + stars: 1325 owner_login: teamhide owner_html_url: https://github.com/teamhide +- name: vue-fastapi-admin + html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin + stars: 1306 + owner_login: mizhexiaoxiao + owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-amis-admin html_url: https://github.com/amisadmin/fastapi-amis-admin - stars: 1235 + stars: 1256 owner_login: amisadmin owner_html_url: https://github.com/amisadmin - name: fastapi-tutorial html_url: https://github.com/liaogx/fastapi-tutorial - stars: 1222 + stars: 1245 owner_login: liaogx owner_html_url: https://github.com/liaogx -- name: vue-fastapi-admin - html_url: https://github.com/mizhexiaoxiao/vue-fastapi-admin - stars: 1190 - owner_login: mizhexiaoxiao - owner_html_url: https://github.com/mizhexiaoxiao - name: fastapi-code-generator html_url: https://github.com/koxudaxi/fastapi-code-generator - stars: 1180 + stars: 1201 owner_login: koxudaxi owner_html_url: https://github.com/koxudaxi +- name: bracket + html_url: https://github.com/evroon/bracket + stars: 1201 + owner_login: evroon + owner_html_url: https://github.com/evroon - name: bolt-python html_url: https://github.com/slackapi/bolt-python - stars: 1166 + stars: 1179 owner_login: slackapi owner_html_url: https://github.com/slackapi - name: fastapi_production_template html_url: https://github.com/zhanymkanov/fastapi_production_template - stars: 1134 + stars: 1147 owner_login: zhanymkanov owner_html_url: https://github.com/zhanymkanov -- name: langchain-extract - html_url: https://github.com/langchain-ai/langchain-extract - stars: 1127 - owner_login: langchain-ai - owner_html_url: https://github.com/langchain-ai -- name: odmantic - html_url: https://github.com/art049/odmantic - stars: 1115 - owner_login: art049 - owner_html_url: https://github.com/art049 - name: prometheus-fastapi-instrumentator html_url: https://github.com/trallnag/prometheus-fastapi-instrumentator - stars: 1112 + stars: 1145 owner_login: trallnag owner_html_url: https://github.com/trallnag - name: bedrock-chat html_url: https://github.com/aws-samples/bedrock-chat - stars: 1107 + stars: 1143 owner_login: aws-samples owner_html_url: https://github.com/aws-samples +- name: langchain-extract + html_url: https://github.com/langchain-ai/langchain-extract + stars: 1134 + owner_login: langchain-ai + owner_html_url: https://github.com/langchain-ai +- name: odmantic + html_url: https://github.com/art049/odmantic + stars: 1118 + owner_login: art049 + owner_html_url: https://github.com/art049 - name: fastapi-alembic-sqlmodel-async html_url: https://github.com/jonra1993/fastapi-alembic-sqlmodel-async - stars: 1094 + stars: 1110 owner_login: jonra1993 owner_html_url: https://github.com/jonra1993 +- name: fastcrud + html_url: https://github.com/benavlabs/fastcrud + stars: 1080 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs - name: restish html_url: https://github.com/rest-sh/restish - stars: 1041 + stars: 1056 owner_login: rest-sh owner_html_url: https://github.com/rest-sh -- name: fastcrud - html_url: https://github.com/igorbenav/fastcrud - stars: 1036 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav -- name: runhouse - html_url: https://github.com/run-house/runhouse - stars: 1022 - owner_login: run-house - owner_html_url: https://github.com/run-house - name: fastapi_best_architecture html_url: https://github.com/fastapi-practices/fastapi_best_architecture - stars: 997 + stars: 1050 owner_login: fastapi-practices owner_html_url: https://github.com/fastapi-practices +- name: runhouse + html_url: https://github.com/run-house/runhouse + stars: 1034 + owner_login: run-house + owner_html_url: https://github.com/run-house +- name: autollm + html_url: https://github.com/viddexa/autollm + stars: 992 + owner_login: viddexa + owner_html_url: https://github.com/viddexa - name: lanarky html_url: https://github.com/ajndkr/lanarky stars: 990 owner_login: ajndkr owner_html_url: https://github.com/ajndkr -- name: autollm - html_url: https://github.com/viddexa/autollm - stars: 990 - owner_login: viddexa - owner_html_url: https://github.com/viddexa +- name: FastAPI-boilerplate + html_url: https://github.com/benavlabs/FastAPI-boilerplate + stars: 985 + owner_login: benavlabs + owner_html_url: https://github.com/benavlabs +- name: authx + html_url: https://github.com/yezz123/authx + stars: 938 + owner_login: yezz123 + owner_html_url: https://github.com/yezz123 - name: secure html_url: https://github.com/TypeError/secure - stars: 932 + stars: 935 owner_login: TypeError owner_html_url: https://github.com/TypeError - name: langcorn @@ -408,88 +423,73 @@ stars: 925 owner_login: msoedov owner_html_url: https://github.com/msoedov -- name: FastAPI-boilerplate - html_url: https://github.com/igorbenav/FastAPI-boilerplate - stars: 925 - owner_login: igorbenav - owner_html_url: https://github.com/igorbenav -- name: authx - html_url: https://github.com/yezz123/authx - stars: 913 - owner_login: yezz123 - owner_html_url: https://github.com/yezz123 - name: energy-forecasting html_url: https://github.com/iusztinpaul/energy-forecasting - stars: 907 + stars: 913 owner_login: iusztinpaul owner_html_url: https://github.com/iusztinpaul - name: titiler html_url: https://github.com/developmentseed/titiler - stars: 873 + stars: 886 owner_login: developmentseed owner_html_url: https://github.com/developmentseed +- name: flock + html_url: https://github.com/Onelevenvy/flock + stars: 866 + owner_login: Onelevenvy + owner_html_url: https://github.com/Onelevenvy - name: httpdbg html_url: https://github.com/cle-b/httpdbg - stars: 850 + stars: 863 owner_login: cle-b owner_html_url: https://github.com/cle-b - name: marker-api html_url: https://github.com/adithya-s-k/marker-api - stars: 844 + stars: 859 owner_login: adithya-s-k owner_html_url: https://github.com/adithya-s-k - name: ludic html_url: https://github.com/getludic/ludic - stars: 842 + stars: 845 owner_login: getludic owner_html_url: https://github.com/getludic -- name: flock - html_url: https://github.com/Onelevenvy/flock - stars: 805 - owner_login: Onelevenvy - owner_html_url: https://github.com/Onelevenvy -- name: fastapi-observability - html_url: https://github.com/blueswen/fastapi-observability - stars: 797 - owner_login: blueswen - owner_html_url: https://github.com/blueswen - name: fastapi-do-zero html_url: https://github.com/dunossauro/fastapi-do-zero - stars: 786 + stars: 827 owner_login: dunossauro owner_html_url: https://github.com/dunossauro +- name: fastapi-observability + html_url: https://github.com/blueswen/fastapi-observability + stars: 823 + owner_login: blueswen + owner_html_url: https://github.com/blueswen +- name: fastapi-langgraph-agent-production-ready-template + html_url: https://github.com/wassim249/fastapi-langgraph-agent-production-ready-template + stars: 803 + owner_login: wassim249 + owner_html_url: https://github.com/wassim249 - name: fastapi-mail html_url: https://github.com/sabuhish/fastapi-mail - stars: 781 + stars: 798 owner_login: sabuhish owner_html_url: https://github.com/sabuhish - name: starlette-admin html_url: https://github.com/jowilf/starlette-admin - stars: 764 + stars: 785 owner_login: jowilf owner_html_url: https://github.com/jowilf - name: lccn_predictor html_url: https://github.com/baoliay2008/lccn_predictor - stars: 759 + stars: 767 owner_login: baoliay2008 owner_html_url: https://github.com/baoliay2008 +- name: aktools + html_url: https://github.com/akfamily/aktools + stars: 759 + owner_login: akfamily + owner_html_url: https://github.com/akfamily - name: KonomiTV html_url: https://github.com/tsukumijima/KonomiTV - stars: 741 + stars: 748 owner_login: tsukumijima owner_html_url: https://github.com/tsukumijima -- name: FastAPI-Backend-Template - html_url: https://github.com/Aeternalis-Ingenium/FastAPI-Backend-Template - stars: 734 - owner_login: Aeternalis-Ingenium - owner_html_url: https://github.com/Aeternalis-Ingenium -- name: learn-generative-ai - html_url: https://github.com/panaverse/learn-generative-ai - stars: 731 - owner_login: panaverse - owner_html_url: https://github.com/panaverse -- name: annotated-py-projects - html_url: https://github.com/hhstore/annotated-py-projects - stars: 730 - owner_login: hhstore - owner_html_url: https://github.com/hhstore diff --git a/docs/en/data/translation_reviewers.yml b/docs/en/data/translation_reviewers.yml index b544633fd..aad3e4fac 100644 --- a/docs/en/data/translation_reviewers.yml +++ b/docs/en/data/translation_reviewers.yml @@ -10,7 +10,7 @@ Xewus: url: https://github.com/Xewus sodaMelon: login: sodaMelon - count: 124 + count: 125 avatarUrl: https://avatars.githubusercontent.com/u/66295123?u=be939db90f1119efee9e6110cc05066ff1f40f00&v=4 url: https://github.com/sodaMelon ceb10n: @@ -646,7 +646,7 @@ riroan: MinLee0210: login: MinLee0210 count: 9 - avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=175010b24bc3a15a5705424badf9b18823bfd67d&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/57653278?u=3c4b6e9d69bff148d09fe022ddf867e564acaa44&v=4 url: https://github.com/MinLee0210 yodai-yodai: login: yodai-yodai @@ -723,6 +723,11 @@ minaton-ru: count: 8 avatarUrl: https://avatars.githubusercontent.com/u/53541518?u=67336ca11a85493f75031508aade588dad3b9910&v=4 url: https://github.com/minaton-ru +sungchan1: + login: sungchan1 + count: 8 + avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 + url: https://github.com/sungchan1 Serrones: login: Serrones count: 7 @@ -768,11 +773,11 @@ d2a-raudenaerde: count: 7 avatarUrl: https://avatars.githubusercontent.com/u/5213150?v=4 url: https://github.com/d2a-raudenaerde -sungchan1: - login: sungchan1 +Zerohertz: + login: Zerohertz count: 7 - avatarUrl: https://avatars.githubusercontent.com/u/28076127?u=a816d86ef3e60450a7225f128caf9a394c9320f9&v=4 - url: https://github.com/sungchan1 + avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=5ebf4d33e73b1ad373154f6cdee44f7cab4d05ba&v=4 + url: https://github.com/Zerohertz deniscapeto: login: deniscapeto count: 6 @@ -921,7 +926,7 @@ Wuerike: jvmazagao: login: jvmazagao count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=f3b2d503b53e6ec8c808f0601b756a063a07f06e&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/22477816?u=2b57addf5830906bf6ae5f25cd4c8c2fa5c2d68e&v=4 url: https://github.com/jvmazagao cun3yt: login: cun3yt @@ -1003,11 +1008,6 @@ devluisrodrigues: count: 5 avatarUrl: https://avatars.githubusercontent.com/u/103431660?u=d9674a3249edc4601d2c712cdebf899918503c3a&v=4 url: https://github.com/devluisrodrigues -Zerohertz: - login: Zerohertz - count: 5 - avatarUrl: https://avatars.githubusercontent.com/u/42334717?u=c6acda352c866b1747921e0ff8782b58571d849e&v=4 - url: https://github.com/Zerohertz 11kkw: login: 11kkw count: 5 @@ -1386,7 +1386,7 @@ tienduong-21: soroushgh1: login: soroushgh1 count: 3 - avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=e4d791c982cf7899c69f6baeebc4d7bbe86635d1&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/178516095?u=5e26f6a5f66cdb32d7b56e6ab362bf18ba7858b9&v=4 url: https://github.com/soroushgh1 zbellos: login: zbellos @@ -1508,11 +1508,11 @@ tyzh-dev: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/51972581?u=ba3882da7c009918a8e2d6b9ead31c89f09c922d&v=4 url: https://github.com/tyzh-dev -WaFeeAL: - login: WaFeeAL +yurkevich-dev: + login: yurkevich-dev count: 2 avatarUrl: https://avatars.githubusercontent.com/u/45145188?u=db2de8c186073d95693279dcf085fcebffab57d0&v=4 - url: https://github.com/WaFeeAL + url: https://github.com/yurkevich-dev emp7yhead: login: emp7yhead count: 2 @@ -1566,7 +1566,7 @@ raphaelauv: Fahad-Md-Kamal: login: Fahad-Md-Kamal count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=84abea85e59c30b2e3bc700ae42424f3fe704332&v=4 + avatarUrl: https://avatars.githubusercontent.com/u/34704464?u=f96c6cbd25b06274e3ff96bc961ca91b3f876481&v=4 url: https://github.com/Fahad-Md-Kamal zxcq544: login: zxcq544 @@ -1733,6 +1733,11 @@ Heumhub: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/173761521?v=4 url: https://github.com/Heumhub +manumolina: + login: manumolina + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/2404208?u=fdc5502910f8dec814b2477f89587b9e45fac846&v=4 + url: https://github.com/manumolina logan2d5: login: logan2d5 count: 2 @@ -1768,6 +1773,11 @@ EgorOnishchuk: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 url: https://github.com/EgorOnishchuk +iamantonreznik: + login: iamantonreznik + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/112612414?u=bf6de9a1ab17326fe14de0709719fff3826526d0&v=4 + url: https://github.com/iamantonreznik Azazul123: login: Azazul123 count: 2 diff --git a/docs/en/data/translators.yml b/docs/en/data/translators.yml index d8593f53f..51d05003b 100644 --- a/docs/en/data/translators.yml +++ b/docs/en/data/translators.yml @@ -13,6 +13,11 @@ ceb10n: count: 27 avatarUrl: https://avatars.githubusercontent.com/u/235213?u=edcce471814a1eba9f0cdaa4cd0de18921a940a6&v=4 url: https://github.com/ceb10n +valentinDruzhinin: + login: valentinDruzhinin + count: 24 + avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 + url: https://github.com/valentinDruzhinin tokusumi: login: tokusumi count: 23 @@ -33,11 +38,6 @@ waynerv: count: 20 avatarUrl: https://avatars.githubusercontent.com/u/39515546?u=ec35139777597cdbbbddda29bf8b9d4396b429a9&v=4 url: https://github.com/waynerv -valentinDruzhinin: - login: valentinDruzhinin - count: 18 - avatarUrl: https://avatars.githubusercontent.com/u/12831905?u=aae1ebc675c91e8fa582df4fcc4fc4128106344d&v=4 - url: https://github.com/valentinDruzhinin AlertRED: login: AlertRED count: 16 @@ -328,6 +328,11 @@ nahyunkeem: count: 3 avatarUrl: https://avatars.githubusercontent.com/u/174440096?u=e12401d492eee58570f8914d0872b52e421a776e&v=4 url: https://github.com/nahyunkeem +timothy-jeong: + login: timothy-jeong + count: 3 + avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 + url: https://github.com/timothy-jeong gerry-sabar: login: gerry-sabar count: 3 @@ -468,6 +473,11 @@ imtiaz101325: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/54007087?u=194d972b501b9ea9d2ddeaed757c492936e0121a&v=4 url: https://github.com/imtiaz101325 +fabianfalon: + login: fabianfalon + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/3700760?u=95f69e31280b17ac22299cdcd345323b142fe0af&v=4 + url: https://github.com/fabianfalon waketzheng: login: waketzheng count: 2 @@ -498,11 +508,6 @@ saeye: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/62229734?u=312d619db2588b60d5d5bde65260a2f44fdc6c76&v=4 url: https://github.com/saeye -timothy-jeong: - login: timothy-jeong - count: 2 - avatarUrl: https://avatars.githubusercontent.com/u/53824764?u=db3d0cea2f5fab64d810113c5039a369699a2774&v=4 - url: https://github.com/timothy-jeong 11kkw: login: 11kkw count: 2 @@ -513,3 +518,8 @@ yes0ng: count: 2 avatarUrl: https://avatars.githubusercontent.com/u/25501794?u=3aed18b0d491e0220a167a1e9e58bea3638c6707&v=4 url: https://github.com/yes0ng +EgorOnishchuk: + login: EgorOnishchuk + count: 2 + avatarUrl: https://avatars.githubusercontent.com/u/120256301?v=4 + url: https://github.com/EgorOnishchuk diff --git a/docs/en/docs/img/sponsors/dribia.png b/docs/en/docs/img/sponsors/dribia.png new file mode 100644 index 000000000..f40e14086 Binary files /dev/null and b/docs/en/docs/img/sponsors/dribia.png differ diff --git a/docs/en/docs/release-notes.md b/docs/en/docs/release-notes.md index 124f3c84b..b5d7f8d3a 100644 --- a/docs/en/docs/release-notes.md +++ b/docs/en/docs/release-notes.md @@ -24,6 +24,21 @@ hide: ### Translations +* ✏️ Remove redundant words in docs/zh/docs/python-types.md. PR [#13774](https://github.com/fastapi/fastapi/pull/13774) by [@CharleeWa](https://github.com/CharleeWa). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-param-models.md`. PR [#13748](https://github.com/fastapi/fastapi/pull/13748) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Bengali translation for `docs/bn/docs/environment-variables.md`. PR [#13629](https://github.com/fastapi/fastapi/pull/13629) by [@SakibSibly](https://github.com/SakibSibly). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/query-params-str-validations.md` page. PR [#13546](https://github.com/fastapi/fastapi/pull/13546) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/cookie-param-models.md`. PR [#13616](https://github.com/fastapi/fastapi/pull/13616) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). +* 🌐 Add Korean translation for `docs/ko/docs/tutorial/extra-models.md`. PR [#13063](https://github.com/fastapi/fastapi/pull/13063) by [@timothy-jeong](https://github.com/timothy-jeong). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/path-params-numeric-validations.md` page. PR [#13548](https://github.com/fastapi/fastapi/pull/13548) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/middleware.md` page. PR [#13520](https://github.com/fastapi/fastapi/pull/13520) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/background-tasks.md` page. PR [#13502](https://github.com/fastapi/fastapi/pull/13502) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/cors.md` page. PR [#13519](https://github.com/fastapi/fastapi/pull/13519) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Update Korean translation for `docs/ko/docs/advanced/events.md`. PR [#13487](https://github.com/fastapi/fastapi/pull/13487) by [@bom1215](https://github.com/bom1215). +* 🌐 Add Ukrainian translation for `docs/uk/docs/tutorial/handling-errors.md` page. PR [#13420](https://github.com/fastapi/fastapi/pull/13420) by [@valentinDruzhinin](https://github.com/valentinDruzhinin). +* 🌐 Add Russian translation for `docs/ru/docs/tutorial/request-form-models.md`. PR [#13552](https://github.com/fastapi/fastapi/pull/13552) by [@EgorOnishchuk](https://github.com/EgorOnishchuk). +* 📝 Fix internal anchor link in Spanish deployment docs. PR [#13737](https://github.com/fastapi/fastapi/pull/13737) by [@fabianfalon](https://github.com/fabianfalon). +* 🌐 Update Korean translation for `docs/ko/docs/virtual-environments.md`. PR [#13630](https://github.com/fastapi/fastapi/pull/13630) by [@sungchan1](https://github.com/sungchan1). * 🌐 Add Russian translation for `docs/ru/docs/tutorial/header-param-models.md`. PR [#13526](https://github.com/fastapi/fastapi/pull/13526) by [@minaton-ru](https://github.com/minaton-ru). * 🌐 Update Chinese translation for `docs/zh/docs/tutorial/index.md`. PR [#13374](https://github.com/fastapi/fastapi/pull/13374) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). * 🌐 Update Chinese translation for `docs/zh/docs/deployment/manually.md`. PR [#13324](https://github.com/fastapi/fastapi/pull/13324) by [@Zhongheng-Cheng](https://github.com/Zhongheng-Cheng). @@ -32,6 +47,15 @@ hide: ### Internal +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13757](https://github.com/fastapi/fastapi/pull/13757) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). +* ⬆ Bump griffe-typingdoc from 0.2.7 to 0.2.8. PR [#13751](https://github.com/fastapi/fastapi/pull/13751) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 🍱 Update sponsors: Dribia badge size. PR [#13773](https://github.com/fastapi/fastapi/pull/13773) by [@tiangolo](https://github.com/tiangolo). +* 🔧 Update sponsors: add Dribia. PR [#13771](https://github.com/fastapi/fastapi/pull/13771) by [@tiangolo](https://github.com/tiangolo). +* ⬆ Bump typer from 0.15.3 to 0.16.0. PR [#13752](https://github.com/fastapi/fastapi/pull/13752) by [@dependabot[bot]](https://github.com/apps/dependabot). +* 👥 Update FastAPI GitHub topic repositories. PR [#13754](https://github.com/fastapi/fastapi/pull/13754) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Sponsors. PR [#13750](https://github.com/fastapi/fastapi/pull/13750) by [@tiangolo](https://github.com/tiangolo). +* 👥 Update FastAPI People - Contributors and Translators. PR [#13749](https://github.com/fastapi/fastapi/pull/13749) by [@tiangolo](https://github.com/tiangolo). +* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13736](https://github.com/fastapi/fastapi/pull/13736) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci). * 🔧 Update sponsors: Add InterviewPal. PR [#13728](https://github.com/fastapi/fastapi/pull/13728) by [@tiangolo](https://github.com/tiangolo). * 🔧 Remove Google Analytics. PR [#13727](https://github.com/fastapi/fastapi/pull/13727) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update sponsors: remove MongoDB. PR [#13725](https://github.com/fastapi/fastapi/pull/13725) by [@tiangolo](https://github.com/tiangolo). diff --git a/docs/es/docs/deployment/docker.md b/docs/es/docs/deployment/docker.md index ff204f078..3a39d3661 100644 --- a/docs/es/docs/deployment/docker.md +++ b/docs/es/docs/deployment/docker.md @@ -6,7 +6,7 @@ Usar contenedores de Linux tiene varias ventajas, incluyendo **seguridad**, **re /// tip | Consejo -¿Tienes prisa y ya conoces esto? Salta al [`Dockerfile` más abajo 👇](#build-a-docker-image-for-fastapi). +¿Tienes prisa y ya conoces esto? Salta al [`Dockerfile` más abajo 👇](#construir-una-imagen-de-docker-para-fastapi). /// diff --git a/docs/ko/docs/advanced/events.md b/docs/ko/docs/advanced/events.md index ae349e7be..5f8fe0f1e 100644 --- a/docs/ko/docs/advanced/events.md +++ b/docs/ko/docs/advanced/events.md @@ -1,53 +1,165 @@ -# 이벤트: startup과 shutdown +# Lifespan 이벤트 -필요에 따라 응용 프로그램이 시작되기 전이나 종료될 때 실행되는 이벤트 핸들러(함수)를 정의할 수 있습니다. +애플리케이션 **시작 전**에 실행되어야 하는 로직(코드)을 정의할 수 있습니다. 이는 이 코드가 **한 번**만 실행되며, **애플리케이션이 요청을 받기 시작하기 전**에 실행된다는 의미입니다. -이 함수들은 `async def` 또는 평범하게 `def`으로 선언할 수 있습니다. +마찬가지로, 애플리케이션이 **종료될 때** 실행되어야 하는 로직(코드)을 정의할 수 있습니다. 이 경우, 이 코드는 **한 번**만 실행되며, **여러 요청을 처리한 후**에 실행됩니다. + +이 코드가 애플리케이션이 **요청을 받기 시작하기 전에** 실행되고, 요청 처리가 끝난 후 **종료 직전에** 실행되기 때문에 전체 애플리케이션의 **수명(Lifespan)**을 다룹니다. (잠시 후 "수명"이라는 단어가 중요해집니다 😉) + +이 방법은 전체 애플리케이션에서 사용해야 하는 **자원**을 설정하거나 요청 간에 **공유되는** 자원을 설정하고, 또는 그 후에 **정리**하는 데 매우 유용할 수 있습니다. 예를 들어, 데이터베이스 연결 풀 또는 공유되는 머신러닝 모델을 로드하는 경우입니다. + + +## 사용 사례 + +먼저 **사용 사례**를 예로 들어보고, 이를 어떻게 해결할 수 있는지 살펴보겠습니다. + +우리가 요청을 처리하기 위해 사용하고 싶은 **머신러닝 모델**이 있다고 상상해 봅시다. 🤖 + +이 모델들은 요청 간에 공유되므로, 요청마다 모델이 하나씩 있는 것이 아니라, 여러 요청에서 동일한 모델을 사용합니다. + +모델을 로드하는 데 **상당한 시간이 걸린다고 상상해 봅시다**, 왜냐하면 모델이 **디스크에서 많은 데이터를 읽어야** 하기 때문입니다. 따라서 모든 요청에 대해 모델을 매번 로드하고 싶지 않습니다. + +모듈/파일의 최상위에서 모델을 로드할 수도 있지만, 그러면 **모델을 로드하는데** 시간이 걸리기 때문에, 단순한 자동화된 테스트를 실행할 때도 모델이 로드될 때까지 기다려야 해서 **테스트 속도가 느려집니다**. + +이 문제를 해결하려고 하는 것입니다. 요청을 처리하기 전에 모델을 로드하되, 애플리케이션이 요청을 받기 시작하기 직전에만 로드하고, 코드가 로드되는 동안은 로드하지 않도록 하겠습니다. + +## Lifespan + +`FastAPI` 애플리케이션의 `lifespan` 매개변수와 "컨텍스트 매니저"를 사용하여 *시작*과 *종료* 로직을 정의할 수 있습니다. (컨텍스트 매니저가 무엇인지 잠시 후에 설명드리겠습니다.) + +예제를 통해 시작하고, 그 후에 자세히 살펴보겠습니다. + +우리는 `yield`를 사용하여 비동기 함수 `lifespan()`을 다음과 같이 생성합니다: + +{* ../../docs_src/events/tutorial003.py hl[16,19] *} + +여기서 우리는 모델을 로드하는 비싼 *시작* 작업을 시뮬레이션하고 있습니다. `yield` 앞에서 (가짜) 모델 함수를 머신러닝 모델이 담긴 딕셔너리에 넣습니다. 이 코드는 **애플리케이션이 요청을 받기 시작하기 전**, *시작* 동안에 실행됩니다. + +그리고 `yield` 직후에는 모델을 언로드합니다. 이 코드는 **애플리케이션이 요청 처리 완료 후**, *종료* 직전에 실행됩니다. 예를 들어, 메모리나 GPU와 같은 자원을 해제하는 작업을 할 수 있습니다. + +/// tip | 팁 + +`shutdown`은 애플리케이션을 **종료**할 때 발생합니다. + +새로운 버전을 시작해야 하거나, 그냥 실행을 멈추고 싶을 수도 있습니다. 🤷 + +/// + +### Lifespan 함수 + +먼저 주목할 점은, `yield`를 사용하여 비동기 함수(async function)를 정의하고 있다는 것입니다. 이는 `yield`를 사용한 의존성과 매우 유사합니다. + +{* ../../docs_src/events/tutorial003.py hl[14:19] *} + +함수의 첫 번째 부분, 즉 `yield` 이전의 코드는 애플리케이션이 시작되기 **전에** 실행됩니다. + +그리고 `yield` 이후의 부분은 애플리케이션이 완료된 후 **나중에** 실행됩니다. + +### 비동기 컨텍스트 매니저 + +함수를 확인해보면, `@asynccontextmanager`로 장식되어 있습니다. + +이것은 함수를 "**비동기 컨텍스트 매니저**"라고 불리는 것으로 변환시킵니다. + +{* ../../docs_src/events/tutorial003.py hl[1,13] *} + +파이썬에서 **컨텍스트 매니저**는 `with` 문에서 사용할 수 있는 것입니다. 예를 들어, `open()`은 컨텍스트 매니저로 사용할 수 있습니다: + +```Python +with open("file.txt") as file: + file.read() +``` +최근 버전의 파이썬에서는 **비동기 컨텍스트 매니저**도 있습니다. 이를 `async with`와 함께 사용합니다: + +```Python +async with lifespan(app): + await do_stuff() +``` + +컨텍스트 매니저나 위와 같은 비동기 컨텍스트 매니저를 만들면, `with` 블록에 들어가기 전에 `yield` 이전의 코드가 실행되고, `with` 블록을 벗어난 후에는 `yield` 이후의 코드가 실행됩니다. + +위의 코드 예제에서는 직접 사용하지 않고, FastAPI에 전달하여 사용하도록 합니다. + +`FastAPI` 애플리케이션의 `lifespan` 매개변수는 **비동기 컨텍스트 매니저**를 받기 때문에, 새로운 `lifespan` 비동기 컨텍스트 매니저를 FastAPI에 전달할 수 있습니다. + +{* ../../docs_src/events/tutorial003.py hl[22] *} + +## 대체 이벤트 (사용 중단) /// warning | 경고 -이벤트 핸들러는 주 응용 프로그램에서만 작동합니다. [하위 응용 프로그램 - 마운트](./sub-applications.md){.internal-link target=_blank}에서는 작동하지 않습니다. +*시작*과 *종료*를 처리하는 권장 방법은 위에서 설명한 대로 `FastAPI` 애플리케이션의 `lifespan` 매개변수를 사용하는 것입니다. `lifespan` 매개변수를 제공하면 `startup`과 `shutdown` 이벤트 핸들러는 더 이상 호출되지 않습니다. `lifespan`을 사용할지, 모든 이벤트를 사용할지 선택해야 하며 둘 다 사용할 수는 없습니다. + +이 부분은 건너뛰셔도 좋습니다. /// -## `startup` 이벤트 +*시작*과 *종료* 동안 실행될 이 로직을 정의하는 대체 방법이 있습니다. + +애플리케이션이 시작되기 전에 또는 종료될 때 실행해야 하는 이벤트 핸들러(함수)를 정의할 수 있습니다. -응용 프로그램을 시작하기 전에 실행하려는 함수를 "startup" 이벤트로 선언합니다: +이 함수들은 `async def` 또는 일반 `def`로 선언할 수 있습니다. + +### `startup` 이벤트 + +애플리케이션이 시작되기 전에 실행되어야 하는 함수를 추가하려면, `"startup"` 이벤트로 선언합니다: {* ../../docs_src/events/tutorial001.py hl[8] *} -이 경우 `startup` 이벤트 핸들러 함수는 단순히 몇 가지 값으로 구성된 `dict` 형식의 "데이터베이스"를 초기화합니다. +이 경우, `startup` 이벤트 핸들러 함수는 "database"라는 항목(단지 `dict`)을 일부 값으로 초기화합니다. -하나 이상의 이벤트 핸들러 함수를 추가할 수도 있습니다. +여러 개의 이벤트 핸들러 함수를 추가할 수 있습니다. -그리고 응용 프로그램은 모든 `startup` 이벤트 핸들러가 완료될 때까지 요청을 받지 않습니다. +애플리케이션은 모든 `startup` 이벤트 핸들러가 완료될 때까지 요청을 받기 시작하지 않습니다. -## `shutdown` 이벤트 +### `shutdown` 이벤트 -응용 프로그램이 종료될 때 실행하려는 함수를 추가하려면 `"shutdown"` 이벤트로 선언합니다: +애플리케이션이 종료될 때 실행되어야 하는 함수를 추가하려면, `"shutdown"` 이벤트로 선언합니다: {* ../../docs_src/events/tutorial002.py hl[6] *} -이 예제에서 `shutdown` 이벤트 핸들러 함수는 `"Application shutdown"`이라는 텍스트가 적힌 `log.txt` 파일을 추가할 것입니다. +여기서, `shutdown` 이벤트 핸들러 함수는 `"Application shutdown"`이라는 텍스트를 `log.txt` 파일에 기록합니다. /// info | 정보 -`open()` 함수에서 `mode="a"`는 "추가"를 의미합니다. 따라서 이미 존재하는 파일의 내용을 덮어쓰지 않고 새로운 줄을 추가합니다. +`open()` 함수에서 `mode="a"`는 "추가"를 의미하므로, 파일에 있는 기존 내용은 덮어쓰지 않고 새로운 줄이 추가됩니다. /// /// tip | 팁 -이 예제에서는 파일과 상호작용 하기 위해 파이썬 표준 함수인 `open()`을 사용하고 있습니다. +이 경우, 우리는 표준 파이썬 `open()` 함수를 사용하여 파일과 상호작용하고 있습니다. -따라서 디스크에 데이터를 쓰기 위해 "대기"가 필요한 I/O (입력/출력) 작업을 수행합니다. +따라서 I/O(입출력) 작업이 포함되어 있어 디스크에 기록되는 것을 "기다리는" 과정이 필요합니다. -그러나 `open()`은 `async`와 `await`을 사용하지 않기 때문에 이벤트 핸들러 함수는 `async def`가 아닌 표준 `def`로 선언하고 있습니다. +하지만 `open()`은 `async`와 `await`를 사용하지 않습니다. + +그래서 우리는 이벤트 핸들러 함수를 `async def` 대신 일반 `def`로 선언합니다. /// +### `startup`과 `shutdown`을 함께 사용 + +*시작*과 *종료* 로직이 연결될 가능성이 높습니다. 예를 들어, 무언가를 시작한 후 끝내거나, 자원을 획득한 후 해제하는 등의 작업을 할 수 있습니다. + +이러한 작업을 별도의 함수로 처리하면 서로 로직이나 변수를 공유하지 않기 때문에 더 어려워집니다. 값들을 전역 변수에 저장하거나 비슷한 트릭을 사용해야 할 수 있습니다. + +그렇기 때문에 위에서 설명한 대로 `lifespan`을 사용하는 것이 권장됩니다. + +## 기술적 세부사항 + +호기심 많은 분들을 위한 기술적인 세부사항입니다. 🤓 + +ASGI 기술 사양에 따르면, 이는 Lifespan Protocol의 일부이며, `startup`과 `shutdown`이라는 이벤트를 정의합니다. + /// info | 정보 -이벤트 핸들러에 관한 내용은 Starlette 이벤트 문서에서 추가로 확인할 수 있습니다. +Starlette의 `lifespan` 핸들러에 대해 더 읽고 싶다면 Starlette의 Lifespan 문서에서 확인할 수 있습니다. + +이 문서에는 코드의 다른 영역에서 사용할 수 있는 lifespan 상태를 처리하는 방법도 포함되어 있습니다. /// + +## 서브 애플리케이션 + +🚨 이 lifespan 이벤트(`startup`과 `shutdown`)는 메인 애플리케이션에 대해서만 실행되며, [서브 애플리케이션 - Mounts](sub-applications.md){.internal-link target=_blank}에는 실행되지 않음을 유의하세요. diff --git a/docs/ko/docs/tutorial/extra-models.md b/docs/ko/docs/tutorial/extra-models.md new file mode 100644 index 000000000..8e4559061 --- /dev/null +++ b/docs/ko/docs/tutorial/extra-models.md @@ -0,0 +1,223 @@ +# 추가 모델 + +지난 예제에 이어서, 연관된 모델을 여러개 갖는 것은 흔한 일입니다. + +특히 사용자 모델의 경우에 그러한데, 왜냐하면: + +* **입력 모델** 은 비밀번호를 가져야 합니다. +* **출력 모델** 은 비밀번호를 가지면 안됩니다. +* **데이터베이스 모델** 은 해시처리된 비밀번호를 가질 것입니다. + +/// danger | 위험 + +절대 사용자의 비밀번호를 평문으로 저장하지 마세요. 항상 이후에 검증 가능한 "안전한 해시(secure hash)"로 저장하세요. + +만약 이게 무엇인지 모르겠다면, [security chapters](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}.에서 비밀번호 해시에 대해 배울 수 있습니다. + +/// + +## 다중 모델 + +아래는 비밀번호 필드와 해당 필드가 사용되는 위치를 포함하여, 각 모델들이 어떤 형태를 가질 수 있는지 전반적인 예시입니다: + +{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *} + + +/// info | 정보 + +Pydantic v1에서는 해당 메서드가 `.dict()`로 불렸으며, Pydantic v2에서는 `.model_dump()`로 이름이 변경되었습니다. `.dict()`는 여전히 지원되지만 더 이상 권장되지 않습니다. + +여기에서 사용하는 예제는 Pydantic v1과의 호환성을 위해 `.dict()`를 사용하지만, Pydantic v2를 사용할 수 있다면 `.model_dump()`를 사용하는 것이 좋습니다. + +/// + +### `**user_in.dict()` 에 대하여 + +#### Pydantic의 `.dict()` + +`user_in`은 Pydantic 모델 클래스인 `UserIn`입니다. + +Pydantic 모델은 모델 데이터를 포함한 `dict`를 반환하는 `.dict()` 메서드를 제공합니다. + +따라서, 다음과 같이 Pydantic 객체 `user_in`을 생성할 수 있습니다: + +```Python +user_in = UserIn(username="john", password="secret", email="john.doe@example.com") +``` + +그 다음, 다음과 같이 호출합니다: + +```Python +user_dict = user_in.dict() +``` + +이제 변수 `user_dict`에 데이터가 포함된 `dict`를 가지게 됩니다(이는 Pydantic 모델 객체가 아닌 `dict`입니다). + +그리고 다음과 같이 호출하면: + +```Python +print(user_dict) +``` + +Python의 `dict`가 다음과 같이 출력됩니다: + +```Python +{ + 'username': 'john', + 'password': 'secret', + 'email': 'john.doe@example.com', + 'full_name': None, +} +``` + +#### `dict` 언패킹(Unpacking) + +`user_dict`와 같은 `dict`를 함수(또는 클래스)에 `**user_dict`로 전달하면, Python은 이를 "언팩(unpack)"합니다. 이 과정에서 `user_dict`의 키와 값을 각각 키-값 인자로 직접 전달합니다. + +따라서, 위에서 생성한 `user_dict`를 사용하여 다음과 같이 작성하면: + +```Python +UserInDB(**user_dict) +``` + +다음과 같은 결과를 생성합니다: + +```Python +UserInDB( + username="john", + password="secret", + email="john.doe@example.com", + full_name=None, +) +``` + +혹은 더 정확히 말하자면, `user_dict`를 직접 사용하는 것은, 나중에 어떤 값이 추가되더라도 아래와 동일한 효과를 냅니다: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], +) +``` + +#### 다른 모델 데이터로 새 Pydantic 모델 생성 + +위의 예제에서 `user_in.dict()`로부터 `user_dict`를 생성한 것처럼, 아래 코드는: + +```Python +user_dict = user_in.dict() +UserInDB(**user_dict) +``` + +다음과 동일합니다: + +```Python +UserInDB(**user_in.dict()) +``` + +...왜냐하면 `user_in.dict()`는 `dict`이며, 이를 `**`로 Python이 "언팩(unpack)"하도록 하여 `UserInDB`에 전달하기 때문입니다. + +따라서, 다른 Pydantic 모델의 데이터를 사용하여 새로운 Pydantic 모델을 생성할 수 있습니다. + +#### `dict` 언패킹(Unpacking)과 추가 키워드 + +그리고 다음과 같이 추가 키워드 인자 `hashed_password=hashed_password`를 추가하면: + +```Python +UserInDB(**user_in.dict(), hashed_password=hashed_password) +``` + +다음과 같은 결과를 생성합니다: + +```Python +UserInDB( + username = user_dict["username"], + password = user_dict["password"], + email = user_dict["email"], + full_name = user_dict["full_name"], + hashed_password = hashed_password, +) +``` + +/// warning | 경고 + +추가적으로 제공된 함수 `fake_password_hasher`와 `fake_save_user`는 데이터 흐름을 시연하기 위한 예제일 뿐이며, 실제 보안을 제공하지 않습니다. + +/// + +## 중복 줄이기 + +코드 중복을 줄이는 것은 **FastAPI**의 핵심 아이디어 중 하나입니다. + +코드 중복은 버그, 보안 문제, 코드 비동기화 문제(한 곳은 업데이트되었지만 다른 곳은 업데이트되지 않는 문제) 등의 가능성을 증가시킵니다. + +그리고 이 모델들은 많은 데이터를 공유하면서 속성 이름과 타입을 중복하고 있습니다. + +더 나은 방법이 있습니다. + +`UserBase` 모델을 선언하여 다른 모델들의 기본(base)으로 사용할 수 있습니다. 그런 다음 이 모델을 상속받아 속성과 타입 선언(유형 선언, 검증 등)을 상속하는 서브클래스를 만들 수 있습니다. + +모든 데이터 변환, 검증, 문서화 등은 정상적으로 작동할 것입니다. + +이렇게 하면 각 모델 간의 차이점만 선언할 수 있습니다(평문 `password`가 있는 경우, `hashed_password`만 있는 경우, 혹은 비밀번호가 없는 경우): + +{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *} + +## `Union` 또는 `anyOf` + +두 가지 이상의 타입을 포함하는 `Union`으로 응답을 선언할 수 있습니다. 이는 응답이 그 중 하나의 타입일 수 있음을 의미합니다. + +OpenAPI에서는 이를 `anyOf`로 정의합니다. + +이를 위해 표준 Python 타입 힌트인 `typing.Union`을 사용할 수 있습니다: + +/// note | 참고 + +`Union`을 정의할때는 더 구체적인 타입을 먼저 포함하고, 덜 구체적인 타입을 그 뒤에 나열해야합니다. 아래 예제에서는 `Union[PlaneItem, CarItem]` 를 보면, 더 구체적인 `PlaneItem`이 `CarItem`보다 앞에 위치합니다. + +/// + +{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *} + + +### Python 3.10에서 `Union` + +위의 예제에서는 `response_model` 인자 값으로 `Union[PlaneItem, CarItem]`을 전달합니다. + +이 경우, 이를 **타입 어노테이션(type annotation)** 이 아닌 **인자 값(argument value)** 으로 전달하고 있기 때문에 Python 3.10에서도 `Union`을 사용해야 합니다. + +만약 타입 어노테이션에 사용한다면, 다음과 같이 수직 막대(|)를 사용할 수 있습니다: + +```Python +some_variable: PlaneItem | CarItem +``` + +하지만 이를 `response_model=PlaneItem | CarItem`과 같이 할당하면 에러가 발생합니다. 이는 Python이 이를 타입 어노테이션으로 해석하지 않고, `PlaneItem`과 `CarItem` 사이의 **잘못된 연산(invalid operation)**을 시도하기 때문입니다 + +## 모델 리스트 + +마찬가지로, 객체 리스트 형태의 응답을 선언할 수도 있습니다. + +이를 위해 표준 Python의 `typing.List`를 사용하세요(또는 Python 3.9 이상에서는 단순히 `list`를 사용할 수 있습니다): + +{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *} + + +## 임의의 `dict` 응답 + +Pydantic 모델을 사용하지 않고, 키와 값의 타입만 선언하여 평범한 임의의 `dict`로 응답을 선언할 수도 있습니다. + +이는 Pydantic 모델에 필요한 유효한 필드/속성 이름을 사전에 알 수 없는 경우에 유용합니다. + +이 경우, `typing.Dict`를 사용할 수 있습니다(또는 Python 3.9 이상에서는 단순히 `dict`를 사용할 수 있습니다): + +{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *} + + +## 요약 + +여러 Pydantic 모델을 사용하고, 각 경우에 맞게 자유롭게 상속하세요. + +엔터티가 서로 다른 "상태"를 가져야 하는 경우, 엔터티당 단일 데이터 모델을 사용할 필요는 없습니다. 예를 들어, 사용자 "엔터티"가 `password`, `password_hash`, 또는 비밀번호가 없는 상태를 포함할 수 있는 경우처럼 말입니다. diff --git a/docs/ko/docs/virtual-environments.md b/docs/ko/docs/virtual-environments.md new file mode 100644 index 000000000..0d10c3200 --- /dev/null +++ b/docs/ko/docs/virtual-environments.md @@ -0,0 +1,846 @@ +# 가상 환경 + +Python 프로젝트를 작업할 때는 **가상 환경** (또는 이와 유사한 도구)을 사용하는 것이 좋습니다. 각 프로젝트 마다 설치하는 패키지를 분리하여 관리할 수 있습니다. + +/// info | 정보 + +이미 가상 환경에 대해 잘 알고 있다면, 이 섹션은 건너 뛰어도 괜찮습니다. 🤓 + +/// + +/// tip | 팁 + +**가상 환경(Virtual Environment)** 은 **환경 변수(Environment Variable)** 와 다릅니다. + +**환경 변수**는 시스템에 존재하며, 프로그램이 사용할 수 있는 변수입니다. + +**가상 환경**은 몇몇 파일로 구성된 하나의 디렉터리입니다. + +/// + +/// info | 정보 + +이 페이지에서는 **가상 환경**의 사용 방법과 작동 방식을 설명합니다. + +만약 **모든 것을 관리해주는 도구** (Python 설치까지 포함)를 사용하고 싶다면 uv를 사용해보세요. + +/// + +## 프로젝트 생성 + +먼저, 프로젝트를 위한 디렉터리를 하나 생성합니다. + +보통 사용자 홈 디렉터리 안에 `code`라는 디렉터리를 만들고, 그 안에 프로젝트마다 하나씩 디렉터리를 만들어 관리합니다. + +
+ +```console +// 홈 디렉터리로 이동 +$ cd +// 모든 코드 프로젝트를 위한 디렉터리 생성 +$ mkdir code +// code 디렉터리로 이동 +$ cd code +// 이번 프로젝트를 위한 디렉터리 생성 +$ mkdir awesome-project +// 해당 프로젝트 디렉터리로 이동 +$ cd awesome-project +``` + +
+ +## 가상 환경 생성 + +Python 프로젝트를 **처음 시작할 때**, 가상 환경을 **프로젝트 내부**에 생성합니다. + +/// tip | 팁 + +이 작업은 **프로젝트를 처음 설정할 때 한번만** 해주면 됩니다. 이후 작업할 때 반복할 필요는 없습니다. + +/// + +//// tab | `venv` + +Python 표준 라이브러리에 포함된 venv 모듈을 사용해 가상 환경을 생성할 수 있습니다. + +
+ +```console +$ python -m venv .venv +``` + +
+ +/// details | 명령어 상세 설명 + +* `python`: `python` 프로그램을 실행합니다. +* `-m`: 특정 모듈을 스크립트처럼 실행합니다. 대상 모듈을 바로 뒤에 지정합니다. +* `venv`: Python 표준 라이브러리에 포함된 `venv` 모듈을 실행합니다. +* `.venv`: 가상 환경을 `.venv` 디렉터리에 생성합니다. + +/// + +//// + +//// tab | `uv` + +`uv`가 설치되어 있다면, uv를 통해 가상 환경을 생성할 수 있습니다. + +
+ +```console +$ uv venv +``` + +
+ +/// tip | 팁 + +`uv`는 기본적으로 `.venv` 디렉터리에 가상 환경을 생성합니다. + +별도로 디렉터리 이름을 추가 인자로 넘겨 주면 경로를 지정 할 수 있습니다. + +/// + +//// + +해당 명령어는 `.venv` 디렉터리에 새로운 가상 환경을 생성합니다. + +/// details | `.venv` 또는 다른 이름 + +가상 환경을 다른 디렉터리에 생성할 수도 있지만, 관례적으로 `.venv` 디렉터리 이름을 사용합니다. + +/// + +## 가상 환경 활성화 + +이후 실행하는 Python 명령어와 패키지 설치가 가상 환경을 따르도록, 가상 환경을 활성화하세요. + +/// tip | 팁 + +**터미널을 새로 열고** 프로젝트 작업을 시작할 때는, **항상 이 작업을** 해주세요. + +/// + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Windows에서 Bash(예: Git Bash)를 사용하는 경우: + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +/// tip | 팁 + +가상 환경에 새로운 패키지를 설치할 때마다, 해당 환경을 다시 활성화하세요. + +이렇게 하면 해당 패키지로 설치된 **터미널(CLI) 프로그램**을 사용할 때, 전역에 설치된 다른 버전이 아니라, 가상 환경 안에 설치된 정확한 버전을 사용합니다. + +/// + +## 가상 환경이 활성화 여부 확인 + +가상 환경이 활성화되었는지 확인합니다. (이전 명령어가 제대로 작동했는지 확인합니다). + +/// tip | 팁 + +이 단계는 **선택 사항**이지만, 모든 것이 예상대로 작동하고 있는지, 그리고 의도한 가상 환경이 활성화 되었는 지 **확인**하는 좋은 방법입니다. + +/// + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +`python` 위치가 프로젝트 내부(이 예시에서는 `awesome-project`)의 `.venv/bin/python` 경로로 표시된다면 성공입니다. 🎉 + +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +`python` 위치가 프로젝트 내부(이 예시에서는 `awesome-project`)의 `.venv\bin\python` 경로로 표시된다면 성공입니다. 🎉 + +//// + +## pip 업그레이드 + +/// tip | 팁 + +`uv`를 사용한다면, `pip` 대신 `uv`로 패키지를 설치하게 되므로 `pip`을 업그레이드할 필요가 없습니다. 😎 + +/// + +`pip`을 사용하여 패키지를 설치하는 경우 (Python 표준 라이브러리에 포함되어 있습니다), **최신 버전으로 업그레이드**하는 것이 좋습니다. + +패키지 설치 중 발생하는 다양하고 특이한 에러들은 `pip` 업그레이드로 쉽게 해결되는 경우가 많습니다. + +/// tip | 팁 + +이 작업은 보통 가상 환경을 생성한 **직후 한 번만** 하면 됩니다. + +/// + +가상 환경이 활성화된 상태인지 확인한 후(앞서 설명한 명령어 사용), 아래 명령어를 실행하세요: + +
+ +```console +$ python -m pip install --upgrade pip + +---> 100% +``` + +
+ +## `.gitignore` 추가하기 + +**Git**을 사용하고 있다면 (사용하는 것이 좋습니다), `.gitignore` 파일을 추가해서 `.venv` 디렉터리 전체를 Git에서 제외하세요. + +/// tip | 팁 + +`uv`를 사용해 가상 환경을 생성했다면, 이미 이 작업이 자동으로 처리되어 있으므로 이 단계는 건너뛰어도 됩니다. 😎 + +/// + +/// tip | 팁 + +이 작업도 마찬가지로, 가상 환경을 생성한 **직후 한 번만** 하면 됩니다. + +/// + +
+ +```console +$ echo "*" > .venv/.gitignore +``` + +
+ +/// details | 명령어 상세 설명 + +* `echo "*"`: 터미널에 `*` 텍스트를 "출력"합니다 (다음 설명에서 조금 바뀝니다) +* `>`: 왼쪽 명령어의 출력 내용을 터미널에 출력하지 않고, 오른쪽에 지정된 파일로 **기록(write)** 하라는 의미입니다. +* `.gitignore`: 출력된 텍스트가 기록될 파일 이름입니다. + +그리고 Git에서 `*`는 "모든 것"을 의미합니다. 따라서 `.venv` 디렉터리 안의 모든 것을 무시하게 됩니다. + +이 명령어는 다음과 같은 내용을 가진 `.gitignore` 파일을 생성합니다: + + +```gitignore +* +``` + +/// + +## 패키지 설치 + +가상 환경을 활성화한 후, 그 안에 필요한 패키지들을 설치할 수 있습니다. + +/// tip | 팁 + +프로젝트에서 필요한 패키지를 설치하거나 업그레이드할 때는 이 작업을 **한 번만** 하면 됩니다. + +만약 특정 패키지의 버전을 업그레이드하거나, 새로운 패키지를 추가할 필요가 생기면 **다시 이 작업을 반복**하면 됩니다. + +/// + +### 패키지 직접 설치 + +급하게 작업하거나, 프로젝트에 필요한 패키지 목록을 따로 파일로 관리하고 싶지 않은 경우, 패키지를 직접 설치할 수도 있습니다. + +/// tip | 팁 + +패키지 이름과 버전 정보를 파일에 정리해두는 것(예: `requirements.txt` 또는 `pyproject.toml`)은 (매우) 좋은 생각입니다. + +/// + +//// tab | `pip` + +
+ +```console +$ pip install "fastapi[standard]" + +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +`uv`를 사용하는 경우: + +
+ +```console +$ uv pip install "fastapi[standard]" +---> 100% +``` + +
+ +//// + +### `requirements.txt`에서 설치 + +`requirements.txt` 파일이 있다면, 그 안에 명시된 패키지들을 한 번에 설치할 수 있습니다. + +//// tab | `pip` + +
+ +```console +$ pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +//// tab | `uv` + +`uv`를 사용하는 경우: + +
+ +```console +$ uv pip install -r requirements.txt +---> 100% +``` + +
+ +//// + +/// details | `requirements.txt` + +다음은 몇 가지 패키지를 포함한 `requirements.txt`의 예시입니다: + +```requirements.txt +fastapi[standard]==0.113.0 +pydantic==2.8.0 +``` + +/// + +## 프로그램 실행 + +가상 환경을 활성화한 후에는 프로그램을 실행할 수 있습니다. 이때 해당 가상 환경에 설치된 Python과 패키지들이 사용됩니다. + +
+ +```console +$ python main.py + +Hello World +``` + +
+ +## 에디터 설정 + +에디터를 사용할 경우, 앞서 만든 가상 환경을 사용하도록 설정하는 것이 좋습니다. (대부분의 에디터는 자동으로 감지하기도 합니다.) +이렇게 하면 자동 완성 기능이나 코드 내 오류 표시 기능을 제대로 사용할 수 있습니다. + +예시: + +* VS Code +* PyCharm + +/// tip | 팁 + +이 설정은 보통 가상 환경을 **처음 만들었을 때 한 번만** 해주면 됩니다. + +/// + +## 가상 환경 비활성화 + +프로젝트 작업이 끝났다면, 가상 환경을 **비활성화**할 수 있습니다. + +
+ +```console +$ deactivate +``` + +
+ +이렇게 하면 이후에 `python` 명령어를 실행했을 때, 가상 환경의 Python이나 그 안에 설치된 패키지들을 사용하지 않게 됩니다. + +## 이제 작업할 준비가 되었습니다 + +이제 프로젝트 작업을 시작할 준비가 완료되었습니다. + + +/// tip | 팁 + +위 내용을 더 깊이 이해하고 싶으신가요? + +그렇다면 계속 읽어 주세요. 👇🤓 + +/// + +## 가상 환경을 왜 사용하는가 + +FastAPI를 사용하려면 먼저 Python을 설치해야 합니다. + +그 후에는 FastAPI와 함께 사용할 **기타 패키지들**을 **설치**해야 합니다. + +패키지를 설치할 때 보통 Python에 기본 포함된 `pip` 명령어(또는 유사한 도구)를 사용합니다. + +하지만 `pip`을 그냥 직접 사용하면, 해당 패키지들은 **전역 Python 환경**(시스템 전체에 설치된 Python)에 설치됩니다. + +### 문제점 + +그렇다면, 전역 Python 환경에 패키지를 설치하면 어떤 문제가 발생할까요? + +어느 시점이 되면, **서로 다른 패키지들**에 의존하는 여러 개의 프로그램을 작성하게 될 것입니다. 그리고 이들 중 일부는 **같은 패키지의 서로 다른 버전**을 필요로 할 수 있습니다. 😱 + +예를 들어, `마법사의 돌(philosophers-stone)` 프로젝트를 만들었다고 가정해봅시다. 이 프로그램은 `해리 포터(harry)`라는 패키지의 `v1` 버전을 **의존**합니다. 따라서 `harry`를 설치해야 합니다. + +```mermaid +flowchart LR + stone(philosophers-stone) -->|requires| harry-1[harry v1] +``` + +그런데 나중에 `아즈카반의 죄수(prisoner-of-azkaban)`이라는 또 다른 프로젝트를 만들게 되었고, 이 프로젝트도 역시 `harry` 패키지를 사용합니다. 그런데 이 프로젝트는 `harry`의 `v3` 버전이 필요합니다. + +```mermaid +flowchart LR + azkaban(prisoner-of-azkaban) --> |requires| harry-3[harry v3] +``` + +하지만 이제 문제가 생깁니다. 로컬 가상 환경 대신에 전역 환경에 패키지를 설치하게 되면, 어떤 버전의 `harry`를 설치할지를 선택해야 하기 때문입니다. + +예를 들어, `마법사의 돌(philosophers-stone)`을 실행하고 싶다면 먼저 `harry` `v1` 버전을 다음과 같이 설치 해야 합니다: + +
+ +```console +$ pip install "harry==1" +``` + +
+ +그러면 결국 전역 Python 환경에는 `harry` `v1`버전이 설치된 상태가 됩니다. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -->|requires| harry-1 + end +``` + +하지만 이제 `아즈카반의 죄수(prisoner-of-azkaban)`을 실행하고 싶다면, `harry` `v1`버전을 제거하고 `harry` `v3`버전을 설치해야 합니다. (또는 단순히 `v3`버전을 설치하는 것만으로도 기존의 `v1`버전이 자동으로 제거됩니다.) + +
+ +```console +$ pip install "harry==3" +``` + +
+ +그렇게 하면 이제 전역 Python 환경에는 `harry` `v3`버전이 설치된 상태가 됩니다. + +그리고 다시 `마법사의 돌(philosophers-stone)`을 실행하려고 하면, **작동하지** 않을 수 있습니다. 왜냐하면 이 프로그램은 `harry` `v1`버전을 필요로 하기 때문입니다. + +```mermaid +flowchart LR + subgraph global[global env] + harry-1[harry v1] + style harry-1 fill:#ccc,stroke-dasharray: 5 5 + harry-3[harry v3] + end + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) -.-x|⛔️| harry-1 + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --> |requires| harry-3 + end +``` + +/// tip | 팁 + +Python 패키지들은 **새 버전**에서 **호환성 문제(breaking changes)**가 발생하지 않도록 최대한 노력하는 것이 일반적입니다. 하지만 그래도 안전하게 작업하려면, 테스트를 실행해보면서 새 버전을 의도적으로 설치하는 것이 좋습니다. + +/// + +이제, 이런 일이 여러분의 **모든 프로젝트**가 사용하는 **수많은 패키지들**에서 동시에 발생한다고 상상해보세요. 이는 매우 관리하기 어려우며, 결국 **서로 호환되지 않는 버전**의 패키지로 프로젝트를 실행하게 될 가능성이 높고, 그로 인해 어떤 문제가 왜 발생하는지 알 수 없게 될 수 있습니다. + +또한 사용하는 운영체제(Linux, Windows, macOS 등)에 따라 Python이 **미리 설치되어 있을 수도** 있습니다. 이런 경우에는 운영체제의 동작에 필요한 특정 버전의 패키지들이 함께 설치되어 있을 수 있습니다. 이 상태에서 전역 Python 환경에 임의의 패키지를 설치하면, 운영체제에 포함된 프로그램 일부가 **깨질 위험**도 있습니다. + +## 패키지들은 어디에 설치되는가 + +Python을 설치하면, 컴퓨터에 여러 디렉터리와 파일들이 생성됩니다. + +이 중 일부 디렉터리는 사용자가 설치한 패키지들을 보관하는 역할을 합니다. + +예를 들어, 아래 명령어를 실행하면: + +
+ +```console +// 지금 실행하지 않아도 됩니다, 그냥 예제일 뿐이에요 🤓 +$ pip install "fastapi[standard]" +---> 100% +``` + +
+ +해당 명령어는 FastAPI 코드를 포함한 압축 파일을 다운로드합니다. 이 파일은 보통 PyPI에서 받아옵니다. + +또한 FastAPI가 의존하는 다른 패키지들도 함께 **다운로드**됩니다. + +그리고 그 모든 파일들을 **압축 해제**한 뒤, 컴퓨터의 특정 디렉터리에 저장합니다. + +기본적으로 이 파일들은 Python이 설치된 디렉터리 안, 즉 **전역 환경**에 내의 디렉터리에 저장됩니다. + +## 가상 환경이란 + +전역 환경에 모든 패키지를 설치하면서 발생하는 문제에 대한 해결책은, 작업하는 **각 프로젝트마다 가상 환경**을 사용하는 것입니다. + +가상 환경은 전역 환경과 매우 유사한 하나의 **디렉터리**이며, 그 안에 해당 프로젝트를 위한 패키지들을 설치할 수 있습니다. + +이렇게 하면 각 프로젝트는 자체적인 가상 환경(`.venv` 디렉터리)을 가지게 되며, 그 안에 해당 프로젝트 전용 패키지들을 보유하게 됩니다. + + +```mermaid +flowchart TB + subgraph stone-project[philosophers-stone project] + stone(philosophers-stone) --->|requires| harry-1 + subgraph venv1[.venv] + harry-1[harry v1] + end + end + subgraph azkaban-project[prisoner-of-azkaban project] + azkaban(prisoner-of-azkaban) --->|requires| harry-3 + subgraph venv2[.venv] + harry-3[harry v3] + end + end + stone-project ~~~ azkaban-project +``` + +## 가상 환경 활성화 의미 + +가상 환경을 활성화한다는 것은, 예를 들어 다음과 같은 명령어를 실행하는 것을 의미합니다: + +//// tab | Linux, macOS + +
+ +```console +$ source .venv/bin/activate +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ .venv\Scripts\Activate.ps1 +``` + +
+ +//// + +//// tab | Windows Bash + +Windows에서 Bash(예: Git Bash)를 사용하는 경우: + +
+ +```console +$ source .venv/Scripts/activate +``` + +
+ +//// + +이 명령어는 이후에 실행될 명령어에서 사용될 [환경 변수](environment-variables.md){.internal-link target=_blank} 몇 개를 생성하거나 수정합니다. + +이 변수들 중 하나가 바로 `PATH` 변수입니다. + +/// tip | 팁 + +`PATH` 환경 변수에 대해 더 알고 싶다면 [환경 변수 문서의 PATH 환경 변수 섹션](environment-variables.md#path-environment-variable){.internal-link target=_blank}을 참고하세요. + +/// + +가상 환경을 활성화하면, 가상 환경의 경로인 `.venv/bin` (Linux와 macOS) 또는 `.venv\Scripts`(Windows)를 `PATH` 환경 변수에 추가됩니다. + +예를 들어, 가상 환경을 활성화하기 전의 `PATH` 변수는 다음과 같았다고 가정해봅시다: + +//// tab | Linux, macOS + +```plaintext +/usr/bin:/bin:/usr/sbin:/sbin +``` + +시스템은 다음 경로들에서 프로그램을 찾게 됩니다: + +* `/usr/bin` +* `/bin` +* `/usr/sbin` +* `/sbin` + +//// + +//// tab | Windows + +```plaintext +C:\Windows\System32 +``` + +시스템은 다음 경로들에서 프로그램을 찾게 됩니다: + +* `C:\Windows\System32` + +//// + +가상 환경을 활성화한 후에는, `PATH` 변수는 다음과 같은 형태가 됩니다: + +//// tab | Linux, macOS + +```plaintext +/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin +``` + +시스템은 가장 먼저 다음 경로에서 프로그램을 찾기 시작합니다: + +```plaintext +/home/user/code/awesome-project/.venv/bin +``` + +그 후에 다른 디렉터리들을 탐색합니다. + +따라서 터미널에 `python`을 입력하면, 시스템은 다음 위치에 있는 Python 프로그램을 찾게 됩니다: + +```plaintext +/home/user/code/awesome-project/.venv/bin/python +``` + +그리고 해당 Python을 사용하게 됩니다. + +//// + +//// tab | Windows + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32 +``` + +시스템은 가장 먼저 다음 경로에서 프로그램을 찾기 시작합니다: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts +``` + +그 후에 다른 디렉터리들을 탐색합니다. + +따라서 터미널에 `python`을 입력하면, 시스템은 다음 경로에 있는 Python 프로그램을 찾게 됩니다: + +```plaintext +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +그리고 해당 Python을 사용하게 됩니다. + +//// + +중요한 세부 사항 중 하나는, 가상 환경의 경로가 `PATH` 변수의 가장 **앞**에 추가된다는 점입니다. 시스템은 사용 가능한 다른 Python들보다 **먼저** 이 경로를 찾습니다. 그래서 터미널에서 `python`을 실행하면, 전역 환경의 Python이 아닌 **가상 환경에 있는** Python이 사용됩니다. (예: 전역 환경에 설치된 `python`이 있더라도 그보다 우선합니다.) + +가상 환경을 활성화하면 이 외에도 몇 가지 다른 것들이 변경되지만, 이는 그중에서도 가장 중요한 변화 중 하나입니다. + +## 가상 환경 확인하기 + +가상 환경이 활성화 되었는지 확인하려면, 아래 명령어를 사용할 수 있습니다: + +//// tab | Linux, macOS, Windows Bash + +
+ +```console +$ which python + +/home/user/code/awesome-project/.venv/bin/python +``` + +
+ +//// + +//// tab | Windows PowerShell + +
+ +```console +$ Get-Command python + +C:\Users\user\code\awesome-project\.venv\Scripts\python +``` + +
+ +//// + +즉, 현재 사용되는 `python` 프로그램은 **가상 환경 내부에 있는 것**입니다. + +Linux와 macOS에서는 `which`, Windows PowerShell에서는 `Get-Command` 명령어를 사용합니다. + +이 명령어는 `PATH` 환경 변수에 지정된 경로들을 **순서대로 탐색**하면서 `python`이라는 이름의 프로그램을 찾습니다. +찾는 즉시, 해당 프로그램의 **경로를 출력**합니다. + +중요한 점은 터미널에서 `python`을 실행했을 때, 실제로 실행되는 "`python`"이 어떤 것인지 정확히 알 수 있다는 것입니다. + +따라서 현재 올바른 가상 환경에 있는지 확인할 수 있습니다. + +/// tip | 팁 + +하나의 가상 환경을 활성화한 뒤, 해당 Python을 가진 상태에서 **또 다른 프로젝트**로 이동하는 것은 흔히 발생합니다. + +하지만 이때 이전 프로젝트의 가상 환경에 있는 **잘못된 Python 실행 파일**을 사용하게 되어 새 프로젝트가 **정상 작동하지 않을 수 있습니다.** + +그래서 현재 어떤 `python`이 사용되고 있는지 확인할 수 있는 능력은 매우 유용합니다. 🤓 + +/// + +## 가상 환경을 비활성화하는 이유 + +예를 들어 `마법사의 돌(philosophers-stone)`이라는 프로젝트에서 작업 중이라고 해보겠습니다. 이때 해당 **가상 환경을 활성화**하고, 필요한 패키지를 설치하며 작업을 진행합니다. + +그런데 이제는 **다른 프로젝트**인 `아즈카반의 죄수(prisoner-of-azkaban)`을 작업하고 싶어졌습니다. + +그래서 그 프로젝트 디렉터리로 이동합니다: + +
+ +```console +$ cd ~/code/prisoner-of-azkaban +``` + +
+ +만약 `마법사의 돌(philosophers-stone)`의 가상 환경을 비활성화하지 않았다면, 터미널에서 `python`을 실행할 때 여전히 `마법사의 돌(philosophers-stone)` 가상 환경의 Python을 사용하게 됩니다. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +$ python main.py + +// sirius를 임포트하는 데 실패했습니다. 설치되어 있지 않아요 😱 +Traceback (most recent call last): + File "main.py", line 1, in + import sirius +``` + +
+ +하지만 `마법사의 돌(philosophers-stone)`의 가상 환경을 비활성화한 다음, `아즈카반의 죄수(prisoner-of-azkaban)` 프로젝트의 가상 환경을 활성화하면, 이제 `python` 명령어는 `아즈카반의 죄수(prisoner-of-azkaban)` 가상 환경의 Python을 사용하게 됩니다. + +
+ +```console +$ cd ~/code/prisoner-of-azkaban + +// 이전 디렉터리에 있을 필요 없이, 어디서든 가상 환경을 비활성화할 수 있습니다. 다른 프로젝트 디렉터리로 이동한 후에도 괜찮아요 😎 +$ deactivate + +// prisoner-of-azkaban/.venv 가상 환경을 활성화합니다 🚀 +$ source .venv/bin/activate + +// 이제 python을 실행하면, 이 가상 환경에 설치된 sirius 패키지를 찾게 됩니다 ✨ +$ python main.py + +못된 짓을 꾸미고 있음을 엄숙히 맹세합니다.🧙 +ImportError는 이제 없습니다. 🐺 +``` + +
+ +## 대안들 + +이 문서는 여러분이 Python 프로젝트를 시작하고, **그 내부에서** 어떻게 돌아가는지 알려주는 간단한 가이드입니다. + +가상 환경, 패키지 의존성(Requirements), 프로젝트를 관리하는 방법에는 이 외에도 다양한 **대안**들이 존재합니다. + +만약 준비가 되었다면, **프로젝트 전체**, 패키지 의존성, 가상 환경 등을 통합적으로 **관리**할 수 있는 도구를 써보는 것도 좋습니다. 그럴 때 추천하는 도구가 바로 uv입니다. + +`uv`는 다양한 기능을 지원합니다: + +* 다양한 버전의 **Python 설치** +* 각 프로젝트 별 **가상 환경 관리** +* **패키지 설치** +* 프로젝트의 **의존성과 버전** 관리 +* 설치된 패키지들과 그 버전을 **정확히 고정(lock)**해서,개발 환경과 운영 환경이 완전히 동일하게 작동할 수 있도록 보장 +* 이 외에도 다양한 기능을 지원 + +## 결론 + +여기까지 모두 읽고 이해했다면, 이제 많은 개발자들보다 가상 환경을 **훨씬 더 깊이 있게 이해**하게 되셨습니다. 🤓 + +이런 세부적인 내용을 알고 있으면, 언젠가 복잡해 보이는 문제를 디버깅할 때 분명히 큰 도움이 될 것입니다. 이제는 **이 모든 것들이 내부에서 어떻게 작동하는지** 알고 있기 때문입니다. 😎 diff --git a/docs/ru/docs/tutorial/cookie-param-models.md b/docs/ru/docs/tutorial/cookie-param-models.md new file mode 100644 index 000000000..3a57443bb --- /dev/null +++ b/docs/ru/docs/tutorial/cookie-param-models.md @@ -0,0 +1,76 @@ +# Модели параметров cookie + +Если у вас есть группа **cookies**, которые связаны между собой, вы можете создать **Pydantic-модель** для их объявления. 🍪 + +Это позволит вам **переиспользовать модель** в **разных местах**, а также объявить проверки и метаданные сразу для всех параметров. 😎 + +/// note | Заметка + +Этот функционал доступен с версии `0.115.0`. 🤓 + +/// + +/// tip | Совет + +Такой же подход применяется для `Query`, `Cookie`, и `Header`. 😎 + +/// + +## Pydantic-модель для cookies + +Объявите параметры **cookie**, которые вам нужны, в **Pydantic-модели**, а затем объявите параметр как `Cookie`: + +{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *} + +**FastAPI** **извлечёт** данные для **каждого поля** из **cookies**, полученных в запросе, и выдаст вам объявленную Pydantic-модель. + +## Проверка сгенерированной документации + +Вы можете посмотреть объявленные cookies в графическом интерфейсе Документации по пути `/docs`: + +
+ +
+ +/// info | Дополнительная информация + +Имейте в виду, что, поскольку **браузеры обрабатывают cookies** особым образом и под капотом, они **не** позволят **JavaScript** легко получить доступ к ним. + +Если вы перейдёте к **графическому интерфейсу документации API** по пути `/docs`, то сможете увидеть **документацию** по cookies для ваших *операций путей*. + +Но даже если вы **заполните данные** и нажмёте "Execute", поскольку графический интерфейс Документации работает с **JavaScript**, cookies не будут отправлены, и вы увидите сообщение об **ошибке** как будто не указывали никаких значений. + +/// + +## Запрет дополнительных cookies + +В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** cookies, которые вы хотите получать. + +Теперь ваш API сам решает, принимать ли cookies. 🤪🍪 + +Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) любые дополнительные (`extra`) поля: + +{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *} + +Если клиент попробует отправить **дополнительные cookies**, то в ответ он получит **ошибку**. + +Бедные баннеры cookies, они всеми силами пытаются получить ваше согласие — и всё ради того, чтобы API его отклонил. 🍪 + +Например, если клиент попытается отправить cookie `santa_tracker` со значением `good-list-please`, то в ответ он получит **ошибку**, сообщающую ему, что cookie `santa_tracker` не разрешён: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["cookie", "santa_tracker"], + "msg": "Extra inputs are not permitted", + "input": "good-list-please" + } + ] +} +``` + +## Заключение + +Вы можете использовать **Pydantic-модели** для объявления **cookies** в **FastAPI**. 😎 diff --git a/docs/ru/docs/tutorial/request-form-models.md b/docs/ru/docs/tutorial/request-form-models.md new file mode 100644 index 000000000..1034ed27f --- /dev/null +++ b/docs/ru/docs/tutorial/request-form-models.md @@ -0,0 +1,78 @@ +# Модели форм + +Вы можете использовать **Pydantic-модели** для объявления **полей форм** в FastAPI. + +/// info | Дополнительная информация + +Чтобы использовать формы, сначала установите `python-multipart`. + +Убедитесь, что вы создали и активировали [виртуальное окружение](../virtual-environments.md){.internal-link target=_blank}, а затем установите пакет, например: + +```console +$ pip install python-multipart +``` + +/// + +/// note | Заметка + +Этот функционал доступен с версии `0.113.0`. 🤓 + +/// + +## Pydantic-модель для формы + +Вам просто нужно объявить **Pydantic-модель** с полями, которые вы хотите получить как **поля формы**, а затем объявить параметр как `Form`: + +{* ../../docs_src/request_form_models/tutorial001_an_py39.py hl[9:11,15] *} + +**FastAPI** **извлечёт** данные для **каждого поля** из **данных формы** в запросе и выдаст вам объявленную Pydantic-модель. + +## Проверка сгенерированной документации + +Вы можете посмотреть поля формы в графическом интерфейсе Документации по пути `/docs`: + +
+ +
+ +## Запрет дополнительных полей формы + +В некоторых случаях (не особо часто встречающихся) вам может понадобиться **ограничить** поля формы только теми, которые объявлены в Pydantic-модели. И **запретить** любые **дополнительные** поля. + +/// note | Заметка + +Этот функционал доступен с версии `0.114.0`. 🤓 + +/// + +Вы можете сконфигурировать Pydantic-модель так, чтобы запретить (`forbid`) все дополнительные (`extra`) поля: + +{* ../../docs_src/request_form_models/tutorial002_an_py39.py hl[12] *} + +Если клиент попробует отправить дополнительные данные, то в ответ он получит **ошибку**. + +Например, если клиент попытается отправить поля формы: + +* `username`: `Rick` +* `password`: `Portal Gun` +* `extra`: `Mr. Poopybutthole` + +То в ответ он получит **ошибку**, сообщающую ему, что поле `extra` не разрешено: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["body", "extra"], + "msg": "Extra inputs are not permitted", + "input": "Mr. Poopybutthole" + } + ] +} +``` + +## Заключение + +Вы можете использовать Pydantic-модели для объявления полей форм в FastAPI. 😎 diff --git a/docs/uk/docs/tutorial/background-tasks.md b/docs/uk/docs/tutorial/background-tasks.md new file mode 100644 index 000000000..912ba8c2a --- /dev/null +++ b/docs/uk/docs/tutorial/background-tasks.md @@ -0,0 +1,85 @@ +# Фонові задачі + +Ви можете створювати фонові задачі, які будуть виконуватися *після* повернення відповіді. + +Це корисно для операцій, які потрібно виконати після обробки запиту, але клієнту не обов’язково чекати завершення цієї операції перед отриманням відповіді. + +Приклади використання: + +* Надсилання email-сповіщень після виконання певної дії: + * Підключення до поштового сервера та надсилання листа може займати кілька секунд. Ви можете відразу повернути відповідь, а email відправити у фоні. +* Обробка даних: + * Наприклад, якщо отримано файл, який потрібно обробити довготривалим процесом, можна повернути відповідь "Accepted" ("Прийнято", HTTP 202) і виконати обробку файлу у фоні. + +## Використання `BackgroundTasks` + +Спочатку імпортуйте `BackgroundTasks` і додайте його як параметр у Вашу *функцію операції шляху* (path operation function) до `BackgroundTasks`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *} + +**FastAPI** автоматично створить об'єкт `BackgroundTasks` і передасть його у цей параметр. + + +## Створення функції задачі + +Створіть функцію, яка буде виконувати фонову задачу. + +Це звичайна функція, яка може отримувати параметри. + +Вона може бути асинхронною `async def` або звичайною `def` функцією – **FastAPI** обробить її правильно. + +У нашому випадку функція записує у файл (імітуючи надсилання email). + +І оскільки операція запису не використовує `async` та `await`, ми визначаємо функцію як звичайну `def`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *} + +## Додавання фонової задачі + +Усередині Вашої *функції обробки шляху*, передайте функцію задачі в об'єкт *background tasks*, використовуючи метод `.add_task()`: + +{* ../../docs_src/background_tasks/tutorial001.py hl[14] *} + +`.add_task()` приймає аргументи: + +* Функція задача, яка буде виконуватися у фоновому режимі (`write_notification`). Зверніть увагу, що передається обʼєкт без дужок. +* Будь-яка послідовність аргументів, які потрібно передати у функцію завдання у відповідному порядку (`email`). +* Будь-які іменовані аргументи, які потрібно передати у функцію задачу (`message="some notification"`). + +## Впровадження залежностей + +Використання `BackgroundTasks` також працює з системою впровадження залежностей. Ви можете оголосити параметр типу `BackgroundTasks` на різних рівнях: у *функції операції шляху*, у залежності (dependable), у під залежності тощо. + +**FastAPI** знає, як діяти в кожному випадку і як повторно використовувати один і той самий об'єкт, щоб усі фонові задачі були об’єднані та виконувалися у фоновому режимі після завершення основного запиту. + +{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *} + +У цьому прикладі повідомлення будуть записані у файл `log.txt` *після* того, як відповідь буде надіслана. + +Якщо у запиті був переданий query-параметр, він буде записаний у лог у фоновій задачі. + +А потім інша фонова задача, яка створюється у *функції операції шляху*, запише повідомлення з використанням path параметра `email`. + +## Технічні деталі + +Клас `BackgroundTasks` походить безпосередньо з `starlette.background`. + +Він імпортується безпосередньо у FastAPI, щоб Ви могли використовувати його з `fastapi` і випадково не імпортували `BackgroundTask` (без s в кінці) з `starlette.background`. + +Якщо використовувати лише `BackgroundTasks` (а не `BackgroundTask`), то його можна передавати як параметр у *функції операції шляху*, і **FastAPI** подбає про все інше, так само як і про використання об'єкта `Request`. + +Також можна використовувати `BackgroundTask` окремо в FastAPI, але для цього Вам доведеться створити об'єкт у коді та повернути Starlette `Response`, включаючи його. + +Детальніше можна почитати в офіційній документації Starlette про фонові задачі . + +## Застереження + +Якщо Вам потрібно виконувати складні фонові обчислення, і при цьому нема потреби запускати їх у тому ж процесі (наприклад, не потрібно спільного доступу до пам’яті чи змінних), можливо, варто скористатися більш потужними інструментами, такими як Celery. + +Такі інструменти зазвичай потребують складнішої конфігурації та менеджера черги повідомлень/завдань, наприклад, RabbitMQ або Redis. Однак вони дозволяють виконувати фонові задачі в кількох процесах і навіть на кількох серверах. + +Якщо ж Вам потрібно отримати доступ до змінних і об’єктів із тієї ж **FastAPI** - програми або виконувати невеликі фонові завдання (наприклад, надсилати сповіщення електронною поштою), достатньо просто використовувати `BackgroundTasks`. + +## Підсумок + +Імпортуйте та використовуйте `BackgroundTasks` як параметр у *функціях операції шляху* та залежностях, щоб додавати фонові задачі. diff --git a/docs/uk/docs/tutorial/cors.md b/docs/uk/docs/tutorial/cors.md new file mode 100644 index 000000000..95b204d0f --- /dev/null +++ b/docs/uk/docs/tutorial/cors.md @@ -0,0 +1,89 @@ +# CORS (Обмін ресурсами між різними джерелами) + +CORS або "Обмін ресурсами між різними джерелами" є ситуація, коли фронтенд, що працює в браузері, містить JavaScript-код, який взаємодіє з бекендом, розташованим в іншому "джерелі" (origin). + +## Джерело (Origin) + +Джерело визначається комбінацією протоколу (`http`, `https`), домену (`myapp.com`, `localhost`, `localhost.tiangolo.com`), порту (`80`, `443`, `8080`). + + +Наприклад, такі адреси вважаються різними джерелами: + +* `http://localhost` +* `https://localhost` +* `http://localhost:8080` + +Навіть якщо вони всі містять `localhost`, вони мають різні протоколи або порти, що робить їх окремими "джерелами". + +## Кроки + +Припустимо, що Ваш фронтенд працює в браузері на `http://localhost:8080`, а його JavaScript намагається відправити запит до бекенду, який працює на `http://localhost` (Оскільки ми не вказуємо порт, браузер за замовчуванням припускає порт `80`). + +Потім браузер надішле HTTP-запит `OPTIONS` до бекенду на порту `:80`, і якщо бекенд надішле відповідні заголовки, що дозволяють комунікацію з цього іншого джерела (`http://localhost:8080`), тоді браузер на порту `:8080` дозволить JavaScript у фронтенді надіслати свій запит до бекенду на порту `:80`. + +Щоб досягти цього, бекенд на порту `:80` повинен мати список "дозволених джерел". + +У цьому випадку список має містити `http://localhost:8080`, щоб фронтенд на порту `:8080` працював коректно. + +## Символьне підставляння + +Можна також оголосити список як `"*"` ("символьне підставляння"), що означає дозвіл для всіх джерел. + +Однак це дозволить лише певні типи комунікації, виключаючи все, що пов'язане з обліковими даними: Cookies, заголовки авторизації, такі як ті, що використовуються з Bearer токенами тощо. + +Тому для коректної роботи краще явно вказувати дозволені джерела. + +## Використання `CORSMiddleware` + +Ви можете налаштувати це у Вашому додатку **FastAPI** за допомогою `CORSMiddleware`. + +* Імпортуйте `CORSMiddleware`. +* Створіть список дозволених джерел (у вигляді рядків). +* Додайте його як "middleware" у Ваш додаток **FastAPI**. + + +Також можна вказати, чи дозволяє Ваш бекенд: + +* Облікові дані (заголовки авторизації, сookies, тощо). +* Конкретні HTTP-методи (`POST`, `PUT`) або всі за допомогою `"*"` +* Конкретні HTTP-заголовки або всі за допомогою `"*"`. + + +{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *} + +Параметри за замовчуванням у `CORSMiddleware` є досить обмеженими, тому Вам потрібно явно вказати конкретні джерела, методи або заголовки, щоб браузери могли використовувати їх у контексті запитів між різними доменами. + + +Підтримуються такі аргументи: + +* `allow_origins` - Список джерел, яким дозволено здійснювати міждоменні запити. Наприклад `['https://example.org', 'https://www.example.org']`. Ви можете використовувати ['*'], щоб дозволити всі джерела. +* `allow_origin_regex` - Рядок регулярного виразу для відповідності джерелам, яким дозволено здійснювати міждоменні запити. Наприклад, `'https://.*\.example\.org'`. +* `allow_methods` - Список HTTP-методів, дозволених для міждоменних запитів. За замовчуванням `['GET']`. Ви можете використовувати `['*']`, щоб дозволити всі стандартні методи. +* `allow_headers` - Список HTTP-заголовків, які підтримуються для міждоменних запитів. За замовчуванням `[]`. Ви можете використовувати `['*']`, щоб дозволити всі заголовки. Заголовки `Accept`, `Accept-Language`, `Content-Language` і `Content-Type` завжди дозволені для простих CORS-запитів. +* `allow_credentials` - Визначає, чи підтримуються файли cookie для міждоменних запитів. За замовчуванням `False`. Також, якщо потрібно дозволити обмін обліковими даними (`allow_credentials = True`), параметр `allow_origins` не може бути встановлений як `['*']`, необхідно вказати конкретні джерела. +* `expose_headers` - Вказує, які заголовки відповіді повинні бути доступні для браузера. За замовчуванням `[]`. +* `max_age` - Встановлює максимальний час (у секундах) для кешування CORS-відповідей у браузерах. За замовчуванням `600`. + +Цей middleware обробляє два типи HTTP-запитів... + +### Попередні CORS-запити (preflight requests) + +Це будь-які `OPTIONS` - запити, що містять заголовки `Origin` та `Access-Control-Request-Method`. + +У такому випадку middleware перехопить вхідний запит і відповість відповідними CORS-заголовками, повертаючи або `200`, або `400` для інформаційних цілей. + +### Прості запити + +Будь-які запити із заголовком `Origin`. У цьому випадку middleware пропустить запит як звичайний, але додасть відповідні CORS-заголовки у відповідь. + +## Додаткова інформація + +Більше про CORS можна дізнатися в документації Mozilla. + +/// note | Технічні деталі + +Також можна використовувати `from starlette.middleware.cors import CORSMiddleware`. + +**FastAPI** надає кілька middleware у `fastapi.middleware` для зручності розробників. Але більшість доступних middleware походять безпосередньо зі Starlette. + +/// diff --git a/docs/uk/docs/tutorial/handling-errors.md b/docs/uk/docs/tutorial/handling-errors.md new file mode 100644 index 000000000..12a356cd0 --- /dev/null +++ b/docs/uk/docs/tutorial/handling-errors.md @@ -0,0 +1,255 @@ +# Обробка Помилок + +Є багато ситуацій, коли потрібно повідомити клієнта, який використовує Ваш API, про помилку. + +Цим клієнтом може бути браузер із фронтендом, код іншого розробника, IoT-пристрій тощо. + +Можливо, Вам потрібно повідомити клієнта, що: + +* У нього недостатньо прав для виконання цієї операції. +* Він не має доступу до цього ресурсу. +* Елемент, до якого він намагається отримати доступ, не існує. +* тощо. + +У таких випадках зазвичай повертається **HTTP статус-код** в діапазоні **400** (від 400 до 499). + +Це схоже на HTTP статус-коди 200 (від 200 до 299). Ці "200" статус-коди означають, що запит пройшов успішно. + +Статус-коди в діапазоні 400 означають, що сталася помилка з боку клієнта. + +Пам'ятаєте всі ці помилки **404 Not Found** (і жарти про них)? + +## Використання `HTTPException` + +Щоб повернути HTTP-відповіді з помилками клієнту, використовуйте `HTTPException`. + +### Імпорт `HTTPException` + +{* ../../docs_src/handling_errors/tutorial001.py hl[1] *} + +### Використання `HTTPException` у коді + +`HTTPException` — це звичайна помилка Python із додатковими даними, які стосуються API. + +Оскільки це помилка Python, Ви не `повертаєте` його, а `генеруєте` (генеруєте помилку). + +Це також означає, що якщо Ви перебуваєте всередині допоміжної функції, яку викликаєте всередині своєї *функції операції шляху*, і там генеруєте `HTTPException`, всередині цієї допоміжної функції, то решта коду в *функції операції шляху* не буде виконана. Запит одразу завершиться, і HTTP-помилка з `HTTPException` буде надіслана клієнту. + +Перевага використання `генерації` (raise) помилки замість `повернення` значення (return) стане більш очевидним в розділі про Залежності та Безпеку. + +У цьому прикладі, якщо клієнт запитує елемент за ID, якого не існує, буде згенеровано помилку зі статус-кодом `404`: + +{* ../../docs_src/handling_errors/tutorial001.py hl[11] *} + +### Отримана відповідь + +Якщо клієнт робить запит за шляхом `http://example.com/items/foo` (де `item_id` `"foo"`), він отримає статус-код 200 і JSON відповідь: + +```JSON +{ + "item": "The Foo Wrestlers" +} +``` + +Але якщо клієнт робить запит на `http://example.com/items/bar` (де `item_id` має не існуюче значення `"bar"`), то отримає статус-код 404 (помилка "не знайдено") та відповідь: + +```JSON +{ + "detail": "Item not found" +} +``` + +/// tip | Порада + +Під час виклику `HTTPException` Ви можете передати будь-яке значення, яке може бути перетворене в JSON, як параметр `detail`, а не лише рядок (`str`). + +Ви можете передати `dict`, `list` тощо. + +Вони обробляються автоматично за допомогою **FastAPI** та перетворюються в JSON. + +/// + +## Додавання власних заголовків + +Іноді потрібно додати власні заголовки до HTTP-помилки, наприклад, для певних типів безпеки. + +Ймовірно, Вам не доведеться використовувати це безпосередньо у своєму коді. + +Але якщо Вам знадобиться це для складного сценарію, Ви можете додати власні заголовки: + +{* ../../docs_src/handling_errors/tutorial002.py hl[14] *} + +## Встановлення власних обробників помилок + +Ви можете додати власні обробники помилок за допомогою тих самих утиліт обробки помилок зі Starlette. + +Припустимо, у Вас є власний обʼєкт помилки `UnicornException`, яке Ви (або бібліотека, яку Ви використовуєте) може `згенерувати` (`raise`). + +І Ви хочете обробляти це виключення глобально за допомогою FastAPI. + +Ви можете додати власний обробник виключень за допомогою `@app.exception_handler()`: + +{* ../../docs_src/handling_errors/tutorial003.py hl[5:7,13:18,24] *} + +Тут, якщо Ви звернетеся до `/unicorns/yolo`, то згенерується помилка `UnicornException`. + +Але вона буде оброблена функцією-обробником `unicorn_exception_handler`. + +Отже, Ви отримаєте зрозумілу помилку зі HTTP-статусом `418` і JSON-відповіддю: + +```JSON +{"message": "Oops! yolo did something. There goes a rainbow..."} +``` + +/// note | Технічні деталі + +Ви також можете використовувати `from starlette.requests import Request` і `from starlette.responses import JSONResponse`. + +**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. Те ж саме стосується і `Request`. + +/// + +## Перевизначення обробників помилок за замовчуванням + +**FastAPI** має кілька обробників помилок за замовчуванням. + +Ці обробники відповідають за повернення стандартних JSON-відповідей, коли Ви `генеруєте` (`raise`) `HTTPException`, а також коли запит містить некоректні дані. + +Ви можете перевизначити ці обробники, створивши власні. + +### Перевизначення помилок валідації запиту + +Коли запит містить некоректні дані, **FastAPI** генерує `RequestValidationError`. + +І також включає обробник помилок за замовчуванням для нього. + +Щоб перевизначити його, імпортуйте `RequestValidationError` і використовуйте його з `@app.exception_handler(RequestValidationError)` для декорування обробника помилок. + +Обробник помилок отримує `Request` і саму помилку. + +{* ../../docs_src/handling_errors/tutorial004.py hl[2,14:16] *} + +Тепер, якщо Ви перейдете за посиланням `/items/foo`, замість того, щоб отримати стандартну JSON-помилку: + +```JSON +{ + "detail": [ + { + "loc": [ + "path", + "item_id" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ] +} +``` + +Ви отримаєте текстову версію: + +``` +1 validation error +path -> item_id + value is not a valid integer (type=type_error.integer) +``` + +#### `RequestValidationError` проти `ValidationError` + +/// warning | Увага + +Це технічні деталі, які Ви можете пропустити, якщо вони зараз не важливі для Вас. + +/// + +`RequestValidationError` є підкласом Pydantic `ValidationError`. + +**FastAPI** використовує його для того, якщо Ви використовуєте модель Pydantic у `response_model` і у ваших даних є помилка, Ви побачили помилку у своєму журналі. + +Але клієнт/користувач не побачить її. Натомість клієнт отримає "Internal Server Error" зі статусом HTTP `500`. + +Так має бути, якщо у Вас виникла `ValidationError` Pydantic у *відповіді* або деінде у вашому коді (не у *запиті* клієнта), це насправді є помилкою у Вашому коді. + +І поки Ви її виправляєте, клієнти/користувачі не повинні мати доступу до внутрішньої інформації про помилку, оскільки це може призвести до вразливості безпеки. + +### Перевизначення обробника помилок `HTTPException` + +Аналогічно, Ви можете перевизначити обробник `HTTPException`. + +Наприклад, Ви можете захотіти повернути текстову відповідь замість JSON для цих помилок: + +{* ../../docs_src/handling_errors/tutorial004.py hl[3:4,9:11,22] *} + +/// note | Технічні деталі + +Ви також можете використовувати `from starlette.responses import PlainTextResponse`. + +**FastAPI** надає ті самі `starlette.responses`, що й `fastapi.responses`, просто для зручності розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette. + +/// + +### Використання тіла `RequestValidationError` + +`RequestValidationError` містить `body`, який він отримав із некоректними даними. + +Ви можете використовувати це під час розробки свого додатка, щоб логувати тіло запиту та налагоджувати його, повертати користувачеві тощо. + +{* ../../docs_src/handling_errors/tutorial005.py hl[14] *} + +Тепер спробуйте надіслати некоректний елемент, наприклад: + +```JSON +{ + "title": "towel", + "size": "XL" +} +``` +Ви отримаєте відповідь, яка повідомить Вам, які саме дані є некоректні у вашому тілі запиту: + + +```JSON hl_lines="12-15" +{ + "detail": [ + { + "loc": [ + "body", + "size" + ], + "msg": "value is not a valid integer", + "type": "type_error.integer" + } + ], + "body": { + "title": "towel", + "size": "XL" + } +} +``` + +#### `HTTPException` FastAPI проти `HTTPException` Starlette + +**FastAPI** має власний `HTTPException`. + +І клас помилки `HTTPException` в **FastAPI** успадковується від класу помилки `HTTPException` в Starlette. + +Єдина різниця полягає в тому, що `HTTPException` в **FastAPI** приймає будь-які дані, які можна перетворити на JSON, для поля `detail`, тоді як `HTTPException` у Starlette приймає тільки рядки. + +Отже, Ви можете продовжувати використовувати `HTTPException` в **FastAPI** як зазвичай у своєму коді. + +Але коли Ви реєструєте обробник виключень, слід реєструвати його для `HTTPException` зі Starlette. + +Таким чином, якщо будь-яка частина внутрішнього коду Starlette або розширення чи плагін Starlette згенерує (raise) `HTTPException`, Ваш обробник зможе перехопити та обробити її. + +У цьому прикладі, щоб мати можливість використовувати обидва `HTTPException` в одному коді, помилка Starlette перейменовується на `StarletteHTTPException`: + +```Python +from starlette.exceptions import HTTPException as StarletteHTTPException +``` + +### Повторне використання обробників помилок **FastAPI** + +Якщо Ви хочете використовувати помилки разом із такими ж обробниками помилок за замовчуванням, як у **FastAPI**, Ви можете імпортувати та повторно використовувати їх із `fastapi.exception_handlers`: + +{* ../../docs_src/handling_errors/tutorial006.py hl[2:5,15,21] *} + +У цьому прикладі Ви просто використовуєте `print` для виведення дуже інформативного повідомлення, але Ви зрозуміли основну ідею. Ви можете обробити помилку та повторно використовувати обробники помилок за замовчуванням. diff --git a/docs/uk/docs/tutorial/middleware.md b/docs/uk/docs/tutorial/middleware.md new file mode 100644 index 000000000..807be484a --- /dev/null +++ b/docs/uk/docs/tutorial/middleware.md @@ -0,0 +1,75 @@ +# Middleware (Проміжний шар) + +У **FastAPI** можна додавати middleware (проміжний шар). + +"Middleware" — це функція, яка працює з кожним **запитом** перед його обробкою будь-якою конкретною *операцією шляху* (*path operation*), а також з кожною **відповіддю** перед її поверненням. + +* Middleware отримує кожен **запит**, що надходить до Вашого застосунку. +* Може виконати певні дії із цим **запитом** або запустити необхідний код. +* Далі передає **запит** для обробки основним застосунком (*операцією шляху*). +* Отримує **відповідь**, сформовану застосунком (*операцією шляху*). +* Може змінити цю **відповідь** або виконати додатковий код. +* Повертає **відповідь** клієнту. + +/// note | Технічні деталі + +Якщо у Вас є залежності з `yield`, код виходу виконається *після* middleware. + +Якщо були заплановані фонові задачі (background tasks - розглянуто далі), вони виконаються *після* всіх middleware. + +/// + +## Створення middleware + +Щоб створити middleware, Ви використовуєте декоратор `@app.middleware("http")` на функції. + +Функція middleware отримує: + +* `Запит`. +* Функцію `call_next`, яка приймає `запит` як параметр. + * Ця функція передає `запит` відповідній *операції шляху*. + * Потім вона повертає `відповідь`, згенеровану цією *операцією шляху*. + +* Ви можете ще змінити `відповідь` перед тим, як повернути її. + + +{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *} + +/// tip | Порада + +Не забувайте, що власні заголовки можна додавати, використовуючи префікс 'X-'. + +Але якщо у Вас є власні заголовки, які Ви хочете, щоб браузерний клієнт міг побачити, потрібно додати їх до Вашої конфігурації CORS (див. [CORS (Обмін ресурсами між різними джерелами)](cors.md){.internal-link target=_blank} за допомогою параметра `expose_headers`, описаного в документації Starlette по CORS. + +/// + +/// note | Технічні деталі + +Ви також можете використати `from starlette.requests import Request`. + +**FastAPI** надає це для Вашої зручності як розробника. Але він походить безпосередньо зі Starlette. + +/// + +### До і після `response`(`відповіді`) + +Ви можете додати код, який буде виконуватися з `запитом` (`request`), до того, як його обробить будь-яка *операція шляху* (*path operation*). + +Також Ви можете додати код, який буде виконуватися після того, як `відповідь` (`response`) буде згенеровано, перед тим як його повернути. + +Наприклад, Ви можете додати власний заголовок `X-Process-Time`, який міститиме час у секундах, який витратився на обробку запиту та генерацію відповіді: + +{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *} + + +/// tip | Підказка + +Тут ми використовуємо `time.perf_counter()` замість `time.time()` оскільки він може бути більш точним для таких випадків. 🤓 + +/// + +## Інші middlewares + +Ви можете пізніше прочитати більше про інші middlewares в [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank}. + +Ви дізнаєтесь, як обробляти CORS за допомогою middleware в наступному розділі. diff --git a/docs/uk/docs/tutorial/path-params-numeric-validations.md b/docs/uk/docs/tutorial/path-params-numeric-validations.md new file mode 100644 index 000000000..281ee183c --- /dev/null +++ b/docs/uk/docs/tutorial/path-params-numeric-validations.md @@ -0,0 +1,165 @@ +# Path Параметри та валідація числових даних + +Так само як Ви можете оголошувати додаткові перевірки та метадані для query параметрів за допомогою `Query`, Ви можете оголошувати той самий тип перевірок і метаданих для параметрів шляху за допомогою `Path`. + +## Імпорт Path + +Спочатку імпортуйте `Path` з `fastapi` і імпортуйте `Annotated`: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *} + +/// info | Інформація + +FastAPI додав підтримку `Annotated` (і почав рекомендувати його використання) у версії 0.95.0. + +Якщо у Вас стара версія, при спробі використати `Annotated` можуть виникати помилки. + +Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} принаймні до версії 0.95.1 перед використанням `Annotated`. + +/// + +## Оголошення метаданих + +Ви можете оголошувати всі ті ж параметри, що і для `Query`. + +Наприклад, щоб оголосити значення метаданих `title` для параметра шляху `item_id`, Ви можете написати: + +{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *} + +/// note | Примітка + +Параметр шляху завжди є обов’язковим, оскільки він має бути частиною шляху. Навіть якщо Ви оголосите його зі значенням `None` або встановите значення за замовчуванням — він все одно залишатиметься обов’язковим. + +/// + +## Упорядковуйте параметри, як Вам потрібно + +/// tip | Підказка + +Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`. + +/// + +Припустимо, Ви хочете оголосити параметр запиту `q` як обов’язковий `str`. + +І Вам не потрібно оголошувати нічого іншого для цього параметра, тому немає потреби використовувати `Query`. + +Але Вам все одно потрібно використовувати `Path` для параметра шляху `item_id`. І з певних причин Ви не хочете використовувати `Annotated`. + +Python видасть помилку, якщо розмістити значення з "default" перед значенням, яке не має "default". + +Але Ви можете змінити порядок і розмістити значення без значення за замовчуванням (параметр запиту `q`) першим. + + +Для **FastAPI** порядок не має значення. Він визначає параметри за їх іменами, типами та значеннями за замовчуванням (`Query`, `Path` тощо) і не звертає уваги на порядок. + +Тому Ви можете оголосити Вашу функцію так: + +//// tab | Python 3.8 non-Annotated + +/// tip | Підказка + +За можливості віддавайте перевагу версії з використанням `Annotated`. + +/// + +{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[7] *} + +//// + +Але майте на увазі, що якщо Ви використовуєте `Annotated`, ця проблема не виникне, оскільки Ви не використовуєте значення за замовчуванням для параметрів `Query()` або `Path()`. + +{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *} + +## Упорядковуйте параметри за потребою, хитрощі + +/// tip | Підказка + +Це, мабуть, не настільки важливо або необхідно, якщо Ви використовуєте `Annotated`. + +/// + +Ось **невелика хитрість**, яка може стати в пригоді, хоча вона рідко знадобиться. + +Якщо Ви хочете: + +* оголосити параметр запиту `q` без використання `Query` або значення за замовчуванням +* оголосити параметр шляху `item_id`, використовуючи `Path` +* розмістити їх у різному порядку +* не використовувати `Annotated` + +...у Python є спеціальний синтаксис для цього. + +Передайте `*` як перший параметр функції. + +Python нічого не зробить із цією `*`, але розпізнає, що всі наступні параметри слід викликати як аргументи за ключовим словом (пари ключ-значення), також відомі як kwargs. Навіть якщо вони не мають значення за замовчуванням. + +{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[7] *} + +### Краще з `Annotated` + +Майте на увазі, якщо Ви використовуєте `Annotated`, оскільки Ви не використовуєте значення за замовчуванням для параметрів функції, цієї проблеми не виникне, і, швидше за все, Вам не потрібно буде використовувати `*`. + +{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *} + +## Валідація числових даних: більше або дорівнює + +За допомогою `Query` і `Path` (та інших, які Ви побачите пізніше) можна оголошувати числові обмеження. + +Тут, завдяки `ge=1`, `item_id` має бути цілим числом, яке "`g`reater than or `e`qual" (більше або дорівнює) `1`. + +{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *} + +## Валідація числових даних: більше ніж і менше або дорівнює + +Те саме застосовується до: + +* `gt`: `g`reater `t`han (більше ніж) +* `le`: `l`ess than or `e`qual (менше або дорівнює) + +{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *} + +## Валідація числових даних: float, більше ніж і менше ніж + +Валідація чисел також працює для значень типу `float`. + +Ось де стає важливо мати можливість оголошувати gt, а не тільки ge. Це дозволяє, наприклад, вимагати, щоб значення було більше `0`, навіть якщо воно менше `1`. + +Таким чином, значення `0.5` буде допустимим. Але `0.0` або `0` — ні. + +Те саме стосується lt. + +{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *} + +## Підсумок + +За допомогою `Query`, `Path` (і інших параметрів, які Ви ще не бачили) можна оголошувати метадані та перевірки рядків, так само як у [Query параметри та валідація рядків](query-params-str-validations.md){.internal-link target=_blank}. + +Також можна оголошувати числові перевірки: + +* `gt`: `g`reater `t`han (більше ніж) +* `ge`: `g`reater than or `e`qual (більше або дорівнює) +* `lt`: `l`ess `t`han (менше ніж) +* `le`: `l`ess than or `e`qual (менше або дорівнює) + +/// info | Інформація + +`Query`, `Path` та інші класи, які Ви побачите пізніше, є підкласами спільного класу `Param`. + +Всі вони мають однакові параметри для додаткових перевірок і метаданих, які Ви вже бачили. + +/// + +/// note | Технічні деталі + +Коли Ви імпортуєте `Query`, `Path` та інші з `fastapi`, насправді це функції. + +При виклику вони повертають екземпляри класів з такими ж іменами. + +Тобто Ви імпортуєте `Query`, яка є функцією. А коли Ви її викликаєте, вона повертає екземпляр класу, який теж називається `Query`. + +Ці функції створені таким чином (замість використання класів напряму), щоб Ваш редактор не відзначав їхні типи як помилки. + +Таким чином, Ви можете користуватися своїм звичайним редактором і інструментами для програмування без додаткових налаштувань для ігнорування таких помилок. + +/// diff --git a/docs/uk/docs/tutorial/query-param-models.md b/docs/uk/docs/tutorial/query-param-models.md new file mode 100644 index 000000000..97eb82fa1 --- /dev/null +++ b/docs/uk/docs/tutorial/query-param-models.md @@ -0,0 +1,68 @@ +# Моделі Query параметрів + +Якщо у Вас є група **query параметрів**, які пов’язані між собою, Ви можете створити **Pydantic-модель** для їх оголошення. + +Це дозволить Вам **повторно використовувати модель** у **різних місцях**, а також оголошувати перевірки та метадані для всіх параметрів одночасно. 😎 + +/// note | Примітка + +Ця можливість підтримується, починаючи з версії FastAPI `0.115.0`. 🤓 + +/// + +## Query параметри з Pydantic-моделлю + +Оголосіть **query параметри**, які Вам потрібні, у **Pydantic-моделі**, а потім оголосіть цей параметр як `Query`: + +{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *} + +**FastAPI** буде **витягувати** дані для **кожного поля** з **query параметрів** у запиті та передавати їх у визначену вами Pydantic-модель. + +## Перевірте документацію + +Ви можете побачити параметри запиту в UI документації за `/docs`: + +
+ +
+ +## Заборона зайвих Query параметрів + +У деяких особливих випадках (ймовірно, не дуже поширених) Ви можете захотіти **обмежити** query параметри, які дозволено отримувати. + +Ви можете використати конфігурацію моделі Pydantic, щоб заборонити (`forbid`) будь-які зайві (`extra`) поля: + +{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *} + +Якщо клієнт спробує надіслати **зайві** дані у **query параметрах**, він отримає **помилку**. + +Наприклад, якщо клієнт спробує надіслати query параметр `tool` зі значенням `plumbus`, як у цьому запиті: + +```http +https://example.com/items/?limit=10&tool=plumbus +``` + +Він отримає відповідь з **помилкою**, яка повідомить, що query параметр `tool ` не дозволено: + +```json +{ + "detail": [ + { + "type": "extra_forbidden", + "loc": ["query", "tool"], + "msg": "Extra inputs are not permitted", + "input": "plumbus" + } + ] +} +``` + +## Підсумок + +Ви можете використовувати **Pydantic-моделі** для оголошення **query параметрів** у **FastAPI**. 😎 + +/// tip | Підказка + +Спойлер: Ви також можете використовувати Pydantic-моделі для оголошення cookie та заголовків, але про це Ви дізнаєтеся пізніше в цьому посібнику. 🤫 + +/// diff --git a/docs/uk/docs/tutorial/query-params-str-validations.md b/docs/uk/docs/tutorial/query-params-str-validations.md new file mode 100644 index 000000000..cd3f4ad93 --- /dev/null +++ b/docs/uk/docs/tutorial/query-params-str-validations.md @@ -0,0 +1,491 @@ +# Query параметри та валідація рядків + +**FastAPI** дозволяє оголошувати додаткову інформацію та виконувати валідацію для Ваших параметрів. + +Розглянемо цей додаток як приклад: + +{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *} + +Query параметр `q` має тип `str | None`, що означає, що він може бути як `str`, так і `None`. За замовчуванням він має значення `None`, тому FastAPI розуміє, що цей параметр не є обов'язковим. + +/// note | Примітка + +FastAPI знає, що `q` не є обов’язковим, завдяки значенню за замовчуванням `= None`. + +Використання `str | None` дозволить Вашому редактору коду надавати кращу підтримку та виявляти помилки. + +/// + +## Додаткова валідація + +Ми хочемо, щоб навіть якщо `q` є необов’язковим, **його довжина не перевищувала 50 символів**, якщо він все ж буде переданий. + +### Імпорт `Query` та `Annotated` + +Щоб це зробити, спочатку імпортуємо: + +* `Query` з `fastapi` +* `Annotated` з `typing` + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} + +/// info | Інформація + +FastAPI додав підтримку `Annotated` (і почав рекомендувати його) у версії 0.95.0. + +Якщо у Вас старіша версія, під час використання `Annotated` можуть виникати помилки. + +Переконайтеся, що Ви [оновили версію FastAPI](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} до принаймні 0.95.1, перш ніж використовувати `Annotated`. + +/// + +## Використання `Annotated` у типі параметра `q` + +Пам’ятаєте, як я раніше розповідав, що `Annotated` можна використовувати для додавання метаданих до параметрів у [Вступі до типів Python](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank}? + +Зараз саме час використати його разом із FastAPI. 🚀 + +Раніше ми мали таку анотацію типу: + +//// tab | Python 3.10+ + +```Python +q: str | None = None +``` + +//// + +//// tab | Python 3.8+ + +```Python +q: Union[str, None] = None +``` + +//// + +Тепер ми загорнемо її у `Annotated`, і отримаємо: + +//// tab | Python 3.10+ + +```Python +q: Annotated[str | None] = None +``` + +//// + +//// tab | Python 3.8+ + +```Python +q: Annotated[Union[str, None]] = None +``` + +//// + +Обидві ці версії означають одне й те саме: `q` — це параметр, який може бути `str` або `None`, і за замовчуванням має значення `None`. + +А тепер переходимо до цікавого! 🎉 + +## Додавання `Query` до `Annotated` у параметр `q` + +Тепер, коли у нас є `Annotated`, де ми можемо додавати додаткову інформацію (зокрема валідацію), додамо `Query` всередину `Annotated` і встановимо параметр `max_length` у `50`: + +{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *} + +Зверніть увагу, що значення за замовчуванням усе ще `None`, тому параметр залишається необов'язковим. + +Але тепер, додавши `Query(max_length=50)` всередину `Annotated`, ми повідомляємо FastAPI, що хочемо **додаткову валідацію** для цього значення — воно має містити максимум 50 символів. 😎 + +/// tip | Підказка + +Ми використовуємо `Query()`, оскільки це **query параметр**. Далі ми розглянемо інші варіанти, як-от `Path()`, `Body()`, `Header()` та `Cookie()`, які приймають ті самі аргументи, що й `Query()`. + +/// + +Тепер FastAPI: + +* **Перевірить** дані, щоб переконатися, що їхня довжина не перевищує 50 символів +* Покажe **чітку помилку** клієнту, якщо дані недійсні +* **Задокументує** параметр в OpenAPI-схемі *операції шляху* (що відобразиться в **автоматично згенерованій документації**) + +## Альтернативний (застарілий) метод: Query як значення за замовчуванням + +У попередніх версіях FastAPI (до 0.95.0) `Query` використовувався як значення за замовчуванням для параметра, а не всередині `Annotated`. Ви, ймовірно, побачите код, який використовує цей підхід, тому варто розглянути його. + +/// tip | Підказка + +Для нового коду та коли це можливо, використовуйте `Annotated`, як показано вище. Це має багато переваг (пояснених нижче) і не має недоліків. 🍰 + +/// + +Раніше ми писали `Query()` як значення за замовчуванням для параметра функції, встановлюючи `max_length` у 50: + +{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *} + +Оскільки в цьому випадку (без `Annotated`) нам потрібно замінити `None` у функції на `Query()`, тепер ми повинні явно встановити значення за замовчуванням через параметр `Query(default=None)`. Це виконує ту саму роль визначення значення за замовчуванням (принаймні для FastAPI). + +Таким чином: + +```Python +q: str | None = Query(default=None) +``` + +...робить параметр необов’язковим зі значенням за замовчуванням `None`, що еквівалентно: + + +```Python +q: str | None = None +``` +Але у версії з `Query` ми явно вказуємо, що це query параметр. + +Далі ми можемо передавати `Query` додаткові параметри, зокрема `max_length`, який застосовується до рядків: + +```Python +q: str | None = Query(default=None, max_length=50) +``` + +Це забезпечить валідацію даних, виведе зрозумілу помилку у разі недійсних даних і задокументує параметр у схемі OpenAPI *операції шляху*. + +### `Query` як значення за замовчуванням або всередині `Annotated` + +Важливо пам’ятати, якщо використовувати `Query` всередині `Annotated`, не можна задавати параметр `default` у `Query`. + +Замість цього використовуйте значення за замовчуванням у самій функції. Інакше це буде нелогічно. + +Наприклад, цей варіант є некоректним: + +```Python +q: Annotated[str, Query(default="rick")] = "morty" +``` + +...тому, що не зрозуміло, яке значення має бути значенням за замовчуванням: `"rick"` чи `"morty"`. + +Коректні варіанти: + +```Python +q: Annotated[str, Query()] = "rick" +``` + +...або у старих кодових базах Ви знайдете: + +```Python +q: str = Query(default="rick") +``` + +### Переваги використання `Annotated` + +**Використання `Annotated` є рекомендованим** замість задання значення за замовчуванням у параметрах функції, оскільки воно **краще** з кількох причин. 🤓 + +Значення **за замовчуванням** параметра **функції** є його **фактичним значенням за замовчуванням**, що є більш інтуїтивним у Python загалом. 😌 + +Ви можете **викликати** ту саму функцію **в інших місцях** без FastAPI, і вона **працюватиме очікувано**. Якщо параметр є **обов’язковим** (без значення за замовчуванням), Ваш **редактор** повідомить про помилку, а **Python** також видасть помилку, якщо Ви виконаєте функцію без передавання цього параметра. + +Якщо Ви не використовуєте `Annotated`, а використовуєте **(старий) стиль значень за замовчуванням**, то при виклику цієї функції без FastAPI **в інших місцях**, потрібно **не забути** передати їй аргументи, інакше значення будуть відрізнятися від очікуваних (наприклад, Ви отримаєте `QueryInfo` або подібне замість `str`). Ваш редактор не повідомить про помилку, і Python також не видасть помилку при запуску функції, поки не виникне помилка під час виконання операцій усередині. + +Оскільки `Annotated` може містити кілька анотацій метаданих, Ви навіть можете використовувати ту саму функцію з іншими інструментами, такими як Typer. 🚀 + +## Додавання додаткових валідацій + +Ви також можете додати параметр `min_length`: + +{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} + +## Додавання регулярних виразів + +Ви можете визначити регулярний вираз pattern, якому має відповідати параметр: + +{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} + +Цей конкретний шаблон регулярного виразу перевіряє, що отримане значення параметра: + +* `^`: починається з наступних символів, перед якими немає інших символів. +* `fixedquery`: точно відповідає значенню `fixedquery`. +* `$`: закінчується тут, після `fixedquery` немає жодних символів. + +Якщо Ви почуваєтеся розгублено щодо **"регулярних виразів"**, не хвилюйтеся. Вони є складною темою для багатьох людей. Ви все одно можете зробити багато речей без їх використання. + +Але тепер Ви знаєте, що коли вони знадобляться, їх можна застосовувати у **FastAPI**. + +### Pydantic v1 `regex` замість `pattern` + +До версії Pydantic 2 і FastAPI 0.100.0 параметр називався `regex` замість `pattern`, але тепер він застарів. + +Ви все ще можете зустріти код, який використовує його: + +//// tab | Pydantic v1 + +{* ../../docs_src/query_params_str_validations/tutorial004_regex_an_py310.py hl[11] *} + +//// + +Але майте на увазі, що він є застарілим і його слід оновити до нового параметра `pattern`. 🤓 + +## Значення за замовчуванням + +Ви можете використовувати значення за замовчуванням, відмінні від `None`. + +Наприклад, якщо Ви хочете оголосити параметр запиту `q` з `min_length` `3` і значенням за замовчуванням `"fixedquery"`: + +{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *} + +/// note | Технічні деталі + +Наявність значення за замовчуванням будь-якого типу, включаючи `None`, робить параметр необов’язковим (not required). + +/// + +## Обов’язкові параметри + +Якщо нам не потрібно вказувати додаткові перевірки або метадані, ми можемо зробити параметр `q` обов’язковим, просто не оголошуючи значення за замовчуванням, наприклад: + +```Python +q: str +``` + +замість: + +```Python +q: str | None = None +``` + +Але тепер ми оголошуємо його з `Query`, наприклад: + +//// tab | Annotated + +```Python +q: Annotated[str | None, Query(min_length=3)] = None +``` + +//// + +Тому, якщо Вам потрібно зробити значення обов’язковим, використовуючи `Query`, просто не вказуйте значення за замовчуванням: + +{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *} + +### Обов’язкове значення, яке може бути `None` + +Ви можете вказати, що параметр може приймати `None`, але при цьому залишається обов’язковим. Це змусить клієнтів надіслати значення, навіть якщо воно дорівнює `None`. + +Щоб зробити це, оголосіть, що `None` є допустимим типом, але не вказуйте значення за замовчуванням: + +{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *} + +## Список параметрів запиту / кілька значень + +Якщо Ви визначаєте параметр запиту за допомогою `Query`, Ви також можете дозволити отримання списку значень, тобто дозволити отримання кількох значень. + +Наприклад, щоб дозволити параметру запиту `q` з'являтися кілька разів в URL, можна написати: + +{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} + +Тоді, у випадку запиту за URL: + +``` +http://localhost:8000/items/?q=foo&q=bar +``` + +Ви отримаєте кілька значень *query параметра* `q` (`foo` і `bar`) у вигляді списку `list` в Python у Вашій *функції обробки шляху*, у *параметрі функції* `q`. + +Отже, відповідь на цей URL буде: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +/// tip | Підказка + +Щоб оголосити параметр запиту з типом `list`, як у наведеному вище прикладі, потрібно явно використовувати `Query`, інакше він буде інтерпретований як тіло запиту. + +/// + +Інтерактивна API-документація оновиться відповідно, дозволяючи передавати кілька значень: + + + +### Список параметрів запиту / кілька значень за замовчуванням + +Ви також можете визначити значення за замовчуванням для `list`, якщо жодне значення не було передане: + +{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *} + +Якщо Ви перейдете за посиланням: + +``` +http://localhost:8000/items/ +``` + +то значення `q` за замовчуванням буде: `["foo", "bar"]`, і Ваша відповідь виглядатиме так: + +```JSON +{ + "q": [ + "foo", + "bar" + ] +} +``` + +#### Використання тільки `list` + +Ви також можете використовувати `list` без уточнення типу, замість `list[str]`: + +{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *} + +/// note | Технічні деталі + +Майте на увазі, що в цьому випадку FastAPI не перевірятиме вміст списку. + +Наприклад, `list[int]` перевірятиме (і документуватиме), що всі елементи списку є цілими числами. Але `list` без уточнення цього не робитиме. + +/// + +## Додавання додаткових метаданих + +Ви можете додати більше інформації про параметр. + +Ця інформація буде включена у згенерований OpenAPI та використана в інтерфейсах документації та зовнішніх інструментах. + +/// note | Технічні деталі + +Майте на увазі, що різні інструменти можуть мати різний рівень підтримки OpenAPI. + +Деякі з них можуть ще не відображати всю додаткову інформацію, хоча в більшості випадків ця функція вже запланована для розробки. + +/// + +Ви можете додати `title` : + +{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *} + +А також `description`: + +{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *} + +## Аліаси параметрів + +Уявіть, що Ви хочете, щоб параметр називався `item-query`. + +Наприклад: + +``` +http://127.0.0.1:8000/items/?item-query=foobaritems +``` + +Але `item-query` — це некоректна назва змінної в Python. + +Найближчий допустимий варіант — `item_query`. + +Проте Вам потрібно, щоб параметр залишався саме `item-query`... + +У такому випадку можна оголосити `alias`, і саме він буде використовуватися для отримання значення параметра: + +{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *} + +## Виведення параметрів як застарілих + +Припустимо, що Ви більше не хочете використовувати цей параметр. + +Вам потрібно залишити його на деякий час, оскільки ним користуються клієнти, але Ви хочете, щоб документація чітко показувала, що він є застарілим. + +Тоді Ви можете передати параметр `deprecated=True` до `Query`: + +{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *} + +Документація буде показувати це таким чином: + + + +## Виняток параметрів з OpenAPI + +Щоб виключити параметр запиту зі згенерованої схеми OpenAPI (і, таким чином, з автоматичних систем документації), встановіть параметр `include_in_schema` для `Query` в `False`: + +{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} + +## Кастомна валідація + +Можуть бути випадки, коли Вам потрібно провести **кастомну валідацію**, яку не можна реалізувати за допомогою параметрів, показаних вище. + +У таких випадках ви можете використати **кастомну функцію валідації**, яка буде застосована після звичайної валідації (наприклад, після перевірки, що значення є типом `str`). + +Це можна досягти за допомогою Pydantic's `AfterValidator` в середині `Annotated`. + +/// tip | Підказка + +Pydantic також має `BeforeValidator` та інші. 🤓 + +/// + +Наприклад, цей кастомний валідатор перевіряє, чи починається ID елемента з `isbn-` для номера книги ISBN або з `imdb-` для ID URL фільму на IMDB: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *} + +/// info | Інформація + +Це доступно з версії Pydantic 2 або вище. 😎 + +/// + +/// tip | Підказка + +Якщо Вам потрібно виконати будь-яку валідацію, яка вимагає взаємодії з будь-яким **зовнішнім компонентом**, таким як база даних чи інший API, ви повинні замість цього використовувати **FastAPI Dependencies**. Ви дізнаєтесь про них пізніше. + +Ці кастомні валідатори використовуються для речей, які можна перевірити лише з **тими даними**, що надані в запиті. + +/// + +### Зрозумійте цей код + +Головний момент – це використання **`AfterValidator` з функцією всередині `Annotated`**. Можете пропустити цю частину, якщо хочете. 🤸 + +--- + +Але якщо Вам цікаво розібратися в цьому конкретному прикладі коду і Вам ще не набридло, ось кілька додаткових деталей. + +#### Рядок із `value.startswith()` + +Звернули увагу? Рядок із `value.startswith()` може приймати кортеж, і тоді він перевірятиме кожне значення в кортежі: + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *} + +#### Випадковий елемент + +За допомогою `data.items()` ми отримуємо ітерабельний об'єкт із кортежами, що містять ключ і значення для кожного елемента словника. + +Ми перетворюємо цей ітерабельний об'єкт у звичайний `list` за допомогою `list(data.items())`. + +Потім, використовуючи `random.choice()`, ми можемо отримати випадкове значення зі списку, тобто отримуємо кортеж із `(id, name)`. Це може бути щось на зразок `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`. + +Далі ми **присвоюємо ці два значення** кортежу змінним `id` і `name`. + +Тож, якщо користувач не вказав ID елемента, він все одно отримає випадкову рекомендацію. + +...і все це реалізовано в **одному рядку коду**. 🤯 Хіба не прекрасний Python? 🐍 + +{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} + +## Підсумок + +Ви можете оголошувати додаткові валідації та метаінформацію для своїх параметрів. + +Загальні валідації та метаінформація: + +* `alias` +* `title` +* `description` +* `deprecated` + +Валідації, специфічні для рядків: + +* `min_length` +* `max_length` +* `pattern` + +Кастомні валідації за допомогою `AfterValidator`. + +У цих прикладах Ви побачили, як оголошувати валідації для значень `str`. + +Дивіться наступні розділи, щоб дізнатися, як оголошувати валідації для інших типів, наприклад чисел. diff --git a/docs/zh/docs/python-types.md b/docs/zh/docs/python-types.md index 5126cb847..ba767da87 100644 --- a/docs/zh/docs/python-types.md +++ b/docs/zh/docs/python-types.md @@ -228,7 +228,7 @@ John Doe ## Pydantic 模型 -Pydantic 是一个用来用来执行数据校验的 Python 库。 +Pydantic 是一个用来执行数据校验的 Python 库。 你可以将数据的"结构"声明为具有属性的类。 diff --git a/requirements-docs.txt b/requirements-docs.txt index bd0082304..606314926 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -3,7 +3,7 @@ mkdocs-material==9.6.1 mdx-include >=1.4.1,<2.0.0 mkdocs-redirects>=1.2.1,<1.3.0 -typer == 0.15.3 +typer == 0.16.0 pyyaml >=5.3.1,<7.0.0 # For Material for MkDocs, Chinese search jieba==0.42.1 @@ -12,7 +12,7 @@ pillow==11.1.0 # For image processing by Material for MkDocs cairosvg==2.7.1 mkdocstrings[python]==0.26.1 -griffe-typingdoc==0.2.7 +griffe-typingdoc==0.2.8 # For griffe, it formats with black black==25.1.0 mkdocs-macros-plugin==1.3.7