🔥 Remove inactive/scarce translations to Vietnamese (#14543)

This commit is contained in:
Sebastián Ramírez 2025-12-16 13:05:18 -08:00 committed by GitHub
parent ed20bf6bf3
commit 818ce0fa2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 0 additions and 3074 deletions

View File

@ -331,8 +331,6 @@ extra:
name: tr - Türkçe
- link: /uk/
name: uk - українська мова
- link: /vi/
name: vi - Tiếng Việt
- link: /zh/
name: zh - 简体中文
- link: /zh-hant/

View File

@ -1,14 +0,0 @@
# Triển khai FastAPI trên các Dịch vụ Cloud
Bạn có thể sử dụng **bất kỳ nhà cung cấp dịch vụ cloud** nào để triển khai ứng dụng FastAPI của mình.
Trong hầu hết các trường hợp, các nhà cung cấp dịch vụ cloud lớn đều có hướng dẫn triển khai FastAPI với họ.
## Nhà cung cấp dịch vụ Cloud - Nhà tài trợ
Một vài nhà cung cấp dịch vụ cloud ✨ [**tài trợ cho FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, điều này giúp đảm bảo sự phát triển liên tục và khỏe mạnh của FastAPI và hệ sinh thái của nó.
Thêm nữa, điều này cũng thể hiện cam kết thực sự của họ đối với FastAPI và **cộng đồng người dùng** (bạn), vì họ không chỉ muốn cung cấp cho bạn một **dịch vụ tốt** mà còn muốn đảm bảo rằng bạn có một **framework tốt và bền vững**, đó chính là FastAPI. 🙇
Bạn có thể thử các dịch vụ của họ và làm theo hướng dẫn của họ:
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>

View File

@ -1,21 +0,0 @@
# Triển khai
Triển khai một ứng dụng **FastAPI** khá dễ dàng.
## Triển khai là gì
Triển khai một ứng dụng có nghĩa là thực hiện các bước cần thiết để làm cho nó **sẵn sàng phục vụ người dùng**.
Đối với một **API web**, điều này có nghĩa là đặt nó trong một **máy chủ từ xa**, với một **chương trình máy chủ** cung cấp hiệu suất tốt, ổn định, v.v., để người dùng của bạn có thể truy cập ứng dụng của bạn một cách hiệu quả và không bị gián đoạn hoặc gặp vấn đề.
Điều này trái ngược với các **giai đoạn phát triển**, trong đó bạn liên tục thay đổi mã, phá vỡ nó và sửa nó, ngừng và khởi động lại máy chủ phát triển, v.v.
## Các Chiến lược Triển khai
Có nhiều cách để triển khai ứng dụng của bạn tùy thuộc vào trường hợp sử dụng của bạn và các công cụ mà bạn sử dụng.
Bạn có thể **triển khai một máy chủ** của riêng bạn bằng cách sử dụng một sự kết hợp các công cụ, hoặc bạn có thể sử dụng một **dịch vụ cloud** để làm một số công việc cho bạn, hoặc các tùy chọn khác.
Tôi sẽ chỉ ra một số khái niệm chính cần thiết khi triển khai một ứng dụng **FastAPI** (mặc dù hầu hết nó áp dụng cho bất kỳ loại ứng dụng web nào).
Bạn sẽ thấy nhiều chi tiết cần thiết và một số kỹ thuật để triển khai trong các phần tiếp theo. ✨

View File

@ -1,93 +0,0 @@
# Về các phiên bản của FastAPI
**FastAPI** đã được sử dụng ở quy mô thực tế (production) trong nhiều ứng dụng và hệ thống. Và phạm vi kiểm thử được giữ ở mức 100%. Nhưng việc phát triển của nó vẫn đang diễn ra nhanh chóng.
Các tính năng mới được bổ sung thường xuyên, lỗi được sửa định kỳ, và mã nguồn vẫn đang được cải thiện liên tục
Đó là lí do các phiên bản hiện tại vẫn còn là 0.x.x, điều này phản ánh rằng mỗi phiên bản có thể có các thay đổi gây mất tương thích. Điều này tuân theo các quy ước về <a href="https://semver.org/" class="external-link" target="blank">Semantic Versioning</a>.
Bạn có thể tạo ra sản phẩm thực tế với **FastAPI** ngay bây giờ (và bạn có thể đã làm điều này trong một thời gian dài), bạn chỉ cần đảm bảo rằng bạn sử dụng một phiên bản hoạt động đúng với các đoạn mã còn lại của bạn.
## Cố định phiên bản của `fastapi`
Điều đầu tiên bạn nên làm là "cố định" phiên bản của **FastAPI** bạn đang sử dụng để phiên bản mới nhất mà bạn biết hoạt động đúng với ứng dụng của bạn.
Ví dụ, giả sử bạn đang sử dụng phiên bản `0.112.0` trong ứng dụng của bạn.
Nếu bạn sử dụng một tệp `requirements.txt` bạn có thể chỉ định phiên bản với:
```txt
fastapi[standard]==0.112.0
```
Như vậy, bạn sẽ sử dụng chính xác phiên bản `0.112.0`.
Hoặc bạn cũng có thể cố định nó với:
```txt
fastapi[standard]>=0.112.0,<0.113.0
```
Như vậy, bạn sẽ sử dụng các phiên bản `0.112.0` trở lên, nhưng nhỏ hơn `0.113.0`, ví dụ, một phiên bản `0.112.2` vẫn được chấp nhận.
Nếu bạn sử dụng bất kỳ công cụ nào để quản lý cài đặt của bạn, như `uv`, Poetry, Pipenv, hoặc bất kỳ công cụ nào khác, chúng đều có một cách để bạn có thể định nghĩa các phiên bản cụ thể cho các gói của bạn.
## Các phiên bản có sẵn
Bạn có thể xem các phiên bản có sẵn (ví dụ để kiểm tra phiên bản mới nhất) trong [Release Notes](../release-notes.md){.internal-link target=_blank}.
## Về các phiên bản
Theo quy ước về Semantic Versioning, bất kỳ phiên bản nào bên dưới `1.0.0` có thể thêm các thay đổi gây mất tương thích.
**FastAPI** cũng theo quy ước rằng bất kỳ thay đổi phiên bản "PATCH" nào là cho các lỗi và các thay đổi không gây mất tương thích.
/// tip
"PATCH" là số cuối cùng, ví dụ, trong `0.2.3`, phiên bản PATCH là `3`.
///
Vì vậy, bạn có thể cố định đến một phiên bản như:
```txt
fastapi>=0.45.0,<0.46.0
```
Các thay đổi gây mất tương thích và các tính năng mới được thêm vào trong các phiên bản "MINOR".
/// tip
"MINOR" là số ở giữa, ví dụ, trong `0.2.3`, phiên bản MINOR là `2`.
///
## Nâng cấp các phiên bản của FastAPI
Bạn nên thêm các bài kiểm tra (tests) cho ứng dụng của bạn.
Với **FastAPI** điều này rất dễ dàng (nhờ vào Starlette), kiểm tra tài liệu: [Testing](../tutorial/testing.md){.internal-link target=_blank}
Sau khi bạn có các bài kiểm tra, bạn có thể nâng cấp phiên bản **FastAPI** lên một phiên bản mới hơn, và đảm bảo rằng tất cả mã của bạn hoạt động đúng bằng cách chạy các bài kiểm tra của bạn.
Nếu mọi thứ đang hoạt động, hoặc sau khi bạn thực hiện các thay đổi cần thiết, và tất cả các bài kiểm tra của bạn đều đi qua, thì bạn có thể cố định phiên bản của `fastapi` đến phiên bản mới hơn.
## Về Starlette
Bạn không nên cố định phiên bản của `starlette`.
Các phiên bản khác nhau của **FastAPI** sẽ sử dụng một phiên bản Starlette mới hơn.
Vì vậy, bạn có thể để **FastAPI** sử dụng phiên bản Starlette phù hợp.
## Về Pydantic
Pydantic bao gồm các bài kiểm tra của riêng nó cho **FastAPI**, vì vậy các phiên bản mới hơn của Pydantic (trên `1.0.0`) luôn tương thích với **FastAPI**.
Bạn có thể cố định Pydantic đến bất kỳ phiên bản nào trên `1.0.0` mà bạn muốn.
Ví dụ:
```txt
pydantic>=2.7.0,<3.0.0
```

View File

@ -1,300 +0,0 @@
# Biến môi trường (Environment Variables)
/// tip
Nếu bạn đã biết về "biến môi trường" và cách sử dụng chúng, bạn có thể bỏ qua phần này.
///
Một biến môi trường (còn được gọi là "**env var**") là một biến mà tồn tại **bên ngoài** đoạn mã Python, ở trong **hệ điều hành**, và có thể được đọc bởi đoạn mã Python của bạn (hoặc bởi các chương trình khác).
Các biến môi trường có thể được sử dụng để xử lí **các thiết lập** của ứng dụng, như một phần của **các quá trình cài đặt** Python, v.v.
## Tạo và Sử dụng các Biến Môi Trường
Bạn có thể **tạo** và sử dụng các biến môi trường trong **shell (terminal)**, mà không cần sử dụng Python:
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
// Bạn có thể tạo một biến môi trường MY_NAME với
$ export MY_NAME="Wade Wilson"
// Sau đó bạn có thể sử dụng nó với các chương trình khác, như
$ echo "Hello $MY_NAME"
Hello Wade Wilson
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Tạo một biến môi trường MY_NAME
$ $Env:MY_NAME = "Wade Wilson"
// Sử dụng nó với các chương trình khác, như là
$ echo "Hello $Env:MY_NAME"
Hello Wade Wilson
```
</div>
////
## Đọc các Biến Môi Trường trong Python
Bạn cũng có thể tạo các biến môi trường **bên ngoài** đoạn mã Python, trong terminal (hoặc bằng bất kỳ phương pháp nào khác), và sau đó **đọc chúng trong Python**.
Ví dụ, bạn có một file `main.py` với:
```Python hl_lines="3"
import os
name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```
/// tip
Tham số thứ hai cho <a href="https://docs.python.org/3.8/library/os.html#os.getenv" class="external-link" target="_blank">`os.getenv()`</a> là giá trị mặc định để trả về.
Nếu không được cung cấp, nó mặc định là `None`, ở đây chúng ta cung cấp `"World"` là giá trị mặc định để sử dụng.
///
Sau đó bạn có thể gọi chương trình Python:
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
// Ở đây chúng ta chưa cài đặt biến môi trường
$ python main.py
// Vì chúng ta chưa cài đặt biến môi trường, chúng ta nhận được giá trị mặc định
Hello World from Python
// Nhưng nếu chúng ta tạo một biến môi trường trước đó
$ export MY_NAME="Wade Wilson"
// Và sau đó gọi chương trình lại
$ python main.py
// Bây giờ nó có thể đọc biến môi trường
Hello Wade Wilson from Python
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
// Ở đây chúng ta chưa cài đặt biến môi trường
$ python main.py
// Vì chúng ta chưa cài đặt biến môi trường, chúng ta nhận được giá trị mặc định
Hello World from Python
// Nhưng nếu chúng ta tạo một biến môi trường trước đó
$ $Env:MY_NAME = "Wade Wilson"
// Và sau đó gọi chương trình lại
$ python main.py
// Bây giờ nó có thể đọc biến môi trường
Hello Wade Wilson from Python
```
</div>
////
Vì các biến môi trường có thể được tạo bên ngoài đoạn mã Python, nhưng có thể được đọc bởi đoạn mã Python, và không cần được lưu trữ (commit vào `git`) cùng với các file khác, nên chúng thường được sử dụng để lưu các thiết lập hoặc **cấu hình**.
Bạn cũng có thể tạo ra một biến môi trường dành riêng cho một **lần gọi chương trình**, chỉ có thể được sử dụng bởi chương trình đó, và chỉ trong thời gian chạy của chương trình.
Để làm điều này, tạo nó ngay trước chương trình đó, trên cùng một dòng:
<div class="termy">
```console
// Tạo một biến môi trường MY_NAME cho lần gọi chương trình này
$ MY_NAME="Wade Wilson" python main.py
// Bây giờ nó có thể đọc biến môi trường
Hello Wade Wilson from Python
// Biến môi trường không còn tồn tại sau đó
$ python main.py
Hello World from Python
```
</div>
/// tip
Bạn có thể đọc thêm về điều này tại <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a>.
///
## Các Kiểu (Types) và Kiểm tra (Validation)
Các biến môi trường có thể chỉ xử lí **chuỗi ký tự**, vì chúng nằm bên ngoài đoạn mã Python và phải tương thích với các chương trình khác và phần còn lại của hệ thống (và thậm chí với các hệ điều hành khác, như Linux, Windows, macOS).
Điều này có nghĩa là **bất kỳ giá trị nào** được đọc trong Python từ một biến môi trường **sẽ là một `str`**, và bất kỳ hành động chuyển đổi sang kiểu dữ liệu khác hoặc hành động kiểm tra nào cũng phải được thực hiện trong đoạn mã.
Bạn sẽ học thêm về việc sử dụng biến môi trường để xử lí **các thiết lập ứng dụng** trong [Hướng dẫn nâng cao - Các thiết lập và biến môi trường](./advanced/settings.md){.internal-link target=_blank}.
## Biến môi trường `PATH`
Có một biến môi trường **đặc biệt** được gọi là **`PATH`** được sử dụng bởi các hệ điều hành (Linux, macOS, Windows) nhằm tìm các chương trình để thực thi.
Giá trị của biến môi trường `PATH` là một chuỗi dài được tạo bởi các thư mục được phân tách bởi dấu hai chấm `:` trên Linux và macOS, và bởi dấu chấm phẩy `;` trên Windows.
Ví dụ, biến môi trường `PATH` có thể có dạng như sau:
//// tab | Linux, macOS
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
Điều này có nghĩa là hệ thống sẽ tìm kiếm các chương trình trong các thư mục:
* `/usr/local/bin`
* `/usr/bin`
* `/bin`
* `/usr/sbin`
* `/sbin`
////
//// tab | Windows
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32
```
Điều này có nghĩa là hệ thống sẽ tìm kiếm các chương trình trong các thư mục:
* `C:\Program Files\Python312\Scripts`
* `C:\Program Files\Python312`
* `C:\Windows\System32`
////
Khi bạn gõ một **lệnh** trong terminal, hệ điều hành **tìm kiếm** chương trình trong **mỗi thư mục** được liệt kê trong biến môi trường `PATH`.
Ví dụ, khi bạn gõ `python` trong terminal, hệ điều hành tìm kiếm một chương trình được gọi `python` trong **thư mục đầu tiên** trong danh sách đó.
Nếu tìm thấy, nó sẽ **sử dụng** nó. Nếu không tìm thấy, nó sẽ tiếp tục tìm kiếm trong **các thư mục khác**.
### Cài đặt Python và cập nhật biến môi trường `PATH`
Khi bạn cài đặt Python, bạn có thể được hỏi nếu bạn muốn cập nhật biến môi trường `PATH`.
//// tab | Linux, macOS
Giả sử bạn cài đặt Python vào thư mục `/opt/custompython/bin`.
Nếu bạn chọn cập nhật biến môi trường `PATH`, thì cài đặt sẽ thêm `/opt/custompython/bin` vào biến môi trường `PATH`.
Nó có thể có dạng như sau:
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/custompython/bin
```
Như vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong `/opt/custompython/bin` (thư mục cuối) và sử dụng nó.
////
//// tab | Windows
Giả sử bạn cài đặt Python vào thư mục `C:\opt\custompython\bin`.
Nếu bạn chọn cập nhật biến môi trường `PATH`, thì cài đặt sẽ thêm `C:\opt\custompython\bin` vào biến môi trường `PATH`.
Nó có thể có dạng như sau:
```plaintext
C:\Program Files\Python312\Scripts;C:\Program Files\Python312;C:\Windows\System32;C:\opt\custompython\bin
```
Như vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong `C:\opt\custompython\bin` (thư mục cuối) và sử dụng nó.
////
Vậy, nếu bạn gõ:
<div class="termy">
```console
$ python
```
</div>
//// tab | Linux, macOS
Hệ thống sẽ **tìm kiếm** chương trình `python` trong `/opt/custompython/bin` và thực thi nó.
Nó tương đương với việc bạn gõ:
<div class="termy">
```console
$ /opt/custompython/bin/python
```
</div>
////
//// tab | Windows
Hệ thống sẽ **tìm kiếm** chương trình `python` trong `C:\opt\custompython\bin\python` và thực thi nó.
Nó tương đương với việc bạn gõ:
<div class="termy">
```console
$ C:\opt\custompython\bin\python
```
</div>
////
Thông tin này sẽ hữu ích khi bạn học về [Môi trường ảo](virtual-environments.md){.internal-link target=_blank}.
## Kết luận
Với những thông tin này, bạn có thể hiểu được **các biến môi trường là gì****cách sử dụng chúng trong Python**.
Bạn có thể đọc thêm về chúng tại <a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">Wikipedia cho Biến môi trường</a>.
Trong nhiều trường hợp, cách các biến môi trường trở nên hữu ích và có thể áp dụng không thực sự rõ ràng ngay từ đầu, nhưng chúng sẽ liên tục xuất hiện trong rất nhiều tình huống khi bạn phát triển ứng dụng, vì vậy việc hiểu biết về chúng là hữu ích.
Chẳng hạn, bạn sẽ cần những thông tin này khi bạn học về [Môi trường ảo](virtual-environments.md).

View File

@ -1,75 +0,0 @@
# FastAPI CLI
**FastAPI CLI** là một chương trình dòng lệnh có thể được sử dụng để phục vụ ứng dụng FastAPI của bạn, quản lý dự án FastAPI của bạn và nhiều hoạt động khác.
Khi bạn cài đặt FastAPI (vd với `pip install "fastapi[standard]"`), nó sẽ bao gồm một gói được gọi là `fastapi-cli`, gói này cung cấp lệnh `fastapi` trong terminal.
Để chạy ứng dụng FastAPI của bạn cho quá trình phát triển (development), bạn có thể sử dụng lệnh `fastapi dev`:
<div class="termy">
```console
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
Searching for package file structure from directories with
<font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with the
following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C to
quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
Chương trình dòng lệnh `fastapi`**FastAPI CLI**.
FastAPI CLI nhận đường dẫn đến chương trình Python của bạn (vd `main.py`) và tự động phát hiện đối tượng `FastAPI` (thường được gọi là `app`), xác định quá trình nhập đúng, và sau đó chạy nó (serve).
Đối với vận hành thực tế (production), bạn sẽ sử dụng `fastapi run` thay thế. 🚀
Ở bên trong, **FastAPI CLI** sử dụng <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>, một server ASGI có hiệu suất cao, sẵn sàng cho vận hành thực tế (production). 😎
## `fastapi dev`
Chạy `fastapi dev` sẽ khởi động quá trình phát triển.
Mặc định, **auto-reload** được bật, tự động tải lại server khi bạn thay đổi code của bạn. Điều này tốn nhiều tài nguyên và có thể kém ổn định hơn khi nó bị tắt. Bạn nên sử dụng nó cho quá trình phát triển. Nó cũng lắng nghe địa chỉ IP `127.0.0.1`, đó là địa chỉ IP của máy tính để tự giao tiếp với chính nó (`localhost`).
## `fastapi run`
Chạy `fastapi run` mặc định sẽ khởi động FastAPI cho quá trình vận hành thực tế.
Mặc định, **auto-reload** bị tắt. Nó cũng lắng nghe địa chỉ IP `0.0.0.0`, đó là tất cả các địa chỉ IP có sẵn, như vậy nó sẽ được truy cập công khai bởi bất kỳ ai có thể giao tiếp với máy tính. Đây là cách bạn thường chạy nó trong sản phẩm hoàn thiện, ví dụ trong một container.
Trong hầu hết các trường hợp, bạn sẽ (và nên) có một "proxy điểm cuối (termination proxy)" xử lý HTTPS cho bạn, điều này sẽ phụ thuộc vào cách bạn triển khai ứng dụng của bạn, nhà cung cấp có thể làm điều này cho bạn, hoặc bạn có thể cần thiết lập nó.
/// tip
Bạn có thể tìm hiểu thêm về FastAPI CLI trong [tài liệu triển khai](deployment/index.md){.internal-link target=_blank}.
///

View File

@ -1,200 +0,0 @@
# Tính năng
## Tính năng của FastAPI
**FastAPI** cho bạn những tính năng sau:
### Dựa trên những tiêu chuẩn mở
* <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a> cho việc tạo API, bao gồm những khai báo về <abbr title="cũng được biết đến như: endpoints, routes">đường dẫn</abbr> <abbr title="cũng được biết đến như các phương thức HTTP, như POST, GET, PUT, DELETE"> các toán tử</abbr>, tham số, body requests, cơ chế bảo mật, etc.
* Tự động tài liệu hóa data model theo <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> (OpenAPI bản thân nó được dựa trên JSON Schema).
* Được thiết kế xung quanh các tiêu chuẩn này sau khi nghiên cứu tỉ mỉ thay vì chỉ suy nghĩ đơn giản và sơ xài.
* Điều này cho phép tự động hóa **trình sinh code client** cho nhiều ngôn ngữ lập trình khác nhau.
### Tự động hóa tài liệu
Tài liệu tương tác API và web giao diện người dùng. Là một framework được dựa trên OpenAPI do đó có nhiều tùy chọn giao diện cho tài liệu API, 2 giao diện bên dưới là mặc định.
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>, với giao diện khám phá, gọi và kiểm thử API trực tiếp từ trình duyệt.
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Thay thế với tài liệu API với <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>.
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Chỉ cần phiên bản Python hiện đại
Tất cả được dựa trên khai báo kiểu dữ liệu chuẩn của **Python 3.8** (cảm ơn Pydantic). Bạn không cần học cú pháp mới, chỉ cần biết chuẩn Python hiện đại.
Nếu bạn cần 2 phút để làm mới lại cách sử dụng các kiểu dữ liệu mới của Python (thậm chí nếu bạn không sử dụng FastAPI), xem hướng dẫn ngắn: [Kiểu dữ liệu Python](python-types.md){.internal-link target=_blank}.
Bạn viết chuẩn Python với kiểu dữ liệu như sau:
```Python
from datetime import date
from pydantic import BaseModel
# Declare a variable as a str
# and get editor support inside the function
def main(user_id: str):
return user_id
# A Pydantic model
class User(BaseModel):
id: int
name: str
joined: date
```
Sau đó có thể được sử dụng:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
second_user_data = {
"id": 4,
"name": "Mary",
"joined": "2018-11-30",
}
my_second_user: User = User(**second_user_data)
```
/// info
`**second_user_data` nghĩa là:
Truyền các khóa và giá trị của dict `second_user_data` trực tiếp như các tham số kiểu key-value, tương đương với: `User(id=4, name="Mary", joined="2018-11-30")`
///
### Được hỗ trợ từ các trình soạn thảo
Toàn bộ framework được thiết kế để sử dụng dễ dàng và trực quan, toàn bộ quyết định đã được kiểm thử trên nhiều trình soạn thảo thậm chí trước khi bắt đầu quá trình phát triển, để chắc chắn trải nghiệm phát triển là tốt nhất.
Trong lần khảo sát cuối cùng dành cho các lập trình viên Python, đã rõ ràng <a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">rằng đa số các lập trình viên sử dụng tính năng "autocompletion"</a>.
Toàn bộ framework "FastAPI" phải đảm bảo rằng: autocompletion hoạt động ở mọi nơi. Bạn sẽ hiếm khi cần quay lại để đọc tài liệu.
Đây là các trình soạn thảo có thể giúp bạn:
* trong <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
* trong <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>:
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
Bạn sẽ có được auto-completion trong code, thậm chí trước đó là không thể. Như trong ví dụ, khóa `price` bên trong một JSON (đó có thể được lồng nhau) đến từ một request.
Không còn nhập sai tên khóa, quay đi quay lại giữa các tài liệu hoặc cuộn lên cuộn xuống để tìm xem cuối cùng bạn đã sử dụng `username` hay `user_name`.
### Ngắn gọn
FastAPI có các giá trị mặc định hợp lý cho mọi thứ, với các cấu hình tùy chọn ở mọi nơi. Tất cả các tham số có thể được tinh chỉnh để thực hiện những gì bạn cần và để định nghĩa API bạn cần.
Nhưng mặc định, tất cả **đều hoạt động**.
### Validation
* Validation cho đa số (hoặc tất cả?) **các kiểu dữ liệu** Python, bao gồm:
* JSON objects (`dict`).
* Mảng JSON (`list`) định nghĩa kiểu dữ liệu từng phần tử.
* Xâu (`str`), định nghĩa độ dài lớn nhất, nhỏ nhất.
* Số (`int`, `float`) với các giá trị lớn nhất, nhỏ nhất, etc.
* Validation cho nhiều kiểu dữ liệu bên ngoài như:
* URL.
* Email.
* UUID.
* ...và nhiều cái khác.
Tất cả validation được xử lí bằng những thiết lập tốt và mạnh mẽ của **Pydantic**.
### Bảo mật và xác thực
Bảo mật và xác thực đã tích hợp mà không làm tổn hại tới cơ sở dữ liệu hoặc data models.
Tất cả cơ chế bảo mật định nghĩa trong OpenAPI, bao gồm:
* HTTP Basic.
* **OAuth2** (với **JWT tokens**). Xem hướng dẫn [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* API keys in:
* Headers.
* Các tham số trong query string.
* Cookies, etc.
Cộng với tất cả các tính năng bảo mật từ Starlette (bao gồm **session cookies**).
Tất cả được xây dựng dưới dạng các công cụ và thành phần có thể tái sử dụng, dễ dàng tích hợp với hệ thống, kho lưu trữ dữ liệu, cơ sở dữ liệu quan hệ và NoSQL của bạn,...
### Dependency Injection
FastAPI bao gồm một hệ thống <abbr title='cũng biết đến như là "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></abbr> vô cùng dễ sử dụng nhưng vô cùng mạnh mẽ.
* Thậm chí, các dependency có thể có các dependency khác, tạo thành một phân cấp hoặc **"một đồ thị" của các dependency**.
* Tất cả **được xử lí tự động** bởi framework.
* Tất cả các dependency có thể yêu cầu dữ liệu từ request và **tăng cường các ràng buộc từ đường dẫn** và tự động tài liệu hóa.
* **Tự động hóa validation**, thậm chí với các tham số *đường dẫn* định nghĩa trong các dependency.
* Hỗ trợ hệ thống xác thực người dùng phức tạp, **các kết nối cơ sở dữ liệu**,...
* **Không làm tổn hại** cơ sở dữ liệu, frontends,... Nhưng dễ dàng tích hợp với tất cả chúng.
### Không giới hạn "plug-ins"
Hoặc theo một cách nào khác, không cần chúng, import và sử dụng code bạn cần.
Bất kì tích hợp nào được thiết kế để sử dụng đơn giản (với các dependency), đến nỗi bạn có thể tạo một "plug-in" cho ứng dụng của mình trong 2 dòng code bằng cách sử dụng cùng một cấu trúc và cú pháp được sử dụng cho *path operations* của bạn.
### Đã được kiểm thử
* 100% <abbr title=" Lượng code đã được kiểm thử tự động">test coverage</abbr>.
* 100% <abbr title="Python type annotations, với điều này trình soạn thảo của bạn và các công cụ bên ngoài có thể hỗ trợ bạn tốt hơn">type annotated</abbr> code base.
* Được sử dụng cho các ứng dụng sản phẩm.
## Tính năng của Starlette
`FastAPI` is thực sự là một sub-class của `Starlette`. Do đó, nếu bạn đã biết hoặc đã sử dụng Starlette, đa số các chức năng sẽ làm việc giống như vậy.
Với **FastAPI**, bạn có được tất cả những tính năng của **Starlette**:
* Hiệu năng thực sự ấn tượng. Nó là <a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">một trong nhưng framework Python nhanh nhất, khi so sánh với **NodeJS****Go**</a>.
* Hỗ trợ **WebSocket**.
* In-process background tasks.
* Startup and shutdown events.
* Client cho kiểm thử xây dựng trên HTTPX.
* **CORS**, GZip, Static Files, Streaming responses.
* Hỗ trợ **Session and Cookie**.
* 100% test coverage.
* 100% type annotated codebase.
## Tính năng của Pydantic
**FastAPI** tương thích đầy đủ với (và dựa trên) <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a>. Do đó, bất kì code Pydantic nào bạn thêm vào cũng sẽ hoạt động.
Bao gồm các thư viện bên ngoài cũng dựa trên Pydantic, như <abbr title="Object-Relational Mapper">ORM</abbr>s, <abbr title="Object-Document Mapper">ODM</abbr>s cho cơ sở dữ liệu.
Nó cũng có nghĩa là trong nhiều trường hợp, bạn có thể truyền cùng object bạn có từ một request **trực tiếp cho cơ sở dữ liệu**, vì mọi thứ được validate tự động.
Điều tương tự áp dụng cho các cách khác nhau, trong nhiều trường hợp, bạn có thể chỉ truyền object từ cơ sở dữ liêu **trực tiếp tới client**.
Với **FastAPI**, bạn có tất cả những tính năng của **Pydantic** (FastAPI dựa trên Pydantic cho tất cả những xử lí về dữ liệu):
* **Không gây rối não**:
* Không cần học ngôn ngữ mô tả cấu trúc mới.
* Nếu bạn biết kiểu dữ liệu Python, bạn biết cách sử dụng Pydantic.
* Sử dụng tốt với **<abbr title="Môi trường phát triển tích hợp, tương tự như một trình soạn thảo code">IDE</abbr>/<abbr title="Một chương trình kiểm tra code lỗi">linter</abbr>/não của bạn**:
* Bởi vì các cấu trúc dữ liệu của Pydantic chỉ là các instances của class bạn định nghĩa; auto-completion, linting, mypy và trực giác của bạn nên làm việc riêng biệt với những dữ liệu mà bạn đã validate.
* Validate **các cấu trúc phức tạp**:
* Sử dụng các models Pydantic phân tầng, `List``Dict` của Python `typing`,...
* Và các validators cho phép các cấu trúc dữ liệu phức tạp trở nên rõ ràng và dễ dàng để định nghĩa, kiểm tra và tài liệu hóa thành JSON Schema.
* Bạn có thể có các object **JSON lồng nhau** và tất cả chúng đã validate và annotated.
* **Có khả năng mở rộng**:
* Pydantic cho phép bạn tùy chỉnh kiểu dữ liệu bằng việc định nghĩa hoặc bạn có thể mở rộng validation với các decorator trong model.
* 100% test coverage.

View File

@ -1,475 +0,0 @@
# FastAPI
<style>
.md-content .md-typeset h1 { display: none; }
</style>
<p align="center">
<a href="https://fastapi.tiangolo.com"><img src="https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" alt="FastAPI"></a>
</p>
<p align="center">
<em>FastAPI framework, hiệu năng cao, dễ học, dễ code, sẵn sàng để tạo ra sản phẩm</em>
</p>
<p align="center">
<a href="https://github.com/fastapi/fastapi/actions?query=workflow%3ATest+event%3Apush+branch%3Amaster" target="_blank">
<img src="https://github.com/fastapi/fastapi/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Test">
</a>
<a href="https://coverage-badge.samuelcolvin.workers.dev/redirect/fastapi/fastapi" target="_blank">
<img src="https://coverage-badge.samuelcolvin.workers.dev/fastapi/fastapi.svg" alt="Coverage">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/v/fastapi?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/fastapi" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/fastapi.svg?color=%2334D058" alt="Supported Python versions">
</a>
</p>
---
**Tài liệu**: <a href="https://fastapi.tiangolo.com" target="_blank">https://fastapi.tiangolo.com</a>
**Mã nguồn**: <a href="https://github.com/fastapi/fastapi" target="_blank">https://github.com/fastapi/fastapi</a>
---
FastAPI là một web framework hiện đại, hiệu năng cao để xây dựng web APIs với Python dựa trên tiêu chuẩn Python type hints.
Những tính năng như:
* **Nhanh**: Hiệu năng rất cao khi so sánh với **NodeJS****Go** (cảm ơn Starlette và Pydantic). [Một trong những Python framework nhanh nhất](#hieu-nang).
* **Code nhanh**: Tăng tốc độ phát triển tính năng từ 200% tới 300%. *
* **Ít lỗi hơn**: Giảm khoảng 40% những lỗi phát sinh bởi con người (nhà phát triển). *
* **Trực giác tốt hơn**: Được các trình soạn thảo hỗ tuyệt vời. <abbr title="như auto-complete, autocompletion, IntelliSense">Completion</abbr> mọi nơi. Ít thời gian gỡ lỗi.
* **Dễ dàng**: Được thiết kế để dễ dàng học và sử dụng. Ít thời gian đọc tài liệu.
* **Ngắn**: Tối thiểu code bị trùng lặp. Nhiều tính năng được tích hợp khi định nghĩa tham số. Ít lỗi hơn.
* **Tăng tốc**: Có được sản phẩm cùng với tài liệu (được tự động tạo) có thể tương tác.
* **Được dựa trên các tiêu chuẩn**: Dựa trên (và hoàn toàn tương thích với) các tiêu chuẩn mở cho APIs : <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> (trước đó được biết đến là Swagger) và <a href="https://json-schema.org/" class="external-link" target="_blank">JSON Schema</a>.
<small>* ước tính được dựa trên những kiểm chứng trong nhóm phát triển nội bộ, xây dựng các ứng dụng sản phẩm.</small>
## Nhà tài trợ
<!-- sponsors -->
{% if sponsors %}
{% for sponsor in sponsors.gold -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor -%}
{%- for sponsor in sponsors.silver -%}
<a href="{{ sponsor.url }}" target="_blank" title="{{ sponsor.title }}"><img src="{{ sponsor.img }}" style="border-radius:15px"></a>
{% endfor %}
{% endif %}
<!-- /sponsors -->
<a href="https://fastapi.tiangolo.com/fastapi-people/#sponsors" class="external-link" target="_blank">Những nhà tài trợ khác</a>
## Ý kiến đánh giá
"_[...] Tôi đang sử dụng **FastAPI** vô cùng nhiều vào những ngày này. [...] Tôi thực sự đang lên kế hoạch sử dụng nó cho tất cả các nhóm **dịch vụ ML tại Microsoft**. Một vài trong số đó đang tích hợp vào sản phẩm lõi của **Window** và một vài sản phẩm cho **Office**._"
<div style="text-align: right; margin-right: 10%;">Kabir Khan - <strong>Microsoft</strong> <a href="https://github.com/fastapi/fastapi/pull/26" target="_blank"><small>(ref)</small></a></div>
---
"_Chúng tôi tích hợp thư viện **FastAPI** để sinh ra một **REST** server, nó có thể được truy vấn để thu được những **dự đoán**._ [bởi Ludwid] "
<div style="text-align: right; margin-right: 10%;">Piero Molino, Yaroslav Dudin, và Sai Sumanth Miryala - <strong>Uber</strong> <a href="https://eng.uber.com/ludwig-v0-2/" target="_blank"><small>(ref)</small></a></div>
---
"_**Netflix** vui mừng thông báo việc phát hành framework mã nguồn mở của chúng tôi cho *quản lí khủng hoảng* tập trung: **Dispatch**! [xây dựng với **FastAPI**]_"
<div style="text-align: right; margin-right: 10%;">Kevin Glisson, Marc Vilanova, Forest Monsen - <strong>Netflix</strong> <a href="https://netflixtechblog.com/introducing-dispatch-da4b8a2a8072" target="_blank"><small>(ref)</small></a></div>
---
"_Tôi vô cùng hào hứng về **FastAPI**. Nó rất thú vị_"
<div style="text-align: right; margin-right: 10%;">Brian Okken - <strong><a href="https://pythonbytes.fm/episodes/show/123/time-to-right-the-py-wrongs?time_in_sec=855" target="_blank">Python Bytes</a> podcast host</strong> <a href="https://x.com/brianokken/status/1112220079972728832" target="_blank"><small>(ref)</small></a></div>
---
"_Thành thật, những gì bạn đã xây dựng nhìn siêu chắc chắn và bóng bẩy. Theo nhiều cách, nó là những gì tôi đã muốn Hug trở thành - thật sự truyền cảm hứng để thấy ai đó xây dựng nó._"
<div style="text-align: right; margin-right: 10%;">Timothy Crosley - người tạo ra <strong><a href="https://github.com/hugapi/hug" target="_blank">Hug</a></strong> <a href="https://news.ycombinator.com/item?id=19455465" target="_blank"><small>(ref)</small></a></div>
---
"_Nếu bạn đang tìm kiếm một **framework hiện đại** để xây dựng một REST APIs, thử xem xét **FastAPI** [...] Nó nhanh, dễ dùng và dễ học [...]_"
"_Chúng tôi đã chuyển qua **FastAPI cho **APIs** của chúng tôi [...] Tôi nghĩ bạn sẽ thích nó [...]_"
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong><a href="https://explosion.ai" target="_blank">Explosion AI</a> founders - <a href="https://spacy.io" target="_blank">spaCy</a> creators</strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
<div style="text-align: right; margin-right: 10%;">Ines Montani - Matthew Honnibal - <strong>nhà sáng lập <a href="https://explosion.ai" target="_blank">Explosion AI</a> - người tạo ra <a href="https://spacy.io" target="_blank">spaCy</a></strong> <a href="https://x.com/_inesmontani/status/1144173225322143744" target="_blank"><small>(ref)</small></a> - <a href="https://x.com/honnibal/status/1144031421859655680" target="_blank"><small>(ref)</small></a></div>
---
"_Nếu ai đó đang tìm cách xây dựng sản phẩm API bằng Python, tôi sẽ đề xuất **FastAPI**. Nó **được thiết kế đẹp đẽ**, **sử dụng đơn giản****có khả năng mở rộng cao**, nó đã trở thành một **thành phần quan trọng** trong chiến lược phát triển API của chúng tôi và đang thúc đẩy nhiều dịch vụ và mảng tự động hóa như Kỹ sư TAC ảo của chúng tôi._"
<div style="text-align: right; margin-right: 10%;">Deon Pillsbury - <strong>Cisco</strong> <a href="https://www.linkedin.com/posts/deonpillsbury_cisco-cx-python-activity-6963242628536487936-trAp/" target="_blank"><small>(ref)</small></a></div>
---
## **Typer**, giao diện dòng lệnh của FastAPI
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Nếu bạn đang xây dựng một <abbr title="Giao diện dòng lệnh">CLI</abbr> - ứng dụng được sử dụng trong giao diện dòng lệnh, xem về <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a>.
**Typer** là một người anh em của FastAPI. Và nó được dự định trở thành **giao diện dòng lệnh cho FastAPI**. ⌨️ 🚀
## Yêu cầu
FastAPI đứng trên vai những người khổng lồ:
* <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> cho phần web.
* <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> cho phần data.
## Cài đặt
<div class="termy">
```console
$ pip install fastapi
---> 100%
```
</div>
Bạn cũng sẽ cần một ASGI server cho production như <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a> hoặc <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
<div class="termy">
```console
$ pip install "uvicorn[standard]"
---> 100%
```
</div>
## Ví dụ
### Khởi tạo
* Tạo một tệp tin `main.py` như sau:
```Python
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
<details markdown="1">
<summary>Hoặc sử dụng <code>async def</code>...</summary>
Nếu code của bạn sử dụng `async` / `await`, hãy sử dụng `async def`:
```Python hl_lines="9 14"
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
```
**Lưu ý**:
Nếu bạn không biết, xem phần _"In a hurry?"_ về <a href="https://fastapi.tiangolo.com/async/#in-a-hurry" target="_blank">`async` và `await` trong tài liệu này</a>.
</details>
### Chạy ứng dụng
Chạy server như sau:
<div class="termy">
```console
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
```
</div>
<details markdown="1">
<summary>Về lệnh <code>uvicorn main:app --reload</code>...</summary>
Lệnh `uvicorn main:app` tham chiếu tới những thành phần sau:
* `main`: tệp tin `main.py` (một Python "module").
* `app`: object được tạo trong tệp tin `main.py` tại dòng `app = FastAPI()`.
* `--reload`: chạy lại server sau khi code thay đổi. Chỉ sử dụng trong quá trình phát triển.
</details>
### Kiểm tra
Mở trình duyệt của bạn tại <a href="http://127.0.0.1:8000/items/5?q=somequery" class="external-link" target="_blank">http://127.0.0.1:8000/items/5?q=somequery</a>.
Bạn sẽ thấy một JSON response:
```JSON
{"item_id": 5, "q": "somequery"}
```
Bạn đã sẵn sàng để tạo một API như sau:
* Nhận HTTP request với _đường dẫn_ `/``/items/{item_id}`.
* Cả hai _đường dẫn_ sử dụng <em>toán tử</em> `GET` (cũng đươc biết đến là _phương thức_ HTTP).
* _Đường dẫn_ `/items/{item_id}` có một _tham số đường dẫn_ `item_id`, nó là một tham số kiểu `int`.
* _Đường dẫn_ `/items/{item_id}` có một _tham số query string_ `q`, nó là một tham số tùy chọn kiểu `str`.
### Tài liệu tương tác API
Truy cập <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Bạn sẽ thấy tài liệu tương tác API được tạo tự động (cung cấp bởi <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Tài liệu API thay thế
Và bây giờ, hãy truy cập tới <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Bạn sẽ thấy tài liệu được thay thế (cung cấp bởi <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
## Nâng cấp ví dụ
Bây giờ sửa tệp tin `main.py` để nhận body từ một request `PUT`.
Định nghĩa của body sử dụng kiểu dữ liệu chuẩn của Python, cảm ơn Pydantic.
```Python hl_lines="4 9-12 25-27"
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
```
Server nên tự động chạy lại (bởi vì bạn đã thêm `--reload` trong lệnh `uvicorn` ở trên).
### Nâng cấp tài liệu API
Bây giờ truy cập tới <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
* Tài liệu API sẽ được tự động cập nhật, bao gồm body mới:
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* Click vào nút "Try it out", nó cho phép bạn điền những tham số và tương tác trực tiếp với API:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-04-swagger-03.png)
* Sau khi click vào nút "Execute", giao diện người dùng sẽ giao tiếp với API của bạn bao gồm: gửi các tham số, lấy kết quả và hiển thị chúng trên màn hình:
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-05-swagger-04.png)
### Nâng cấp tài liệu API thay thế
Và bây giờ truy cập tới <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
* Tài liệu thay thế cũng sẽ phản ánh tham số và body mới:
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### Tóm lại
Bạn khai báo **một lần** kiểu dữ liệu của các tham số, body, etc là các tham số của hàm số.
Bạn định nghĩa bằng cách sử dụng các kiểu dữ liệu chuẩn của Python.
Bạn không phải học một cú pháp mới, các phương thức và class của một thư viện cụ thể nào.
Chỉ cần sử dụng các chuẩn của **Python**.
Ví dụ, với một tham số kiểu `int`:
```Python
item_id: int
```
hoặc với một model `Item` phức tạp hơn:
```Python
item: Item
```
...và với định nghĩa đơn giản đó, bạn có được:
* Sự hỗ trợ từ các trình soạn thảo, bao gồm:
* Completion.
* Kiểm tra kiểu dữ liệu.
* Kiểm tra kiểu dữ liệu:
* Tự động sinh lỗi rõ ràng khi dữ liệu không hợp lệ .
* Kiểm tra JSON lồng nhau .
* <abbr title="cũng được biết tới như: serialization, parsing, marshalling">Chuyển đổi</abbr> dữ liệu đầu vào: tới từ network sang dữ liệu kiểu Python. Đọc từ:
* JSON.
* Các tham số trong đường dẫn.
* Các tham số trong query string.
* Cookies.
* Headers.
* Forms.
* Files.
* <abbr title="cũng được biết tới như: serialization, parsing, marshalling">Chuyển đổi</abbr> dữ liệu đầu ra: chuyển đổi từ kiểu dữ liệu Python sang dữ liệu network (như JSON):
* Chuyển đổi kiểu dữ liệu Python (`str`, `int`, `float`, `bool`, `list`,...).
* `datetime` objects.
* `UUID` objects.
* Database models.
* ...và nhiều hơn thế.
* Tự động tạo tài liệu tương tác API, bao gồm 2 giao diện người dùng:
* Swagger UI.
* ReDoc.
---
Quay trở lại ví dụ trước, **FastAPI** sẽ thực hiện:
* Kiểm tra xem có một `item_id` trong đường dẫn với các request `GET``PUT` không?
* Kiểm tra xem `item_id` có phải là kiểu `int` trong các request `GET``PUT` không?
* Nếu không, client sẽ thấy một lỗi rõ ràng và hữu ích.
* Kiểm tra xem nếu có một tham số `q` trong query string (ví dụ như `http://127.0.0.1:8000/items/foo?q=somequery`) cho request `GET`.
* Tham số `q` được định nghĩa `= None`, nó là tùy chọn.
* Nếu không phải `None`, nó là bắt buộc (như body trong trường hợp của `PUT`).
* Với request `PUT` tới `/items/{item_id}`, đọc body như JSON:
* Kiểm tra xem nó có một thuộc tính bắt buộc kiểu `str``name` không?
* Kiểm tra xem nó có một thuộc tính bắt buộc kiểu `float``price` không?
* Kiểm tra xem nó có một thuộc tính tùy chọn là `is_offer` không? Nếu có, nó phải có kiểu `bool`.
* Tất cả những kiểm tra này cũng được áp dụng với các JSON lồng nhau.
* Chuyển đổi tự động các JSON object đến và JSON object đi.
* Tài liệu hóa mọi thứ với OpenAPI, tài liệu đó có thể được sử dụng bởi:
* Các hệ thống tài liệu có thể tương tác.
* Hệ thống sinh code tự động, cho nhiều ngôn ngữ lập trình.
* Cung cấp trực tiếp 2 giao diện web cho tài liệu tương tác
---
Chúng tôi chỉ trình bày những thứ cơ bản bên ngoài, nhưng bạn đã hiểu cách thức hoạt động của nó.
Thử thay đổi dòng này:
```Python
return {"item_name": item.name, "item_id": item_id}
```
...từ:
```Python
... "item_name": item.name ...
```
...sang:
```Python
... "item_price": item.price ...
```
...và thấy trình soạn thảo của bạn nhận biết kiểu dữ liệu và gợi ý hoàn thiện các thuộc tính.
![trình soạn thảo hỗ trợ](https://fastapi.tiangolo.com/img/vscode-completion.png)
Ví dụ hoàn chỉnh bao gồm nhiều tính năng hơn, xem <a href="https://fastapi.tiangolo.com/tutorial/">Tutorial - User Guide</a>.
**Cảnh báo tiết lỗ**: Tutorial - User Guide:
* Định nghĩa **tham số** từ các nguồn khác nhau như: **headers**, **cookies**, **form fields****files**.
* Cách thiết lập **các ràng buộc cho validation** như `maximum_length` hoặc `regex`.
* Một hệ thống **<abbr title="cũng được biết đến như components, resources, providers, services, injectables">Dependency Injection</abbr> vô cùng mạnh mẽ và dễ dàng sử dụng.
* Bảo mật và xác thực, hỗ trợ **OAuth2**(với **JWT tokens**) và **HTTP Basic**.
* Những kĩ thuật nâng cao hơn (nhưng tương đối dễ) để định nghĩa **JSON models lồng nhau** (cảm ơn Pydantic).
* Tích hợp **GraphQL** với <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> và các thư viện khác.
* Nhiều tính năng mở rộng (cảm ơn Starlette) như:
* **WebSockets**
* kiểm thử vô cùng dễ dàng dựa trên HTTPX và `pytest`
* **CORS**
* **Cookie Sessions**
* ...và nhiều hơn thế.
## Hiệu năng
Independent TechEmpower benchmarks cho thấy các ứng dụng **FastAPI** chạy dưới Uvicorn là <a href="https://www.techempower.com/benchmarks/#section=test&runid=7464e520-0dc2-473d-bd34-dbdfd7e85911&hw=ph&test=query&l=zijzen-7" class="external-link" target="_blank">một trong những Python framework nhanh nhất</a>, chỉ đứng sau Starlette và Uvicorn (được sử dụng bên trong FastAPI). (*)
Để hiểu rõ hơn, xem phần <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
## Các dependency tùy chọn
Sử dụng bởi Pydantic:
* <a href="https://github.com/JoshData/python-email-validator" target="_blank"><code>email-validator</code></a> - cho email validation.
Sử dụng Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Bắt buộc nếu bạn muốn sử dụng `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Bắt buộc nếu bạn muốn sử dụng cấu hình template engine mặc định.
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Bắt buộc nếu bạn muốn hỗ trợ <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, form với `request.form()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Bắt buộc để hỗ trợ `SessionMiddleware`.
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Bắt buộc để hỗ trợ `SchemaGenerator` cho Starlette (bạn có thể không cần nó trong FastAPI).
Sử dụng bởi FastAPI / Starlette:
* <a href="https://www.uvicorn.dev" target="_blank"><code>uvicorn</code></a> - Server để chạy ứng dụng của bạn.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Bắt buộc nếu bạn muốn sử dụng `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Bắt buộc nếu bạn muốn sử dụng `UJSONResponse`.
Bạn có thể cài đặt tất cả những dependency trên với `pip install "fastapi[all]"`.
## Giấy phép
Dự án này được cấp phép dưới những điều lệ của giấy phép MIT.

View File

@ -1,593 +0,0 @@
# Giới thiệu kiểu dữ liệu Python
Python hỗ trợ tùy chọn "type hints" (còn được gọi là "type annotations").
Những **"type hints"** hay chú thích là một cú pháp đặc biệt cho phép khai báo <abbr title="ví dụ: str, int, float, bool"> kiểu dữ liệu</abbr> của một biến.
Bằng việc khai báo kiểu dữ liệu cho các biến của bạn, các trình soạn thảo và các công cụ có thể hỗ trợ bạn tốt hơn.
Đây chỉ là một **hướng dẫn nhanh** về gợi ý kiểu dữ liệu trong Python. Nó chỉ bao gồm những điều cần thiết tối thiểu để sử dụng chúng với **FastAPI**... đó thực sự là rất ít.
**FastAPI** hoàn toàn được dựa trên những gợi ý kiểu dữ liệu, chúng mang đến nhiều ưu điểm và lợi ích.
Nhưng thậm chí nếu bạn không bao giờ sử dụng **FastAPI**, bạn sẽ được lợi từ việc học một ít về chúng.
/// note
Nếu bạn là một chuyên gia về Python, và bạn đã biết mọi thứ về gợi ý kiểu dữ liệu, bỏ qua và đi tới chương tiếp theo.
///
## Động lực
Hãy bắt đầu với một ví dụ đơn giản:
{* ../../docs_src/python_types/tutorial001.py *}
Kết quả khi gọi chương trình này:
```
John Doe
```
Hàm thực hiện như sau:
* Lấy một `first_name``last_name`.
* Chuyển đổi kí tự đầu tiên của mỗi biến sang kiểu chữ hoa với `title()`.
* <abbr title="Đặt chúng lại với nhau thành một. Với các nội dung lần lượt.">Nối</abbr> chúng lại với nhau bằng một kí tự trắng ở giữa.
{* ../../docs_src/python_types/tutorial001.py hl[2] *}
### Sửa đổi
Nó là một chương trình rất đơn giản.
Nhưng bây giờ hình dung rằng bạn đang viết nó từ đầu.
Tại một vài thời điểm, bạn sẽ bắt đầu định nghĩa hàm, bạn có các tham số...
Nhưng sau đó bạn phải gọi "phương thức chuyển đổi kí tự đầu tiên sang kiểu chữ hoa".
Có phải là `upper`? Có phải là `uppercase`? `first_uppercase`? `capitalize`?
Sau đó, bạn thử hỏi người bạn cũ của mình, autocompletion của trình soạn thảo.
Bạn gõ tham số đầu tiên của hàm, `first_name`, sau đó một dấu chấm (`.`) và sau đó ấn `Ctrl+Space` để kích hoạt bộ hoàn thành.
Nhưng đáng buồn, bạn không nhận được điều gì hữu ích cả:
<img src="/img/python-types/image01.png">
### Thêm kiểu dữ liệu
Hãy sửa một dòng từ phiên bản trước.
Chúng ta sẽ thay đổi chính xác đoạn này, tham số của hàm, từ:
```Python
first_name, last_name
```
sang:
```Python
first_name: str, last_name: str
```
Chính là nó.
Những thứ đó là "type hints":
{* ../../docs_src/python_types/tutorial002.py hl[1] *}
Đó không giống như khai báo những giá trị mặc định giống như:
```Python
first_name="john", last_name="doe"
```
Nó là một thứ khác.
Chúng ta sử dụng dấu hai chấm (`:`), không phải dấu bằng (`=`).
Và việc thêm gợi ý kiểu dữ liệu không làm thay đổi những gì xảy ra so với khi chưa thêm chúng.
But now, imagine you are again in the middle of creating that function, but with type hints.
Tại cùng một điểm, bạn thử kích hoạt autocomplete với `Ctrl+Space` và bạn thấy:
<img src="/img/python-types/image02.png">
Với cái đó, bạn có thể cuộn, nhìn thấy các lựa chọn, cho đến khi bạn tìm thấy một "tiếng chuông":
<img src="/img/python-types/image03.png">
## Động lực nhiều hơn
Kiểm tra hàm này, nó đã có gợi ý kiểu dữ liệu:
{* ../../docs_src/python_types/tutorial003.py hl[1] *}
Bởi vì trình soạn thảo biết kiểu dữ liệu của các biến, bạn không chỉ có được completion, bạn cũng được kiểm tra lỗi:
<img src="/img/python-types/image04.png">
Bây giờ bạn biết rằng bạn phải sửa nó, chuyển `age` sang một xâu với `str(age)`:
{* ../../docs_src/python_types/tutorial004.py hl[2] *}
## Khai báo các kiểu dữ liệu
Bạn mới chỉ nhìn thấy những nơi chủ yếu để đặt khai báo kiểu dữ liệu. Như là các tham số của hàm.
Đây cũng là nơi chủ yếu để bạn sử dụng chúng với **FastAPI**.
### Kiểu dữ liệu đơn giản
Bạn có thể khai báo tất cả các kiểu dữ liệu chuẩn của Python, không chỉ là `str`.
Bạn có thể sử dụng, ví dụ:
* `int`
* `float`
* `bool`
* `bytes`
{* ../../docs_src/python_types/tutorial005.py hl[1] *}
### Các kiểu dữ liệu tổng quát với tham số kiểu dữ liệu
Có một vài cấu trúc dữ liệu có thể chứa các giá trị khác nhau như `dict`, `list`, `set``tuple`. Và những giá trị nội tại cũng có thể có kiểu dữ liệu của chúng.
Những kiểu dữ liệu nội bộ này được gọi là những kiểu dữ liệu "**tổng quát**". Và có khả năng khai báo chúng, thậm chí với các kiểu dữ liệu nội bộ của chúng.
Để khai báo những kiểu dữ liệu và những kiểu dữ liệu nội bộ đó, bạn có thể sử dụng mô đun chuẩn của Python là `typing`. Nó có hỗ trợ những gợi ý kiểu dữ liệu này.
#### Những phiên bản mới hơn của Python
Cú pháp sử dụng `typing` **tương thích** với tất cả các phiên bản, từ Python 3.6 tới những phiên bản cuối cùng, bao gồm Python 3.9, Python 3.10,...
As Python advances, **những phiên bản mới** mang tới sự hỗ trợ được cải tiến cho những chú thích kiểu dữ liệu và trong nhiều trường hợp bạn thậm chí sẽ không cần import và sử dụng mô đun `typing` để khai báo chú thích kiểu dữ liệu.
Nếu bạn có thể chọn một phiên bản Python gần đây hơn cho dự án của bạn, ban sẽ có được những ưu điểm của những cải tiến đơn giản đó.
Trong tất cả các tài liệu tồn tại những ví dụ tương thích với mỗi phiên bản Python (khi có một sự khác nhau).
Cho ví dụ "**Python 3.6+**" có nghĩa là nó tương thích với Python 3.7 hoặc lớn hơn (bao gồm 3.7, 3.8, 3.9, 3.10,...). và "**Python 3.9+**" nghĩa là nó tương thích với Python 3.9 trở lên (bao gồm 3.10,...).
Nếu bạn có thể sử dụng **phiên bản cuối cùng của Python**, sử dụng những ví dụ cho phiên bản cuối, những cái đó sẽ có **cú pháp đơn giản và tốt nhât**, ví dụ, "**Python 3.10+**".
#### List
Ví dụ, hãy định nghĩa một biến là `list` các `str`.
//// tab | Python 3.9+
Khai báo biến với cùng dấu hai chấm (`:`).
Tương tự kiểu dữ liệu `list`.
Như danh sách là một kiểu dữ liệu chứa một vài kiểu dữ liệu có sẵn, bạn đặt chúng trong các dấu ngoặc vuông:
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006_py39.py!}
```
////
//// tab | Python 3.8+
Từ `typing`, import `List` (với chữ cái `L` viết hoa):
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial006.py!}
```
Khai báo biến với cùng dấu hai chấm (`:`).
Tương tự như kiểu dữ liệu, `List` bạn import từ `typing`.
Như danh sách là một kiểu dữ liệu chứa các kiểu dữ liệu có sẵn, bạn đặt chúng bên trong dấu ngoặc vuông:
```Python hl_lines="4"
{!> ../../docs_src/python_types/tutorial006.py!}
```
////
/// info
Các kiểu dữ liệu có sẵn bên trong dấu ngoặc vuông được gọi là "tham số kiểu dữ liệu".
Trong trường hợp này, `str` là tham số kiểu dữ liệu được truyền tới `List` (hoặc `list` trong Python 3.9 trở lên).
///
Có nghĩa là: "biến `items` là một `list`, và mỗi phần tử trong danh sách này là một `str`".
/// tip
Nếu bạn sử dụng Python 3.9 hoặc lớn hơn, bạn không phải import `List` từ `typing`, bạn có thể sử dụng `list` để thay thế.
///
Bằng cách này, trình soạn thảo của bạn có thể hỗ trợ trong khi xử lí các phần tử trong danh sách:
<img src="/img/python-types/image05.png">
Đa phần đều không thể đạt được nếu không có các kiểu dữ liệu.
Chú ý rằng, biến `item` là một trong các phần tử trong danh sách `items`.
Và do vậy, trình soạn thảo biết nó là một `str`, và cung cấp sự hỗ trợ cho nó.
#### Tuple and Set
Bạn sẽ làm điều tương tự để khai báo các `tuple` và các `set`:
//// tab | Python 3.9+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial007_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial007.py!}
```
////
Điều này có nghĩa là:
* Biến `items_t` là một `tuple` với 3 phần tử, một `int`, một `int` nữa, và một `str`.
* Biến `items_s` là một `set`, và mỗi phần tử của nó có kiểu `bytes`.
#### Dict
Để định nghĩa một `dict`, bạn truyền 2 tham số kiểu dữ liệu, phân cách bởi dấu phẩy.
Tham số kiểu dữ liệu đầu tiên dành cho khóa của `dict`.
Tham số kiểu dữ liệu thứ hai dành cho giá trị của `dict`.
//// tab | Python 3.9+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008_py39.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008.py!}
```
////
Điều này có nghĩa là:
* Biến `prices` là một `dict`:
* Khóa của `dict` này là kiểu `str` (đó là tên của mỗi vật phẩm).
* Giá trị của `dict` này là kiểu `float` (đó là giá của mỗi vật phẩm).
#### Union
Bạn có thể khai báo rằng một biến có thể là **một vài kiểu dữ liệu" bất kì, ví dụ, một `int` hoặc một `str`.
Trong Python 3.6 hoặc lớn hơn (bao gồm Python 3.10) bạn có thể sử dụng kiểu `Union` từ `typing` và đặt trong dấu ngoặc vuông những giá trị được chấp nhận.
In Python 3.10 there's also a **new syntax** where you can put the possible types separated by a <abbr title='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr>.
Trong Python 3.10 cũng có một **cú pháp mới** mà bạn có thể đặt những kiểu giá trị khả thi phân cách bởi một dấu <abbr title='cũng được gọi là "toán tử nhị phân"'>sổ dọc (`|`)</abbr>.
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b.py!}
```
////
Trong cả hai trường hợp có nghĩa là `item` có thể là một `int` hoặc `str`.
#### Khả năng `None`
Bạn có thể khai báo một giá trị có thể có một kiểu dữ liệu, giống như `str`, nhưng nó cũng có thể là `None`.
Trong Python 3.6 hoặc lớn hơn (bao gồm Python 3.10) bạn có thể khai báo nó bằng các import và sử dụng `Optional` từ mô đun `typing`.
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009.py!}
```
Sử dụng `Optional[str]` thay cho `str` sẽ cho phép trình soạn thảo giúp bạn phát hiện các lỗi mà bạn có thể gặp như một giá trị luôn là một `str`, trong khi thực tế nó rất có thể là `None`.
`Optional[Something]` là một cách viết ngắn gọn của `Union[Something, None]`, chúng là tương đương nhau.
Điều này cũng có nghĩa là trong Python 3.10, bạn có thể sử dụng `Something | None`:
//// tab | Python 3.10+
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial009_py310.py!}
```
////
//// tab | Python 3.8+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009.py!}
```
////
//// tab | Python 3.8+ alternative
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009b.py!}
```
////
#### Sử dụng `Union` hay `Optional`
If you are using a Python version below 3.10, here's a tip from my very **subjective** point of view:
Nếu bạn đang sử dụng phiên bản Python dưới 3.10, đây là một mẹo từ ý kiến rất "chủ quan" của tôi:
* 🚨 Tránh sử dụng `Optional[SomeType]`
* Thay vào đó ✨ **sử dụng `Union[SomeType, None]`** ✨.
Cả hai là tương đương và bên dưới chúng giống nhau, nhưng tôi sẽ đễ xuất `Union` thay cho `Optional` vì từ "**tùy chọn**" có vẻ ngầm định giá trị là tùy chọn, và nó thực sự có nghĩa rằng "nó có thể là `None`", do đó nó không phải là tùy chọn và nó vẫn được yêu cầu.
Tôi nghĩ `Union[SomeType, None]` là rõ ràng hơn về ý nghĩa của nó.
Nó chỉ là về các từ và tên. Nhưng những từ đó có thể ảnh hưởng cách bạn và những đồng đội của bạn suy nghĩ về code.
Cho một ví dụ, hãy để ý hàm này:
{* ../../docs_src/python_types/tutorial009c.py hl[1,4] *}
Tham số `name` được định nghĩa là `Optional[str]`, nhưng nó **không phải là tùy chọn**, bạn không thể gọi hàm mà không có tham số:
```Python
say_hi() # Oh, no, this throws an error! 😱
```
Tham số `name` **vẫn được yêu cầu** (không phải là *tùy chọn*) vì nó không có giá trị mặc định. Trong khi đó, `name` chấp nhận `None` như là giá trị:
```Python
say_hi(name=None) # This works, None is valid 🎉
```
Tin tốt là, khi bạn sử dụng Python 3.10, bạn sẽ không phải lo lắng về điều đó, bạn sẽ có thể sử dụng `|` để định nghĩa hợp của các kiểu dữ liệu một cách đơn giản:
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
Và sau đó, bạn sẽ không phải lo rằng những cái tên như `Optional``Union`. 😎
#### Những kiểu dữ liệu tổng quát
Những kiểu dữ liệu này lấy tham số kiểu dữ liệu trong dấu ngoặc vuông được gọi là **Kiểu dữ liệu tổng quát**, cho ví dụ:
//// tab | Python 3.10+
Bạn có thể sử dụng các kiểu dữ liệu có sẵn như là kiểu dữ liệu tổng quát (với ngoặc vuông và kiểu dữ liệu bên trong):
* `list`
* `tuple`
* `set`
* `dict`
Và tương tự với Python 3.6, từ mô đun `typing`:
* `Union`
* `Optional` (tương tự như Python 3.6)
* ...và các kiểu dữ liệu khác.
Trong Python 3.10, thay vì sử dụng `Union``Optional`, bạn có thể sử dụng <abbr title='cũng gọi là "toán tử nhị phân", nhưng ý nghĩa không liên quan ở đây'>sổ dọc ('|')</abbr> để khai báo hợp của các kiểu dữ liệu, điều đó tốt hơn và đơn giản hơn nhiều.
////
//// tab | Python 3.9+
Bạn có thể sử dụng các kiểu dữ liệu có sẵn tương tự như (với ngoặc vuông và kiểu dữ liệu bên trong):
* `list`
* `tuple`
* `set`
* `dict`
Và tương tự với Python 3.6, từ mô đun `typing`:
* `Union`
* `Optional`
* ...and others.
////
//// tab | Python 3.8+
* `List`
* `Tuple`
* `Set`
* `Dict`
* `Union`
* `Optional`
* ...và các kiểu khác.
////
### Lớp như kiểu dữ liệu
Bạn cũng có thể khai báo một lớp như là kiểu dữ liệu của một biến.
Hãy nói rằng bạn muốn có một lớp `Person` với một tên:
{* ../../docs_src/python_types/tutorial010.py hl[1:3] *}
Sau đó bạn có thể khai báo một biến có kiểu là `Person`:
{* ../../docs_src/python_types/tutorial010.py hl[6] *}
Và lại một lần nữa, bạn có được tất cả sự hỗ trợ từ trình soạn thảo:
<img src="/img/python-types/image06.png">
Lưu ý rằng, điều này có nghĩa rằng "`one_person`" là một **thực thể** của lớp `Person`.
Nó không có nghĩa "`one_person`" là một **lớp** gọi là `Person`.
## Pydantic models
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> là một thư viện Python để validate dữ liệu hiệu năng cao.
Bạn có thể khai báo "hình dạng" của dữa liệu như là các lớp với các thuộc tính.
Và mỗi thuộc tính có một kiểu dữ liệu.
Sau đó bạn tạo một thực thể của lớp đó với một vài giá trị và nó sẽ validate các giá trị, chuyển đổi chúng sang kiểu dữ liệu phù hợp (nếu đó là trường hợp) và cho bạn một object với toàn bộ dữ liệu.
Và bạn nhận được tất cả sự hỗ trợ của trình soạn thảo với object kết quả đó.
Một ví dụ từ tài liệu chính thức của Pydantic:
//// tab | Python 3.10+
```Python
{!> ../../docs_src/python_types/tutorial011_py310.py!}
```
////
//// tab | Python 3.9+
```Python
{!> ../../docs_src/python_types/tutorial011_py39.py!}
```
////
//// tab | Python 3.8+
```Python
{!> ../../docs_src/python_types/tutorial011.py!}
```
////
/// info
Để học nhiều hơn về <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic, tham khảo tài liệu của nó</a>.
///
**FastAPI** được dựa hoàn toàn trên Pydantic.
Bạn sẽ thấy nhiều ví dụ thực tế hơn trong [Hướng dẫn sử dụng](tutorial/index.md){.internal-link target=_blank}.
/// tip
Pydantic có một hành vi đặc biệt khi bạn sử dụng `Optional` hoặc `Union[Something, None]` mà không có giá trị mặc dịnh, bạn có thể đọc nhiều hơn về nó trong tài liệu của Pydantic về <a href="https://docs.pydantic.dev/latest/concepts/models/#required-optional-fields" class="external-link" target="_blank">Required Optional fields</a>.
///
## Type Hints với Metadata Annotations
Python cũng có một tính năng cho phép đặt **metadata bổ sung** trong những gợi ý kiểu dữ liệu này bằng cách sử dụng `Annotated`.
//// tab | Python 3.9+
Trong Python 3.9, `Annotated` là một phần của thư viện chuẩn, do đó bạn có thể import nó từ `typing`.
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial013_py39.py!}
```
////
//// tab | Python 3.8+
Ở phiên bản dưới Python 3.9, bạn import `Annotated` từ `typing_extensions`.
Nó đã được cài đặt sẵng cùng với **FastAPI**.
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial013.py!}
```
////
Python bản thân nó không làm bất kì điều gì với `Annotated`. Với các trình soạn thảo và các công cụ khác, kiểu dữ liệu vẫn là `str`.
Nhưng bạn có thể sử dụng `Annotated` để cung cấp cho **FastAPI** metadata bổ sung về cách mà bạn muốn ứng dụng của bạn xử lí.
Điều quan trọng cần nhớ là ***tham số kiểu dữ liệu* đầu tiên** bạn truyền tới `Annotated`**kiểu giá trị thực sự**. Phần còn lại chỉ là metadata cho các công cụ khác.
Bây giờ, bạn chỉ cần biết rằng `Annotated` tồn tại, và nó là tiêu chuẩn của Python. 😎
Sau đó, bạn sẽ thấy sự **mạnh mẽ** mà nó có thể làm.
/// tip
Thực tế, cái này là **tiêu chuẩn của Python**, nghĩa là bạn vẫn sẽ có được **trải nghiệm phát triển tốt nhất có thể** với trình soạn thảo của bạn, với các công cụ bạn sử dụng để phân tích và tái cấu trúc code của bạn, etc. ✨
Và code của bạn sẽ tương thích với nhiều công cụ và thư viện khác của Python. 🚀
///
## Các gợi ý kiểu dữ liệu trong **FastAPI**
**FastAPI** lấy các ưu điểm của các gợi ý kiểu dữ liệu để thực hiện một số thứ.
Với **FastAPI**, bạn khai báo các tham số với gợi ý kiểu và bạn có được:
* **Sự hỗ trợ từ các trình soạn thảo**.
* **Kiểm tra kiểu dữ liệu (type checking)**.
...và **FastAPI** sử dụng các khia báo để:
* **Định nghĩa các yêu cầu**: từ tham số đường dẫn của request, tham số query, headers, bodies, các phụ thuộc (dependencies),...
* **Chuyển dổi dữ liệu*: từ request sang kiểu dữ liệu được yêu cầu.
* **Kiểm tra tính đúng đắn của dữ liệu**: tới từ mỗi request:
* Sinh **lỗi tự động** để trả về máy khác khi dữ liệu không hợp lệ.
* **Tài liệu hóa** API sử dụng OpenAPI:
* cái mà sau được được sử dụng bởi tài liệu tương tác người dùng.
Điều này có thể nghe trừu tượng. Đừng lo lắng. Bạn sẽ thấy tất cả chúng trong [Hướng dẫn sử dụng](tutorial/index.md){.internal-link target=_blank}.
Điều quan trọng là bằng việc sử dụng các kiểu dữ liệu chuẩn của Python (thay vì thêm các lớp, decorators,...), **FastAPI** sẽ thực hiện nhiều công việc cho bạn.
/// info
Nếu bạn đã đi qua toàn bộ các hướng dẫn và quay trở lại để tìm hiểu nhiều hơn về các kiểu dữ liệu, một tài nguyên tốt như <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">"cheat sheet" từ `mypy`</a>.
///

View File

@ -1,335 +0,0 @@
# Những bước đầu tiên
Tệp tin FastAPI đơn giản nhất có thể trông như này:
{* ../../docs_src/first_steps/tutorial001.py *}
Sao chép sang một tệp tin `main.py`.
Chạy live server:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
/// note
Câu lệnh `uvicorn main:app` được giải thích như sau:
* `main`: tệp tin `main.py` (một Python "mô đun").
* `app`: một object được tạo ra bên trong `main.py` với dòng `app = FastAPI()`.
* `--reload`: làm server khởi động lại sau mỗi lần thay đổi. Chỉ sử dụng trong môi trường phát triển.
///
Trong output, có một dòng giống như:
```hl_lines="4"
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Dòng đó cho thấy URL, nơi mà app của bạn đang được chạy, trong máy local của bạn.
### Kiểm tra
Mở trình duyệt của bạn tại <a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>.
Bạn sẽ thấy một JSON response như:
```JSON
{"message": "Hello World"}
```
### Tài liệu tương tác API
Bây giờ tới <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
Bạn sẽ thấy một tài liệu tương tác API (cung cấp bởi <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank">Swagger UI</a>):
![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png)
### Phiên bản thay thế của tài liệu API
Và bây giờ tới <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>.
Bạn sẽ thấy một bản thay thế của tài liệu (cung cấp bởi <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank">ReDoc</a>):
![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png)
### OpenAPI
**FastAPI** sinh một "schema" với tất cả API của bạn sử dụng tiêu chuẩn **OpenAPI** cho định nghĩa các API.
#### "Schema"
Một "schema" là một định nghĩa hoặc mô tả thứ gì đó. Không phải code triển khai của nó, nhưng chỉ là một bản mô tả trừu tượng.
#### API "schema"
Trong trường hợp này, <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a> là một bản mô tả bắt buộc cơ chế định nghĩa API của bạn.
Định nghĩa cấu trúc này bao gồm những đường dẫn API của bạn, các tham số có thể có,...
#### "Cấu trúc" dữ liệu
Thuật ngữ "cấu trúc" (schema) cũng có thể được coi như là hình dạng của dữ liệu, tương tự như một JSON content.
Trong trường hợp đó, nó có nghĩa là các thuộc tính JSON và các kiểu dữ liệu họ có,...
#### OpenAPI và JSON Schema
OpenAPI định nghĩa một cấu trúc API cho API của bạn. Và cấu trúc đó bao gồm các dịnh nghĩa (or "schema") về dữ liệu được gửi đi và nhận về bởi API của bạn, sử dụng **JSON Schema**, một tiêu chuẩn cho cấu trúc dữ liệu JSON.
#### Kiểm tra `openapi.json`
Nếu bạn tò mò về việc cấu trúc OpenAPI nhìn như thế nào thì FastAPI tự động sinh một JSON (schema) với các mô tả cho tất cả API của bạn.
Bạn có thể thấy nó trực tiếp tại: <a href="http://127.0.0.1:8000/openapi.json" class="external-link" target="_blank">http://127.0.0.1:8000/openapi.json</a>.
Nó sẽ cho thấy một JSON bắt đầu giống như:
```JSON
{
"openapi": "3.1.0",
"info": {
"title": "FastAPI",
"version": "0.1.0"
},
"paths": {
"/items/": {
"get": {
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
...
```
#### OpenAPI dùng để làm gì?
Cấu trúc OpenAPI là sức mạnh của tài liệu tương tác.
Và có hàng tá các bản thay thế, tất cả đều dựa trên OpenAPI. Bạn có thể dễ dàng thêm bất kì bản thay thế bào cho ứng dụng của bạn được xây dựng với **FastAPI**.
Bạn cũng có thể sử dụng nó để sinh code tự động, với các client giao viết qua API của bạn. Ví dụ, frontend, mobile hoặc các ứng dụng IoT.
## Tóm lại, từng bước một
### Bước 1: import `FastAPI`
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
`FastAPI` là một Python class cung cấp tất cả chức năng cho API của bạn.
/// note | Chi tiết kĩ thuật
`FastAPI` là một class kế thừa trực tiếp `Starlette`.
Bạn cũng có thể sử dụng tất cả <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> chức năng với `FastAPI`.
///
### Bước 2: Tạo một `FastAPI` "instance"
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
Biến `app` này là một "instance" của class `FastAPI`.
Đây sẽ là điểm cốt lõi để tạo ra tất cả API của bạn.
`app` này chính là điều được nhắc tới bởi `uvicorn` trong câu lệnh:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Nếu bạn tạo ứng dụng của bạn giống như:
{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
Và đặt nó trong một tệp tin `main.py`, sau đó bạn sẽ gọi `uvicorn` giống như:
<div class="termy">
```console
$ uvicorn main:my_awesome_api --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### Bước 3: tạo một *đường dẫn toán tử*
#### Đường dẫn
"Đường dẫn" ở đây được nhắc tới là phần cuối cùng của URL bắt đầu từ `/`.
Do đó, trong một URL nhìn giống như:
```
https://example.com/items/foo
```
...đường dẫn sẽ là:
```
/items/foo
```
/// info
Một đường dẫn cũng là một cách gọi chung cho một "endpoint" hoặc một "route".
///
Trong khi xây dựng một API, "đường dẫn" là các chính để phân tách "mối quan hệ" và "tài nguyên".
#### Toán tử (Operation)
"Toán tử" ở đây được nhắc tới là một trong các "phương thức" HTTP.
Một trong những:
* `POST`
* `GET`
* `PUT`
* `DELETE`
...và một trong những cái còn lại:
* `OPTIONS`
* `HEAD`
* `PATCH`
* `TRACE`
Trong giao thức HTTP, bạn có thể giao tiếp trong mỗi đường dẫn sử dụng một (hoặc nhiều) trong các "phương thức này".
---
Khi xây dựng các API, bạn thường sử dụng cụ thể các phương thức HTTP này để thực hiện một hành động cụ thể.
Thông thường, bạn sử dụng
* `POST`: để tạo dữ liệu.
* `GET`: để đọc dữ liệu.
* `PUT`: để cập nhật dữ liệu.
* `DELETE`: để xóa dữ liệu.
Do đó, trong OpenAPI, mỗi phương thức HTTP được gọi là một "toán tử (operation)".
Chúng ta cũng sẽ gọi chúng là "**các toán tử**".
#### Định nghĩa moojt *decorator cho đường dẫn toán tử*
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
`@app.get("/")` nói **FastAPI** rằng hàm bên dưới có trách nhiệm xử lí request tới:
* đường dẫn `/`
* sử dụng một <abbr title="an HTTP GET method">toán tử<code>get</code></abbr>
/// info | Thông tin về "`@decorator`"
Cú pháp `@something` trong Python được gọi là một "decorator".
Bạn đặt nó trên một hàm. Giống như một chiếc mũ xinh xắn (Tôi ddonas đó là lí do mà thuật ngữ này ra đời).
Một "decorator" lấy một hàm bên dưới và thực hiện một vài thứ với nó.
Trong trường hợp của chúng ta, decorator này nói **FastAPI** rằng hàm bên dưới ứng với **đường dẫn** `/` và một **toán tử** `get`.
Nó là một "**decorator đường dẫn toán tử**".
///
Bạn cũng có thể sử dụng với các toán tử khác:
* `@app.post()`
* `@app.put()`
* `@app.delete()`
Và nhiều hơn với các toán tử còn lại:
* `@app.options()`
* `@app.head()`
* `@app.patch()`
* `@app.trace()`
/// tip
Bạn thoải mái sử dụng mỗi toán tử (phương thức HTTP) như bạn mơ ước.
**FastAPI** không bắt buộc bất kì ý nghĩa cụ thể nào.
Thông tin ở đây được biểu thị như là một chỉ dẫn, không phải là một yêu cầu bắt buộc.
Ví dụ, khi sử dụng GraphQL bạn thông thường thực hiện tất cả các hành động chỉ bằng việc sử dụng các toán tử `POST`.
///
### Step 4: Định nghĩa **hàm cho đường dẫn toán tử**
Đây là "**hàm cho đường dẫn toán tử**":
* **đường dẫn**: là `/`.
* **toán tử**: là `get`.
* **hàm**: là hàm bên dưới "decorator" (bên dưới `@app.get("/")`).
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
Đây là một hàm Python.
Nó sẽ được gọi bởi **FastAPI** bất cứ khi nào nó nhận một request tới URL "`/`" sử dụng một toán tử `GET`.
Trong trường hợp này, nó là một hàm `async`.
---
Bạn cũng có thể định nghĩa nó như là một hàm thông thường thay cho `async def`:
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
/// note
Nếu bạn không biết sự khác nhau, kiểm tra [Async: *"Trong khi vội vàng?"*](../async.md#in-a-hurry){.internal-link target=_blank}.
///
### Bước 5: Nội dung trả về
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
Bạn có thể trả về một `dict`, `list`, một trong những giá trị đơn như `str`, `int`,...
Bạn cũng có thể trả về Pydantic model (bạn sẽ thấy nhiều hơn về nó sau).
Có nhiều object và model khác nhau sẽ được tự động chuyển đổi sang JSON (bao gồm cả ORM,...). Thử sử dụng loại ưa thích của bạn, nó có khả năng cao đã được hỗ trợ.
## Tóm lại
* Import `FastAPI`.
* Tạo một `app` instance.
* Viết một **decorator cho đường dẫn toán tử** (giống như `@app.get("/")`).
* Viết một **hàm cho đường dẫn toán tử** (giống như `def root(): ...` ở trên).
* Chạy server trong môi trường phát triển (giống như `uvicorn main:app --reload`).

View File

@ -1,83 +0,0 @@
# Hướng dẫn sử dụng
Hướng dẫn này cho bạn thấy từng bước cách sử dụng **FastAPI** đa số các tính năng của nó.
Mỗi phần được xây dựng từ những phần trước đó, nhưng nó được cấu trúc thành các chủ đề riêng biệt, do đó bạn có thể xem trực tiếp từng phần cụ thể bất kì để giải quyết những API cụ thể mà bạn cần.
Nó cũng được xây dựng để làm việc như một tham chiếu trong tương lai.
Do đó bạn có thể quay lại và tìm chính xác những gì bạn cần.
## Chạy mã
Tất cả các code block có thể được sao chép và sử dụng trực tiếp (chúng thực chất là các tệp tin Python đã được kiểm thử).
Để chạy bất kì ví dụ nào, sao chép code tới tệp tin `main.py`, và bắt đầu `uvicorn` với:
<div class="termy">
```console
$ uvicorn main:app --reload
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<span style="color: green;">INFO</span>: Started reloader process [28720]
<span style="color: green;">INFO</span>: Started server process [28722]
<span style="color: green;">INFO</span>: Waiting for application startup.
<span style="color: green;">INFO</span>: Application startup complete.
```
</div>
**Khuyến khích** bạn viết hoặc sao chép code, sửa và chạy nó ở local.
Sử dụng nó trong trình soạn thảo của bạn thực sự cho bạn thấy những lợi ích của FastAPI, thấy được cách bạn viết code ít hơn, tất cả đều được type check, autocompletion,...
---
## Cài đặt FastAPI
Bước đầu tiên là cài đặt FastAPI.
Với hướng dẫn này, bạn có thể muốn cài đặt nó với tất cả các phụ thuộc và tính năng tùy chọn:
<div class="termy">
```console
$ pip install "fastapi[all]"
---> 100%
```
</div>
...dó cũng bao gồm `uvicorn`, bạn có thể sử dụng như một server để chạy code của bạn.
/// note
Bạn cũng có thể cài đặt nó từng phần.
Đây là những gì bạn có thể sẽ làm một lần duy nhất bạn muốn triển khai ứng dụng của bạn lên production:
```
pip install fastapi
```
Cũng cài đặt `uvicorn` để làm việc như một server:
```
pip install "uvicorn[standard]"
```
Và tương tự với từng phụ thuộc tùy chọn mà bạn muốn sử dụng.
///
## Hướng dẫn nâng cao
Cũng có một **Hướng dẫn nâng cao** mà bạn có thể đọc nó sau **Hướng dẫn sử dụng**.
**Hướng dẫn sử dụng nâng cao**, xây dựng dựa trên cái này, sử dụng các khái niệm tương tự, và dạy bạn những tính năng mở rộng.
Nhưng bạn nên đọc **Hướng dẫn sử dụng** đầu tiên (những gì bạn đang đọc).
Nó được thiết kế do đó bạn có thể xây dựng một ứng dụng hoàn chỉnh chỉ với **Hướng dẫn sử dụng**, và sau đó mở rộng nó theo các cách khác nhau, phụ thuộc vào những gì bạn cần, sử dụng một vài ý tưởng bổ sung từ **Hướng dẫn sử dụng nâng cao**.

View File

@ -1,40 +0,0 @@
# Tệp tĩnh (Static Files)
Bạn có thể triển khai tệp tĩnh tự động từ một thư mục bằng cách sử dụng StaticFiles.
## Sử dụng `Tệp tĩnh`
- Nhập `StaticFiles`.
- "Mount" a `StaticFiles()` instance in a specific path.
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
/// note | Chi tiết kỹ thuật
Bạn cũng có thể sử dụng `from starlette.staticfiles import StaticFiles`.
**FastAPI** cung cấp cùng `starlette.staticfiles` như `fastapi.staticfiles` giúp đơn giản hóa việc sử dụng, nhưng nó thực sự đến từ Starlette.
///
### "Mounting" là gì
"Mounting" có nghĩa là thêm một ứng dụng "độc lập" hoàn chỉnh vào một đường dẫn cụ thể, sau đó ứng dụng đó sẽ chịu trách nhiệm xử lý tất cả các đường dẫn con.
Điều này khác với việc sử dụng `APIRouter` vì một ứng dụng được gắn kết là hoàn toàn độc lập. OpenAPI và tài liệu từ ứng dụng chính của bạn sẽ không bao gồm bất kỳ thứ gì từ ứng dụng được gắn kết, v.v.
Bạn có thể đọc thêm về điều này trong [Hướng dẫn Người dùng Nâng cao](../advanced/index.md){.internal-link target=\_blank}.
## Chi tiết
Đường dẫn đầu tiên `"/static"` là đường dẫn con mà "ứng dụng con" này sẽ được "gắn" vào. Vì vậy, bất kỳ đường dẫn nào bắt đầu bằng `"/static"` sẽ được xử lý bởi nó.
Đường dẫn `directory="static"` là tên của thư mục chứa tệp tĩnh của bạn.
Tham số `name="static"` đặt tên cho nó để có thể được sử dụng bên trong **FastAPI**.
Tất cả các tham số này có thể khác với `static`, điều chỉnh chúng với phù hợp với ứng dụng của bạn.
## Thông tin thêm
Để biết thêm chi tiết và tùy chọn, hãy xem <a href="https://www.starlette.dev/staticfiles/" class="external-link" target="_blank">Starlette's docs about Static Files</a>.

View File

@ -1,842 +0,0 @@
# Môi trường ảo (Virtual Environments)
Khi bạn làm việc trong các dự án Python, bạn có thể sử dụng một **môi trường ảo** (hoặc một cơ chế tương tự) để cách ly các gói bạn cài đặt cho mỗi dự án.
/// info
Nếu bạn đã biết về các môi trường ảo, cách tạo chúng và sử dụng chúng, bạn có thể bỏ qua phần này. 🤓
///
/// tip
Một **môi trường ảo** khác với một **biến môi trường (environment variable)**.
Một **biến môi trường** là một biến trong hệ thống có thể được sử dụng bởi các chương trình.
Một **môi trường ảo** là một thư mục với một số tệp trong đó.
///
/// info
Trang này sẽ hướng dẫn bạn cách sử dụng các **môi trường ảo** và cách chúng hoạt động.
Nếu bạn đã sẵn sàng sử dụng một **công cụ có thể quản lý tất cả mọi thứ** cho bạn (bao gồm cả việc cài đặt Python), hãy thử <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>.
///
## Tạo một Dự án
Đầu tiên, tạo một thư mục cho dự án của bạn.
Cách tôi thường làm là tạo một thư mục có tên `code` trong thư mục `home/user`.
Và trong thư mục đó, tôi tạo một thư mục cho mỗi dự án.
<div class="termy">
```console
// Đi đến thư mục home
$ cd
// Tạo một thư mục cho tất cả các dự án của bạn
$ mkdir code
// Vào thư mục code
$ cd code
// Tạo một thư mục cho dự án này
$ mkdir awesome-project
// Vào thư mục dự án
$ cd awesome-project
```
</div>
## Tạo một Môi trường ảo
Khi bạn bắt đầu làm việc với một dự án Python **trong lần đầu**, hãy tạo một môi trường ảo **<abbr title="có nhiều cách thực hiện khác nhau, đây là một hướng dẫn đơn giản">trong thư mục dự án của bạn</abbr>**.
/// tip
Bạn cần làm điều này **một lần cho mỗi dự án**, không phải mỗi khi bạn làm việc.
///
//// tab | `venv`
Để tạo một môi trường ảo, bạn có thể sử dụng module `venv` có sẵn của Python.
<div class="termy">
```console
$ python -m venv .venv
```
</div>
/// details | Cách các lệnh hoạt động
* `python`: sử dụng chương trình `python`
* `-m`: gọi một module như một script, chúng ta sẽ nói về module đó sau
* `venv`: sử dụng module `venv` được cài đặt sẵn của Python
* `.venv`: tạo môi trường ảo trong thư mục mới `.venv`
///
////
//// tab | `uv`
Nếu bạn có <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a> được cài đặt, bạn có thể sử dụng nó để tạo một môi trường ảo.
<div class="termy">
```console
$ uv venv
```
</div>
/// tip
Mặc định, `uv` sẽ tạo một môi trường ảo trong một thư mục có tên `.venv`.
Nhưng bạn có thể tùy chỉnh nó bằng cách thêm một đối số với tên thư mục.
///
////
Lệnh này tạo một môi trường ảo mới trong một thư mục có tên `.venv`.
/// details | `.venv` hoặc tên khác
Bạn có thể tạo môi trường ảo trong một thư mục khác, nhưng thường người ta quy ước đặt nó là `.venv`.
///
## Kích hoạt Môi trường ảo
Kích hoạt môi trường ảo mới để bất kỳ lệnh Python nào bạn chạy hoặc gói nào bạn cài đặt sẽ sử dụng nó.
/// tip
Làm điều này **mỗi khi** bạn bắt đầu một **phiên terminal mới** để làm việc trên dự án.
///
//// tab | Linux, macOS
<div class="termy">
```console
$ source .venv/bin/activate
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
$ .venv\Scripts\Activate.ps1
```
</div>
////
//// tab | Windows Bash
Nếu bạn sử dụng Bash cho Windows (ví dụ: <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>):
<div class="termy">
```console
$ source .venv/Scripts/activate
```
</div>
////
/// tip
Mỗi khi bạn cài đặt thêm một **package mới** trong môi trường đó, hãy **kích hoạt** môi trường đó lại.
Điều này đảm bảo rằng khi bạn sử dụng một **chương trình dòng lệnh (<abbr title="command line interface">CLI</abbr>)** được cài đặt từ gói đó, bạn sẽ dùng bản cài đặt từ môi trường ảo của mình thay vì bản được cài đặt toàn cục khác có thể có phiên bản khác với phiên bản bạn cần.
///
## Kiểm tra xem Môi trường ảo đã được Kích hoạt chưa
Kiểm tra xem môi trường ảo đã được kích hoạt chưa (lệnh trước đó đã hoạt động).
/// tip
Điều này là **không bắt buộc**, nhưng nó là một cách tốt để **kiểm tra** rằng mọi thứ đang hoạt động như mong đợi và bạn đang sử dụng đúng môi trường ảo mà bạn đã định.
///
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
$ which python
/home/user/code/awesome-project/.venv/bin/python
```
</div>
Nếu nó hiển thị `python` binary tại `.venv/bin/python`, trong dự án của bạn (trong trường hợp `awesome-project`), thì tức là nó hoạt động. 🎉
////
//// tab | Windows PowerShell
<div class="termy">
```console
$ Get-Command python
C:\Users\user\code\awesome-project\.venv\Scripts\python
```
</div>
Nếu nó hiển thị `python` binary tại `.venv\Scripts\python`, trong dự án của bạn (trong trường hợp `awesome-project`), thì tức là nó hoạt động. 🎉
////
## Nâng cấp `pip`
/// tip
Nếu bạn sử dụng <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a> bạn sử dụng nó để cài đặt thay vì `pip`, thì bạn không cần cập nhật `pip`. 😎
///
Nếu bạn sử dụng `pip` để cài đặt gói (nó được cài đặt mặc định với Python), bạn nên **nâng cấp** nó lên phiên bản mới nhất.
Nhiều lỗi khác nhau trong khi cài đặt gói được giải quyết chỉ bằng cách nâng cấp `pip` trước.
/// tip
Bạn thường làm điều này **một lần**, ngay sau khi bạn tạo môi trường ảo.
///
Đảm bảo rằng môi trường ảo đã được kích hoạt (với lệnh trên) và sau đó chạy:
<div class="termy">
```console
$ python -m pip install --upgrade pip
---> 100%
```
</div>
## Thêm `.gitignore`
Nếu bạn sử dụng **Git** (nên làm), hãy thêm một file `.gitignore` để Git bỏ qua mọi thứ trong `.venv`.
/// tip
Nếu bạn sử dụng <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a> để tạo môi trường ảo, nó đã tự động làm điều này cho bạn, bạn có thể bỏ qua bước này. 😎
///
/// tip
Làm điều này **một lần**, ngay sau khi bạn tạo môi trường ảo.
///
<div class="termy">
```console
$ echo "*" > .venv/.gitignore
```
</div>
/// details | Cách lệnh hoạt động
* `echo "*"`: sẽ "in" văn bản `*` trong terminal (phần tiếp theo sẽ thay đổi điều đó một chút)
* `>`: bất kỳ văn bản nào được in ra terminal bởi lệnh trước `>` không được in ra mà thay vào đó được viết vào file ở phía bên phải của `>`
* `.gitignore`: tên của file mà văn bản sẽ được viết vào
`*` với Git có nghĩa là "mọi thứ". Vì vậy, nó sẽ bỏ qua mọi thứ trong thư mục `.venv`.
Lệnh này sẽ tạo một file `.gitignore` với nội dung:
```gitignore
*
```
///
## Cài đặt gói (packages)
Sau khi kích hoạt môi trường, bạn có thể cài đặt các gói trong đó.
/// tip
Thực hiện điều này **một lần** khi cài đặt hoặc cập nhật gói cần thiết cho dự án của bạn.
Nếu bạn cần cập nhật phiên bản hoặc thêm một gói mới, bạn sẽ **thực hiện điều này lại**.
///
### Cài đặt gói trực tiếp
Nếu bạn cần cập nhật phiên bản hoặc thêm một gói mới, bạn sẽ **thực hiện điều này lại**.
/// tip
Để quản lý dự án tốt hơn, hãy liệt kê tất cả các gói và phiên bản cần thiết trong một file (ví dụ `requirements.txt` hoặc `pyproject.toml`).
///
//// tab | `pip`
<div class="termy">
```console
$ pip install "fastapi[standard]"
---> 100%
```
</div>
////
//// tab | `uv`
Nếu bạn có <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>:
<div class="termy">
```console
$ uv pip install "fastapi[standard]"
---> 100%
```
</div>
////
### Cài đặt từ `requirements.txt`
Nếu bạn có một tệp `requirements.txt`, bạn có thể sử dụng nó để cài đặt các gói.
//// tab | `pip`
<div class="termy">
```console
$ pip install -r requirements.txt
---> 100%
```
</div>
////
//// tab | `uv`
Nếu bạn có <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">`uv`</a>:
<div class="termy">
```console
$ uv pip install -r requirements.txt
---> 100%
```
</div>
////
/// details | `requirements.txt`
Một tệp `requirements.txt` với một số gói sẽ trông như thế này:
```requirements.txt
fastapi[standard]==0.113.0
pydantic==2.8.0
```
///
## Chạy Chương trình của bạn
Sau khi kích hoạt môi trường ảo, bạn có thể chạy chương trình của mình, nó sẽ sử dụng Python trong môi trường ảo của bạn với các gói bạn đã cài đặt.
<div class="termy">
```console
$ python main.py
Hello World
```
</div>
## Cấu hình Trình soạn thảo của bạn
Nếu bạn sử dụng một trình soạn thảo, hãy đảm bảo bạn cấu hình nó để sử dụng cùng môi trường ảo mà bạn đã tạo (trình soạn thảo sẽ tự động phát hiện môi trường ảo) để bạn có thể nhận được tính năng tự động hoàn thành câu lệnh (autocomplete) và in lỗi trực tiếp trong trình soạn thảo (inline errors).
Ví dụ:
* <a href="https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment" class="external-link" target="_blank">VS Code</a>
* <a href="https://www.jetbrains.com/help/pycharm/creating-virtual-environment.html" class="external-link" target="_blank">PyCharm</a>
/// tip
Bạn thường chỉ cần làm điều này **một lần**, khi bạn tạo môi trường ảo.
///
## Huỷ kích hoạt Môi trường ảo
Khi bạn hoàn tất việc làm trên dự án của bạn, bạn có thể **huỷ kích hoạt** môi trường ảo.
<div class="termy">
```console
$ deactivate
```
</div>
Như vậy, khi bạn chạy `python`, nó sẽ không chạy từ môi trường ảo đó với các gói đã cài đặt.
## Sẵn sàng để Làm việc
Bây giờ bạn đã sẵn sàng để làm việc trên dự án của mình rồi đấy.
/// tip
Bạn muốn hiểu tất cả những gì ở trên?
Tiếp tục đọc. 👇🤓
///
## Tại sao cần Môi trường ảo
Để làm việc với FastAPI, bạn cần cài đặt <a href="https://www.python.org/" class="external-link" target="_blank">Python</a>.
Sau đó, bạn sẽ cần **cài đặt** FastAPI và bất kỳ **gói** nào mà bạn muốn sử dụng.
Để cài đặt gói, bạn thường sử dụng lệnh `pip` có sẵn với Python (hoặc các phiên bản tương tự).
Tuy nhiên, nếu bạn sử dụng `pip` trực tiếp, các gói sẽ được cài đặt trong **môi trường Python toàn cục** của bạn (phần cài đặt toàn cục của Python).
### Vấn đề
Vậy, vấn đề gì khi cài đặt gói trong môi trường Python toàn cục?
Trong một vài thời điểm, bạn sẽ phải viết nhiều chương trình khác nhau phụ thuộc vào **các gói khác nhau**. Và một số dự án bạn thực hiện lại phụ thuộc vào **các phiên bản khác nhau** của cùng một gói. 😱
Ví dụ, bạn có thể tạo một dự án được gọi là `philosophers-stone`, chương trình này phụ thuộc vào một gói khác được gọi là **`harry`, sử dụng phiên bản `1`**. Vì vậy, bạn cần cài đặt `harry`.
```mermaid
flowchart LR
stone(philosophers-stone) -->|phụ thuộc| harry-1[harry v1]
```
Sau đó, vào một vài thời điểm sau, bạn tạo một dự án khác được gọi là `prisoner-of-azkaban`, và dự án này cũng phụ thuộc vào `harry`, nhưng dự án này cần **`harry` phiên bản `3`**.
```mermaid
flowchart LR
azkaban(prisoner-of-azkaban) --> |phụ thuộc| harry-3[harry v3]
```
Bây giờ, vấn đề là, nếu bạn cài đặt các gói toàn cục (trong môi trường toàn cục) thay vì trong một **môi trường ảo cục bộ**, bạn sẽ phải chọn phiên bản `harry` nào để cài đặt.
Nếu bạn muốn chạy `philosophers-stone` bạn sẽ cần phải cài đặt `harry` phiên bản `1`, ví dụ với:
<div class="termy">
```console
$ pip install "harry==1"
```
</div>
Và sau đó bạn sẽ có `harry` phiên bản `1` được cài đặt trong môi trường Python toàn cục của bạn.
```mermaid
flowchart LR
subgraph global[môi trường toàn cục]
harry-1[harry v1]
end
subgraph stone-project[dự án philosophers-stone ]
stone(philosophers-stone) -->|phụ thuộc| harry-1
end
```
Nhưng sau đó, nếu bạn muốn chạy `prisoner-of-azkaban`, bạn sẽ cần phải gỡ bỏ `harry` phiên bản `1` và cài đặt `harry` phiên bản `3` (hoặc chỉ cần cài đặt phiên bản `3` sẽ tự động gỡ bỏ phiên bản `1`).
<div class="termy">
```console
$ pip install "harry==3"
```
</div>
Và sau đó bạn sẽ có `harry` phiên bản `3` được cài đặt trong môi trường Python toàn cục của bạn.
Và nếu bạn cố gắng chạy `philosophers-stone` lại, có khả năng nó sẽ **không hoạt động** vì nó cần `harry` phiên bản `1`.
```mermaid
flowchart LR
subgraph global[môi trường toàn cục]
harry-1[<strike>harry v1</strike>]
style harry-1 fill:#ccc,stroke-dasharray: 5 5
harry-3[harry v3]
end
subgraph stone-project[dự án philosophers-stone ]
stone(philosophers-stone) -.-x|⛔️| harry-1
end
subgraph azkaban-project[dự án prisoner-of-azkaban ]
azkaban(prisoner-of-azkaban) --> |phụ thuộc| harry-3
end
```
/// tip
Mặc dù các gói Python thường cố gắng **tránh các thay đổi làm hỏng code** trong **phiên bản mới**, nhưng để đảm bảo an toàn, bạn nên chủ động cài đặt phiên bản mới và chạy kiểm thử để xác nhận mọi thứ vẫn hoạt động đúng.
///
Bây giờ, hãy hình dung về **nhiều** gói khác nhau mà tất cả các dự án của bạn phụ thuộc vào. Rõ ràng rất khó để quản lý. Điều này dẫn tới việc là bạn sẽ có nhiều dự án với **các phiên bản không tương thích** của các gói, và bạn có thể không biết tại sao một số thứ không hoạt động.
Hơn nữa, tuỳ vào hệ điều hành của bạn (vd Linux, Windows, macOS), có thể đã có Python được cài đặt sẵn. Trong trường hợp ấy, một vài gói nhiều khả năng đã được cài đặt trước với các phiên bản **cần thiết cho hệ thống của bạn**. Nếu bạn cài đặt các gói trong môi trường Python toàn cục, bạn có thể sẽ **phá vỡ** một số chương trình đã được cài đặt sẵn cùng hệ thống.
## Nơi các Gói được Cài đặt
Khi bạn cài đặt Python, nó sẽ tạo ra một vài thư mục và tệp trong máy tính của bạn.
Một vài thư mục này là những thư mục chịu trách nhiệm có tất cả các gói bạn cài đặt.
Khi bạn chạy:
<div class="termy">
```console
// Đừng chạy lệnh này ngay, đây chỉ là một ví dụ 🤓
$ pip install "fastapi[standard]"
---> 100%
```
</div>
Lệnh này sẽ tải xuống một tệp nén với mã nguồn FastAPI, thường là từ <a href="https://pypi.org/project/fastapi/" class="external-link" target="_blank">PyPI</a>.
Nó cũng sẽ **tải xuống** các tệp cho các gói khác mà FastAPI phụ thuộc vào.
Sau đó, nó sẽ **giải nén** tất cả các tệp đó và đưa chúng vào một thư mục trong máy tính của bạn.
Mặc định, nó sẽ đưa các tệp đã tải xuống và giải nén vào thư mục được cài đặt cùng Python của bạn, đó là **môi trường toàn cục**.
## Những Môi trường ảo là gì?
Cách giải quyết cho vấn đề có tất cả các gói trong môi trường toàn cục là sử dụng một **môi trường ảo cho mỗi dự án** bạn làm việc.
Một môi trường ảo là một **thư mục**, rất giống với môi trường toàn cục, trong đó bạn có thể cài đặt các gói cho một dự án.
Vì vậy, mỗi dự án sẽ có một môi trường ảo riêng của nó (thư mục `.venv`) với các gói riêng của nó.
```mermaid
flowchart TB
subgraph stone-project[dự án philosophers-stone ]
stone(philosophers-stone) --->|phụ thuộc| harry-1
subgraph venv1[.venv]
harry-1[harry v1]
end
end
subgraph azkaban-project[dự án prisoner-of-azkaban ]
azkaban(prisoner-of-azkaban) --->|phụ thuộc| harry-3
subgraph venv2[.venv]
harry-3[harry v3]
end
end
stone-project ~~~ azkaban-project
```
## Kích hoạt Môi trường ảo nghĩa là gì
Khi bạn kích hoạt một môi trường ảo, ví dụ với:
//// tab | Linux, macOS
<div class="termy">
```console
$ source .venv/bin/activate
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
$ .venv\Scripts\Activate.ps1
```
</div>
////
//// tab | Windows Bash
Nếu bạn sử dụng Bash cho Windows (ví dụ <a href="https://gitforwindows.org/" class="external-link" target="_blank">Git Bash</a>):
<div class="termy">
```console
$ source .venv/Scripts/activate
```
</div>
////
Lệnh này sẽ tạo hoặc sửa đổi một số [biến môi trường](environment-variables.md){.internal-link target=_blank} mà sẽ được sử dụng cho các lệnh tiếp theo.
Một trong số đó là biến `PATH`.
/// tip
Bạn có thể tìm hiểu thêm về biến `PATH` trong [Biến môi trường](environment-variables.md#path-environment-variable){.internal-link target=_blank} section.
///
Kích hoạt môi trường ảo thêm đường dẫn `.venv/bin` (trên Linux và macOS) hoặc `.venv\Scripts` (trên Windows) vào biến `PATH`.
Giả sử rằng trước khi kích hoạt môi trường, biến `PATH` như sau:
//// tab | Linux, macOS
```plaintext
/usr/bin:/bin:/usr/sbin:/sbin
```
Nghĩa là hệ thống sẽ tìm kiếm chương trình trong:
* `/usr/bin`
* `/bin`
* `/usr/sbin`
* `/sbin`
////
//// tab | Windows
```plaintext
C:\Windows\System32
```
Nghĩa là hệ thống sẽ tìm kiếm chương trình trong:
* `C:\Windows\System32`
////
Sau khi kích hoạt môi trường ảo, biến `PATH` sẽ như sau:
//// tab | Linux, macOS
```plaintext
/home/user/code/awesome-project/.venv/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
Nghĩa là hệ thống sẽ bắt đầu tìm kiếm chương trình trong:
```plaintext
/home/user/code/awesome-project/.venv/bin
```
trước khi tìm kiếm trong các thư mục khác.
Vì vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong:
```plaintext
/home/user/code/awesome-project/.venv/bin/python
```
và sử dụng chương trình đó.
////
//// tab | Windows
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts;C:\Windows\System32
```
Nghĩa là hệ thống sẽ bắt đầu tìm kiếm chương trình trong:
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts
```
trước khi tìm kiếm trong các thư mục khác.
Vì vậy, khi bạn gõ `python` trong terminal, hệ thống sẽ tìm thấy chương trình Python trong:
```plaintext
C:\Users\user\code\awesome-project\.venv\Scripts\python
```
và sử dụng chương trình đó.
////
Một chi tiết quan trọng là nó sẽ đưa địa chỉ của môi trường ảo vào **đầu** của biến `PATH`. Hệ thống sẽ tìm kiếm nó **trước** khi tìm kiếm bất kỳ Python nào khác có sẵn. Vì vậy, khi bạn chạy `python`, nó sẽ sử dụng Python **từ môi trường ảo** thay vì bất kỳ Python nào khác (ví dụ, Python từ môi trường toàn cục).
Kích hoạt một môi trường ảo cũng thay đổi một vài thứ khác, nhưng đây là một trong những điều quan trọng nhất mà nó thực hiện.
## Kiểm tra một Môi trường ảo
Khi bạn kiểm tra một môi trường ảo đã được kích hoạt chưa, ví dụ với:
//// tab | Linux, macOS, Windows Bash
<div class="termy">
```console
$ which python
/home/user/code/awesome-project/.venv/bin/python
```
</div>
////
//// tab | Windows PowerShell
<div class="termy">
```console
$ Get-Command python
C:\Users\user\code\awesome-project\.venv\Scripts\python
```
</div>
////
Điều đó có nghĩa là chương trình `python` sẽ được sử dụng là chương trình **trong môi trường ảo**.
Bạn sử dụng `which` trên Linux và macOS và `Get-Command` trên Windows PowerShell.
Cách hoạt động của lệnh này là nó sẽ đi và kiểm tra biến `PATH`, đi qua **mỗi đường dẫn theo thứ tự**, tìm kiếm chương trình được gọi là `python`. Khi nó tìm thấy nó, nó sẽ **hiển thị cho bạn đường dẫn** đến chương trình đó.
Điều quan trọng nhất là khi bạn gọi `python`, đó chính là chương trình `python` được thực thi.
Vì vậy, bạn có thể xác nhận nếu bạn đang ở trong môi trường ảo đúng.
/// tip
Dễ dàng kích hoạt một môi trường ảo, cài đặt Python, và sau đó **chuyển đến một dự án khác**.
Và dự án thứ hai **sẽ không hoạt động** vì bạn đang sử dụng **Python không đúng**, từ một môi trường ảo cho một dự án khác.
Thật tiện lợi khi có thể kiểm tra `python` nào đang được sử dụng 🤓
///
## Tại sao lại Huỷ kích hoạt một Môi trường ảo
Ví dụ, bạn có thể làm việc trên một dự án `philosophers-stone`, **kích hoạt môi trường ảo**, cài đặt các gói và làm việc với môi trường ảo đó.
Sau đó, bạn muốn làm việc trên **dự án khác** `prisoner-of-azkaban`.
Bạn đi đến dự án đó:
<div class="termy">
```console
$ cd ~/code/prisoner-of-azkaban
```
</div>
Nếu bạn không tắt môi trường ảo cho `philosophers-stone`, khi bạn chạy `python` trong terminal, nó sẽ cố gắng sử dụng Python từ `philosophers-stone`.
<div class="termy">
```console
$ cd ~/code/prisoner-of-azkaban
$ python main.py
// Lỗi khi import sirius, nó không được cài đặt 😱
Traceback (most recent call last):
File "main.py", line 1, in <module>
import sirius
```
</div>
Nếu bạn huỷ kích hoạt môi trường ảo hiện tại và kích hoạt môi trường ảo mới cho `prisoner-of-azkaban`, khi bạn chạy `python`, nó sẽ sử dụng Python từ môi trường ảo trong `prisoner-of-azkaban`.
<div class="termy">
```console
$ cd ~/code/prisoner-of-azkaban
// Bạn không cần phải ở trong thư mục trước để huỷ kích hoạt, bạn có thể làm điều đó ở bất kỳ đâu, ngay cả sau khi đi đến dự án khác 😎
$ deactivate
// Kích hoạt môi trường ảo trong prisoner-of-azkaban/.venv 🚀
$ source .venv/bin/activate
// Bây giờ khi bạn chạy python, nó sẽ tìm thấy gói sirius được cài đặt trong môi trường ảo này ✨
$ python main.py
I solemnly swear 🐺
(Tôi long trọng thề 🐺 - câu này được lấy từ Harry Potter, chú thích của người dịch)
```
</div>
## Các cách làm tương tự
Đây là một hướng dẫn đơn giản để bạn có thể bắt đầu và hiểu cách mọi thứ hoạt động **bên trong**.
Có nhiều **cách khác nhau** để quản lí các môi trường ảo, các gói phụ thuộc (requirements), và các dự án.
Một khi bạn đã sẵn sàng và muốn sử dụng một công cụ để **quản lí cả dự án**, các gói phụ thuộc, các môi trường ảo, v.v. Tôi sẽ khuyên bạn nên thử <a href="https://github.com/astral-sh/uv" class="external-link" target="_blank">uv</a>.
`uv` có thể làm nhiều thứ, chẳng hạn:
* **Cài đặt Python** cho bạn, bao gồm nhiều phiên bản khác nhau
* Quản lí **các môi trường ảo** cho các dự án của bạn
* Cài đặt **các gói (packages)**
* Quản lí **các thành phần phụ thuộc và phiên bản** của các gói cho dự án của bạn
* Đảm bảo rằng bạn có một **tập hợp chính xác** các gói và phiên bản để cài đặt, bao gồm các thành phần phụ thuộc của chúng, để bạn có thể đảm bảo rằng bạn có thể chạy dự án của bạn trong sản xuất chính xác như trong máy tính của bạn trong khi phát triển, điều này được gọi là **locking**
* Và còn nhiều thứ khác nữa
## Kết luận
Nếu bạn đã đọc và hiểu hết những điều này, khá chắc là bây giờ bạn đã **biết nhiều hơn** về môi trường ảo so với kha khá lập trình viên khác đấy. 🤓
Những hiểu biết chi tiết này có thể sẽ hữu ích với bạn trong tương lai khi mà bạn cần gỡ lỗi một vài thứ phức tạp, và bạn đã có những hiểu biết về **ngọn ngành gốc rễ cách nó hoạt động**. 😎

View File

@ -1 +0,0 @@
INHERIT: ../en/mkdocs.yml