committed by
GitHub
43 changed files with 50 additions and 1382 deletions
@ -1,162 +0,0 @@ |
|||
# 🔁 🗄 (🔗) 💽 |
|||
|
|||
👆 💪 ⚙️ <a href="https://github.com/encode/databases" class="external-link" target="_blank">`encode/databases`</a> ⏮️ **FastAPI** 🔗 💽 ⚙️ `async` & `await`. |
|||
|
|||
⚫️ 🔗 ⏮️: |
|||
|
|||
* ✳ |
|||
* ✳ |
|||
* 🗄 |
|||
|
|||
👉 🖼, 👥 🔜 ⚙️ **🗄**, ↩️ ⚫️ ⚙️ 👁 📁 & 🐍 ✔️ 🛠️ 🐕🦺. , 👆 💪 📁 👉 🖼 & 🏃 ⚫️. |
|||
|
|||
⏪, 👆 🏭 🈸, 👆 💪 💚 ⚙️ 💽 💽 💖 **✳**. |
|||
|
|||
!!! tip |
|||
👆 💪 🛠️ 💭 ⚪️➡️ 📄 🔃 🇸🇲 🐜 ([🗄 (🔗) 💽](../tutorial/sql-databases.md){.internal-link target=_blank}), 💖 ⚙️ 🚙 🔢 🎭 🛠️ 💽, 🔬 👆 **FastAPI** 📟. |
|||
|
|||
👉 📄 🚫 ✔ 📚 💭, 🌓 😑 <a href="https://www.starlette.io/database/" class="external-link" target="_blank">💃</a>. |
|||
|
|||
## 🗄 & ⚒ 🆙 `SQLAlchemy` |
|||
|
|||
* 🗄 `SQLAlchemy`. |
|||
* ✍ `metadata` 🎚. |
|||
* ✍ 🏓 `notes` ⚙️ `metadata` 🎚. |
|||
|
|||
```Python hl_lines="4 14 16-22" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! tip |
|||
👀 👈 🌐 👉 📟 😁 🇸🇲 🐚. |
|||
|
|||
`databases` 🚫 🔨 🕳 📥. |
|||
|
|||
## 🗄 & ⚒ 🆙 `databases` |
|||
|
|||
* 🗄 `databases`. |
|||
* ✍ `DATABASE_URL`. |
|||
* ✍ `database` 🎚. |
|||
|
|||
```Python hl_lines="3 9 12" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! tip |
|||
🚥 👆 🔗 🎏 💽 (✅ ✳), 👆 🔜 💪 🔀 `DATABASE_URL`. |
|||
|
|||
## ✍ 🏓 |
|||
|
|||
👉 💼, 👥 🏗 🏓 🎏 🐍 📁, ✋️ 🏭, 👆 🔜 🎲 💚 ✍ 👫 ⏮️ ⚗, 🛠️ ⏮️ 🛠️, ♒️. |
|||
|
|||
📥, 👉 📄 🔜 🏃 🔗, ▶️️ ⏭ ▶️ 👆 **FastAPI** 🈸. |
|||
|
|||
* ✍ `engine`. |
|||
* ✍ 🌐 🏓 ⚪️➡️ `metadata` 🎚. |
|||
|
|||
```Python hl_lines="25-28" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## ✍ 🏷 |
|||
|
|||
✍ Pydantic 🏷: |
|||
|
|||
* 🗒 ✍ (`NoteIn`). |
|||
* 🗒 📨 (`Note`). |
|||
|
|||
```Python hl_lines="31-33 36-39" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
🏗 👫 Pydantic 🏷, 🔢 💽 🔜 ✔, 🎻 (🗜), & ✍ (📄). |
|||
|
|||
, 👆 🔜 💪 👀 ⚫️ 🌐 🎓 🛠️ 🩺. |
|||
|
|||
## 🔗 & 🔌 |
|||
|
|||
* ✍ 👆 `FastAPI` 🈸. |
|||
* ✍ 🎉 🐕🦺 🔗 & 🔌 ⚪️➡️ 💽. |
|||
|
|||
```Python hl_lines="42 45-47 50-52" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## ✍ 🗒 |
|||
|
|||
✍ *➡ 🛠️ 🔢* ✍ 🗒: |
|||
|
|||
```Python hl_lines="55-58" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! Note |
|||
👀 👈 👥 🔗 ⏮️ 💽 ⚙️ `await`, *➡ 🛠️ 🔢* 📣 ⏮️ `async`. |
|||
|
|||
### 👀 `response_model=List[Note]` |
|||
|
|||
⚫️ ⚙️ `typing.List`. |
|||
|
|||
👈 📄 (& ✔, 🎻, ⛽) 🔢 💽, `list` `Note`Ⓜ. |
|||
|
|||
## ✍ 🗒 |
|||
|
|||
✍ *➡ 🛠️ 🔢* ✍ 🗒: |
|||
|
|||
```Python hl_lines="61-65" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! Note |
|||
👀 👈 👥 🔗 ⏮️ 💽 ⚙️ `await`, *➡ 🛠️ 🔢* 📣 ⏮️ `async`. |
|||
|
|||
### 🔃 `{**note.dict(), "id": last_record_id}` |
|||
|
|||
`note` Pydantic `Note` 🎚. |
|||
|
|||
`note.dict()` 📨 `dict` ⏮️ 🚮 💽, 🕳 💖: |
|||
|
|||
```Python |
|||
{ |
|||
"text": "Some note", |
|||
"completed": False, |
|||
} |
|||
``` |
|||
|
|||
✋️ ⚫️ 🚫 ✔️ `id` 🏑. |
|||
|
|||
👥 ✍ 🆕 `dict`, 👈 🔌 🔑-💲 👫 ⚪️➡️ `note.dict()` ⏮️: |
|||
|
|||
```Python |
|||
{**note.dict()} |
|||
``` |
|||
|
|||
`**note.dict()` "unpacks" the key value pairs directly, so, `{**note.dict()}` would be, more or less, a copy of `note.dict()`. |
|||
|
|||
& ⤴️, 👥 ↔ 👈 📁 `dict`, ❎ ➕1️⃣ 🔑-💲 👫: `"id": last_record_id`: |
|||
|
|||
```Python |
|||
{**note.dict(), "id": last_record_id} |
|||
``` |
|||
|
|||
, 🏁 🏁 📨 🔜 🕳 💖: |
|||
|
|||
```Python |
|||
{ |
|||
"id": 1, |
|||
"text": "Some note", |
|||
"completed": False, |
|||
} |
|||
``` |
|||
|
|||
## ✅ ⚫️ |
|||
|
|||
👆 💪 📁 👉 📟, & 👀 🩺 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>. |
|||
|
|||
📤 👆 💪 👀 🌐 👆 🛠️ 📄 & 🔗 ⏮️ ⚫️: |
|||
|
|||
<img src="/img/tutorial/async-sql-databases/image01.png"> |
|||
|
|||
## 🌅 ℹ |
|||
|
|||
👆 💪 ✍ 🌅 🔃 <a href="https://github.com/encode/databases" class="external-link" target="_blank">`encode/databases` 🚮 📂 📃</a>. |
@ -1,156 +0,0 @@ |
|||
# ☁ (📎 / 🦏 💽) 💽 |
|||
|
|||
**FastAPI** 💪 🛠️ ⏮️ 🙆 <abbr title="Distributed database (Big Data), also 'Not Only SQL'">☁</abbr>. |
|||
|
|||
📥 👥 🔜 👀 🖼 ⚙️ **<a href="https://www.couchbase.com/" class="external-link" target="_blank">🗄</a>**, <abbr title="Document here refers to a JSON object (a dict), with keys and values, and those values can also be other JSON objects, arrays (lists), numbers, strings, booleans, etc.">📄</abbr> 🧢 ☁ 💽. |
|||
|
|||
👆 💪 🛠️ ⚫️ 🙆 🎏 ☁ 💽 💖: |
|||
|
|||
* **✳** |
|||
* **👸** |
|||
* **✳** |
|||
* **🇸🇲** |
|||
* **✳**, ♒️. |
|||
|
|||
!!! tip |
|||
📤 🛂 🏗 🚂 ⏮️ **FastAPI** & **🗄**, 🌐 ⚓️ 🔛 **☁**, 🔌 🕸 & 🌖 🧰: <a href="https://github.com/tiangolo/full-stack-fastapi-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-couchbase</a> |
|||
|
|||
## 🗄 🗄 🦲 |
|||
|
|||
🔜, 🚫 💸 🙋 🎂, 🕴 🗄: |
|||
|
|||
```Python hl_lines="3-5" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## 🔬 📉 ⚙️ "📄 🆎" |
|||
|
|||
👥 🔜 ⚙️ ⚫️ ⏪ 🔧 🏑 `type` 👆 📄. |
|||
|
|||
👉 🚫 ✔ 🗄, ✋️ 👍 💡 👈 🔜 ℹ 👆 ⏮️. |
|||
|
|||
```Python hl_lines="9" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## 🚮 🔢 🤚 `Bucket` |
|||
|
|||
**🗄**, 🥡 ⚒ 📄, 👈 💪 🎏 🆎. |
|||
|
|||
👫 🛎 🌐 🔗 🎏 🈸. |
|||
|
|||
🔑 🔗 💽 🌏 🔜 "💽" (🎯 💽, 🚫 💽 💽). |
|||
|
|||
🔑 **✳** 🔜 "🗃". |
|||
|
|||
📟, `Bucket` 🎨 👑 🇨🇻 📻 ⏮️ 💽. |
|||
|
|||
👉 🚙 🔢 🔜: |
|||
|
|||
* 🔗 **🗄** 🌑 (👈 💪 👁 🎰). |
|||
* ⚒ 🔢 ⏲. |
|||
* 🔓 🌑. |
|||
* 🤚 `Bucket` 👐. |
|||
* ⚒ 🔢 ⏲. |
|||
* 📨 ⚫️. |
|||
|
|||
```Python hl_lines="12-21" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## ✍ Pydantic 🏷 |
|||
|
|||
**🗄** "📄" 🤙 "🎻 🎚", 👥 💪 🏷 👫 ⏮️ Pydantic. |
|||
|
|||
### `User` 🏷 |
|||
|
|||
🥇, ➡️ ✍ `User` 🏷: |
|||
|
|||
```Python hl_lines="24-28" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
👥 🔜 ⚙️ 👉 🏷 👆 *➡ 🛠️ 🔢*,, 👥 🚫 🔌 ⚫️ `hashed_password`. |
|||
|
|||
### `UserInDB` 🏷 |
|||
|
|||
🔜, ➡️ ✍ `UserInDB` 🏷. |
|||
|
|||
👉 🔜 ✔️ 💽 👈 🤙 🏪 💽. |
|||
|
|||
👥 🚫 ✍ ⚫️ 🏿 Pydantic `BaseModel` ✋️ 🏿 👆 👍 `User`, ↩️ ⚫️ 🔜 ✔️ 🌐 🔢 `User` ➕ 👩❤👨 🌅: |
|||
|
|||
```Python hl_lines="31-33" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! note |
|||
👀 👈 👥 ✔️ `hashed_password` & `type` 🏑 👈 🔜 🏪 💽. |
|||
|
|||
✋️ ⚫️ 🚫 🍕 🏢 `User` 🏷 (1️⃣ 👥 🔜 📨 *➡ 🛠️*). |
|||
|
|||
## 🤚 👩💻 |
|||
|
|||
🔜 ✍ 🔢 👈 🔜: |
|||
|
|||
* ✊ 🆔. |
|||
* 🏗 📄 🆔 ⚪️➡️ ⚫️. |
|||
* 🤚 📄 ⏮️ 👈 🆔. |
|||
* 🚮 🎚 📄 `UserInDB` 🏷. |
|||
|
|||
🏗 🔢 👈 🕴 💡 🤚 👆 👩💻 ⚪️➡️ `username` (⚖️ 🙆 🎏 🔢) 🔬 👆 *➡ 🛠️ 🔢*, 👆 💪 🌖 💪 🏤-⚙️ ⚫️ 💗 🍕 & 🚮 <abbr title="Automated test, written in code, that checks if another piece of code is working correctly.">⚒ 💯</abbr> ⚫️: |
|||
|
|||
```Python hl_lines="36-42" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
### Ⓜ-🎻 |
|||
|
|||
🚥 👆 🚫 😰 ⏮️ `f"userprofile::{username}"`, ⚫️ 🐍 "<a href="https://docs.python.org/3/glossary.html#term-f-string" class="external-link" target="_blank">Ⓜ-🎻</a>". |
|||
|
|||
🙆 🔢 👈 🚮 🔘 `{}` Ⓜ-🎻 🔜 ↔ / 💉 🎻. |
|||
|
|||
### `dict` 🏗 |
|||
|
|||
🚥 👆 🚫 😰 ⏮️ `UserInDB(**result.value)`, <a href="https://docs.python.org/3/glossary.html#term-argument" class="external-link" target="_blank">⚫️ ⚙️ `dict` "🏗"</a>. |
|||
|
|||
⚫️ 🔜 ✊ `dict` `result.value`, & ✊ 🔠 🚮 🔑 & 💲 & 🚶♀️ 👫 🔑-💲 `UserInDB` 🇨🇻 ❌. |
|||
|
|||
, 🚥 `dict` 🔌: |
|||
|
|||
```Python |
|||
{ |
|||
"username": "johndoe", |
|||
"hashed_password": "some_hash", |
|||
} |
|||
``` |
|||
|
|||
⚫️ 🔜 🚶♀️ `UserInDB` : |
|||
|
|||
```Python |
|||
UserInDB(username="johndoe", hashed_password="some_hash") |
|||
``` |
|||
|
|||
## ✍ 👆 **FastAPI** 📟 |
|||
|
|||
### ✍ `FastAPI` 📱 |
|||
|
|||
```Python hl_lines="46" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
### ✍ *➡ 🛠️ 🔢* |
|||
|
|||
👆 📟 🤙 🗄 & 👥 🚫 ⚙️ <a href="https://docs.couchbase.com/python-sdk/2.5/async-programming.html#asyncio-python-3-5" class="external-link" target="_blank">🥼 🐍 <code>await</code> 🐕🦺</a>, 👥 🔜 📣 👆 🔢 ⏮️ 😐 `def` ↩️ `async def`. |
|||
|
|||
, 🗄 👍 🚫 ⚙️ 👁 `Bucket` 🎚 💗 "<abbr title="A sequence of code being executed by the program, while at the same time, or at intervals, there can be others being executed too.">🧵</abbr>Ⓜ",, 👥 💪 🤚 🥡 🔗 & 🚶♀️ ⚫️ 👆 🚙 🔢: |
|||
|
|||
```Python hl_lines="49-53" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## 🌃 |
|||
|
|||
👆 💪 🛠️ 🙆 🥉 🥳 ☁ 💽, ⚙️ 👫 🐩 📦. |
|||
|
|||
🎏 ✔ 🙆 🎏 🔢 🧰, ⚙️ ⚖️ 🛠️. |
@ -1,156 +0,0 @@ |
|||
# NoSQL (分散 / ビッグデータ) Databases |
|||
|
|||
**FastAPI** はあらゆる <abbr title="分散データベース (Big Data)や 'Not Only SQL'">NoSQL</abbr>と統合することもできます。 |
|||
|
|||
ここでは<abbr title="ここでのドキュメントとは、キーと値を持つJSONオブジェクト(ディクショナリー)をあらわし、これらの値は他のJSONオブジェクトや配列(リスト)、数値、文字列、真偽値などにすることができます。">ドキュメント</abbr>ベースのNoSQLデータベースである**<a href="https://www.couchbase.com/" class="external-link" target="_blank">Couchbase</a>**を使用した例を見てみましょう。 |
|||
|
|||
他にもこれらのNoSQLデータベースを利用することが出来ます: |
|||
|
|||
* **MongoDB** |
|||
* **Cassandra** |
|||
* **CouchDB** |
|||
* **ArangoDB** |
|||
* **ElasticSearch** など。 |
|||
|
|||
!!! tip "豆知識" |
|||
**FastAPI**と**Couchbase**を使った公式プロジェクト・ジェネレータがあります。すべて**Docker**ベースで、フロントエンドやその他のツールも含まれています: <a href="https://github.com/tiangolo/full-stack-fastapi-couchbase" class="external-link" target="_blank">https://github.com/tiangolo/full-stack-fastapi-couchbase</a> |
|||
|
|||
## Couchbase コンポーネントの Import |
|||
|
|||
まずはImportしましょう。今はその他のソースコードに注意を払う必要はありません。 |
|||
|
|||
```Python hl_lines="3-5" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## "document type" として利用する定数の定義 |
|||
|
|||
documentで利用する固定の`type`フィールドを用意しておきます。 |
|||
|
|||
これはCouchbaseで必須ではありませんが、後々の助けになるベストプラクティスです。 |
|||
|
|||
```Python hl_lines="9" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## `Bucket` を取得する関数の追加 |
|||
|
|||
**Couchbase**では、bucketはdocumentのセットで、様々な種類のものがあります。 |
|||
|
|||
Bucketは通常、同一のアプリケーション内で互いに関係を持っています。 |
|||
|
|||
リレーショナルデータベースの世界でいう"database"(データベースサーバではなく特定のdatabase)と類似しています。 |
|||
|
|||
**MongoDB** で例えると"collection"と似た概念です。 |
|||
|
|||
次のコードでは主に `Bucket` を利用してCouchbaseを操作します。 |
|||
|
|||
この関数では以下の処理を行います: |
|||
|
|||
* **Couchbase** クラスタ(1台の場合もあるでしょう)に接続 |
|||
* タイムアウトのデフォルト値を設定 |
|||
* クラスタで認証を取得 |
|||
* `Bucket` インスタンスを取得 |
|||
* タイムアウトのデフォルト値を設定 |
|||
* 作成した`Bucket`インスタンスを返却 |
|||
|
|||
```Python hl_lines="12-21" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## Pydantic モデルの作成 |
|||
|
|||
**Couchbase**のdocumentは実際には単にJSONオブジェクトなのでPydanticを利用してモデルに出来ます。 |
|||
|
|||
### `User` モデル |
|||
|
|||
まずは`User`モデルを作成してみましょう: |
|||
|
|||
```Python hl_lines="24-28" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
このモデルは*path operation*に使用するので`hashed_password`は含めません。 |
|||
|
|||
### `UserInDB` モデル |
|||
|
|||
それでは`UserInDB`モデルを作成しましょう。 |
|||
|
|||
こちらは実際にデータベースに保存されるデータを保持します。 |
|||
|
|||
`User`モデルの持つ全ての属性に加えていくつかの属性を追加するのでPydanticの`BaseModel`を継承せずに`User`のサブクラスとして定義します: |
|||
|
|||
```Python hl_lines="31-33" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! note "備考" |
|||
データベースに保存される`hashed_password`と`type`フィールドを`UserInDB`モデルに保持させていることに注意してください。 |
|||
|
|||
しかしこれらは(*path operation*で返却する)一般的な`User`モデルには含まれません |
|||
|
|||
## user の取得 |
|||
|
|||
それでは次の関数を作成しましょう: |
|||
|
|||
* username を取得する |
|||
* username を利用してdocumentのIDを生成する |
|||
* 作成したIDでdocumentを取得する |
|||
* documentの内容を`UserInDB`モデルに設定する |
|||
|
|||
*path operation関数*とは別に、`username`(またはその他のパラメータ)からuserを取得することだけに特化した関数を作成することで、より簡単に複数の部分で再利用したり<abbr title="コードで書かれた自動テストで、他のコードが正しく動作しているかどうかをチェックするもの。">ユニットテスト</abbr>を追加することができます。 |
|||
|
|||
```Python hl_lines="36-42" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
### f-strings |
|||
|
|||
`f"userprofile::{username}"` という記載に馴染みがありませんか?これは Python の"<a href="https://docs.python.org/3/glossary.html#term-f-string" class="external-link" target="_blank">f-string</a>"と呼ばれるものです。 |
|||
|
|||
f-stringの`{}`の中に入れられた変数は、文字列の中に展開/注入されます。 |
|||
|
|||
### `dict` アンパック |
|||
|
|||
`UserInDB(**result.value)`という記載に馴染みがありませんか?<a href="https://docs.python.org/3/glossary.html#term-argument" class="external-link" target="_blank">これは`dict`の"アンパック"</a>と呼ばれるものです。 |
|||
|
|||
これは`result.value`の`dict`からそのキーと値をそれぞれ取りキーワード引数として`UserInDB`に渡します。 |
|||
|
|||
例えば`dict`が下記のようになっていた場合: |
|||
|
|||
```Python |
|||
{ |
|||
"username": "johndoe", |
|||
"hashed_password": "some_hash", |
|||
} |
|||
``` |
|||
|
|||
`UserInDB`には次のように渡されます: |
|||
|
|||
```Python |
|||
UserInDB(username="johndoe", hashed_password="some_hash") |
|||
``` |
|||
|
|||
## **FastAPI** コードの実装 |
|||
|
|||
### `FastAPI` app の作成 |
|||
|
|||
```Python hl_lines="46" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
### *path operation関数*の作成 |
|||
|
|||
私たちのコードはCouchbaseを呼び出しており、<a href="https://docs.couchbase.com/python-sdk/2.5/async-programming.html#asyncio-python-3-5" class="external-link" target="_blank">実験的なPython <code>await</code></a>を使用していないので、私たちは`async def`ではなく通常の`def`で関数を宣言する必要があります。 |
|||
|
|||
また、Couchbaseは単一の`Bucket`オブジェクトを複数の<abbr title="プログラムによって実行される一連のコードのことで、同時に、または間隔をおいて他のコードも実行されることがあります。">スレッド</abbr>で使用しないことを推奨していますので、単に直接Bucketを取得して関数に渡すことが出来ます。 |
|||
|
|||
```Python hl_lines="49-53" |
|||
{!../../../docs_src/nosql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## まとめ |
|||
|
|||
他のサードパーティ製のNoSQLデータベースを利用する場合でも、そのデータベースの標準ライブラリを利用するだけで利用できます。 |
|||
|
|||
他の外部ツール、システム、APIについても同じことが言えます。 |
@ -1,167 +0,0 @@ |
|||
# 异步 SQL 关系型数据库 |
|||
|
|||
**FastAPI** 使用 <a href="https://github.com/encode/databases" class="external-link" target="_blank">`encode/databases`</a> 为连接数据库提供异步支持(`async` 与 `await`)。 |
|||
|
|||
`databases` 兼容以下数据库: |
|||
|
|||
* PostgreSQL |
|||
* MySQL |
|||
* SQLite |
|||
|
|||
本章示例使用 **SQLite**,它使用的是单文件,且 Python 内置集成了 SQLite,因此,可以直接复制并运行本章示例。 |
|||
|
|||
生产环境下,则要使用 **PostgreSQL** 等数据库服务器。 |
|||
|
|||
!!! tip "提示" |
|||
|
|||
您可以使用 SQLAlchemy ORM([SQL 关系型数据库一章](../tutorial/sql-databases.md){.internal-link target=_blank})中的思路,比如,使用工具函数在数据库中执行操作,独立于 **FastAPI** 代码。 |
|||
|
|||
本章不应用这些思路,等效于 <a href="https://www.starlette.io/database/" class="external-link" target="_blank">Starlette</a> 的对应内容。 |
|||
|
|||
## 导入与设置 `SQLAlchemy` |
|||
|
|||
* 导入 `SQLAlchemy` |
|||
* 创建 `metadata` 对象 |
|||
* 使用 `metadata` 对象创建 `notes` 表 |
|||
|
|||
```Python hl_lines="4 14 16-22" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! tip "提示" |
|||
|
|||
注意,上例是都是纯 SQLAlchemy Core 代码。 |
|||
|
|||
`databases` 还没有进行任何操作。 |
|||
|
|||
## 导入并设置 `databases` |
|||
|
|||
* 导入 `databases` |
|||
* 创建 `DATABASE_URL` |
|||
* 创建 `database` |
|||
|
|||
```Python hl_lines="3 9 12" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! tip "提示" |
|||
|
|||
连接 PostgreSQL 等数据库时,需要修改 `DATABASE_URL`。 |
|||
|
|||
## 创建表 |
|||
|
|||
本例中,使用 Python 文件创建表,但在生产环境中,应使用集成迁移等功能的 Alembic 创建表。 |
|||
|
|||
本例在启动 **FastAPI** 应用前,直接执行这些操作。 |
|||
|
|||
* 创建 `engine` |
|||
* 使用 `metadata` 对象创建所有表 |
|||
|
|||
```Python hl_lines="25-28" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## 创建模型 |
|||
|
|||
创建以下 Pydantic 模型: |
|||
|
|||
* 创建笔记的模型(`NoteIn`) |
|||
* 返回笔记的模型(`Note`) |
|||
|
|||
```Python hl_lines="31-33 36-39" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
这两个 Pydantic 模型都可以辅助验证、序列化(转换)并注释(存档)输入的数据。 |
|||
|
|||
因此,API 文档会显示这些数据。 |
|||
|
|||
## 连接与断开 |
|||
|
|||
* 创建 `FastAPI` 应用 |
|||
* 创建事件处理器,执行数据库连接与断开操作 |
|||
|
|||
```Python hl_lines="42 45-47 50-52" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
## 读取笔记 |
|||
|
|||
创建读取笔记的*路径操作函数*: |
|||
|
|||
```Python hl_lines="55-58" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! Note "笔记" |
|||
|
|||
注意,本例与数据库通信时使用 `await`,因此*路径操作函数*要声明为异步函数(`asnyc`)。 |
|||
|
|||
### 注意 `response_model=List[Note]` |
|||
|
|||
`response_model=List[Note]` 使用的是 `typing.List`。 |
|||
|
|||
它以笔记(`Note`)列表的形式存档(及验证、序列化、筛选)输出的数据。 |
|||
|
|||
## 创建笔记 |
|||
|
|||
创建新建笔记的*路径操作函数*: |
|||
|
|||
```Python hl_lines="61-65" |
|||
{!../../../docs_src/async_sql_databases/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! Note "笔记" |
|||
|
|||
注意,本例与数据库通信时使用 `await`,因此要把*路径操作函数*声明为异步函数(`asnyc`)。 |
|||
|
|||
### 关于 `{**note.dict(), "id": last_record_id}` |
|||
|
|||
`note` 是 Pydantic `Note` 对象: |
|||
|
|||
`note.dict()` 返回包含如下数据的**字典**: |
|||
|
|||
```Python |
|||
{ |
|||
"text": "Some note", |
|||
"completed": False, |
|||
} |
|||
``` |
|||
|
|||
但它不包含 `id` 字段。 |
|||
|
|||
因此要新建一个包含 `note.dict()` 键值对的**字典**: |
|||
|
|||
```Python |
|||
{**note.dict()} |
|||
``` |
|||
|
|||
`**note.dict()` 直接**解包**键值对, 因此,`{**note.dict()}` 是 `note.dict()` 的副本。 |
|||
|
|||
然后,扩展`dict` 副本,添加键值对`"id": last_record_id`: |
|||
|
|||
```Python |
|||
{**note.dict(), "id": last_record_id} |
|||
``` |
|||
|
|||
最终返回的结果如下: |
|||
|
|||
```Python |
|||
{ |
|||
"id": 1, |
|||
"text": "Some note", |
|||
"completed": False, |
|||
} |
|||
``` |
|||
|
|||
## 查看文档 |
|||
|
|||
复制这些代码,查看文档 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs。</a> |
|||
|
|||
API 文档显示如下内容: |
|||
|
|||
<img src="/img/tutorial/async-sql-databases/image01.png"> |
|||
|
|||
## 更多说明 |
|||
|
|||
更多内容详见 <a href="https://github.com/encode/databases" class="external-link" target="_blank">Github 上的`encode/databases` 的说明</a>。 |
@ -1,113 +0,0 @@ |
|||
# 自定义请求与 APIRoute 类 |
|||
|
|||
有时,我们要覆盖 `Request` 与 `APIRoute` 类使用的逻辑。 |
|||
|
|||
尤其是中间件里的逻辑。 |
|||
|
|||
例如,在应用处理请求体前,预先读取或操控请求体。 |
|||
|
|||
!!! danger "危险" |
|||
|
|||
本章内容**较难**。 |
|||
|
|||
**FastAPI** 新手可跳过本章。 |
|||
|
|||
## 用例 |
|||
|
|||
常见用例如下: |
|||
|
|||
* 把 <a href="https://msgpack.org/index.html" class="external-link" target="_blank">`msgpack`</a> 等非 JSON 请求体转换为 JSON |
|||
* 解压 gzip 压缩的请求体 |
|||
* 自动记录所有请求体的日志 |
|||
|
|||
## 处理自定义请求体编码 |
|||
|
|||
下面学习如何使用自定义 `Request` 子类压缩 gizp 请求。 |
|||
|
|||
并在自定义请求的类中使用 `APIRoute` 子类。 |
|||
|
|||
### 创建自定义 `GzipRequest` 类 |
|||
|
|||
!!! tip "提示" |
|||
|
|||
本例只是为了说明 `GzipRequest` 类如何运作。如需 Gzip 支持,请使用 [`GzipMiddleware`](./middleware.md#gzipmiddleware){.internal-link target=_blank}。 |
|||
|
|||
首先,创建 `GzipRequest` 类,覆盖解压请求头中请求体的 `Request.body()` 方法。 |
|||
|
|||
请求头中没有 `gzip` 时,`GzipRequest` 不会解压请求体。 |
|||
|
|||
这样就可以让同一个路由类处理 gzip 压缩的请求或未压缩的请求。 |
|||
|
|||
```Python hl_lines="8-15" |
|||
{!../../../docs_src/custom_request_and_route/tutorial001.py!} |
|||
``` |
|||
|
|||
### 创建自定义 `GzipRoute` 类 |
|||
|
|||
接下来,创建使用 `GzipRequest` 的 `fastapi.routing.APIRoute ` 的自定义子类。 |
|||
|
|||
此时,这个自定义子类会覆盖 `APIRoute.get_route_handler()`。 |
|||
|
|||
`APIRoute.get_route_handler()` 方法返回的是函数,并且返回的函数接收请求并返回响应。 |
|||
|
|||
本例用它根据原始请求创建 `GzipRequest`。 |
|||
|
|||
```Python hl_lines="18-26" |
|||
{!../../../docs_src/custom_request_and_route/tutorial001.py!} |
|||
``` |
|||
|
|||
!!! note "技术细节" |
|||
|
|||
`Request` 的 `request.scope` 属性是包含关联请求元数据的字典。 |
|||
|
|||
`Request` 的 `request.receive` 方法是**接收**请求体的函数。 |
|||
|
|||
`scope` 字典与 `receive` 函数都是 ASGI 规范的内容。 |
|||
|
|||
`scope` 与 `receive` 也是创建新的 `Request` 实例所需的。 |
|||
|
|||
`Request` 的更多内容详见 <a href="https://www.starlette.io/requests/" class="external-link" target="_blank">Starlette 官档 - 请求</a>。 |
|||
|
|||
`GzipRequest.get_route_handler` 返回函数的唯一区别是把 `Request` 转换成了 `GzipRequest`。 |
|||
|
|||
如此一来,`GzipRequest` 把数据传递给*路径操作*前,就会解压数据(如需)。 |
|||
|
|||
之后,所有处理逻辑都一样。 |
|||
|
|||
但因为改变了 `GzipRequest.body`,**FastAPI** 加载请求体时会自动解压。 |
|||
|
|||
## 在异常处理器中访问请求体 |
|||
|
|||
!!! tip "提示" |
|||
|
|||
为了解决同样的问题,在 `RequestValidationError` 的自定义处理器使用 `body` ([处理错误](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank})可能会更容易。 |
|||
|
|||
但本例仍然可行,而且本例展示了如何与内部组件进行交互。 |
|||
|
|||
同样也可以在异常处理器中访问请求体。 |
|||
|
|||
此时要做的只是处理 `try`/`except` 中的请求: |
|||
|
|||
```Python hl_lines="13 15" |
|||
{!../../../docs_src/custom_request_and_route/tutorial002.py!} |
|||
``` |
|||
|
|||
发生异常时,`Request` 实例仍在作用域内,因此处理错误时可以读取和使用请求体: |
|||
|
|||
```Python hl_lines="16-18" |
|||
{!../../../docs_src/custom_request_and_route/tutorial002.py!} |
|||
``` |
|||
|
|||
## 在路由中自定义 `APIRoute` 类 |
|||
|
|||
您还可以设置 `APIRoute` 的 `route_class` 参数: |
|||
|
|||
```Python hl_lines="26" |
|||
{!../../../docs_src/custom_request_and_route/tutorial003.py!} |
|||
``` |
|||
|
|||
本例中,*路径操作*下的 `router` 使用自定义的 `TimedRoute` 类,并在响应中包含输出生成响应时间的 `X-Response-Time` 响应头: |
|||
|
|||
```Python hl_lines="13-20" |
|||
{!../../../docs_src/custom_request_and_route/tutorial003.py!} |
|||
``` |
@ -1,252 +0,0 @@ |
|||
# 扩展 OpenAPI |
|||
|
|||
!!! warning "警告" |
|||
|
|||
本章介绍的功能较难,您可以跳过阅读。 |
|||
|
|||
如果您刚开始学习**用户指南**,最好跳过本章。 |
|||
|
|||
如果您确定要修改 OpenAPI 概图,请继续阅读。 |
|||
|
|||
某些情况下,我们需要修改 OpenAPI 概图。 |
|||
|
|||
本章介绍如何修改 OpenAPI 概图。 |
|||
|
|||
## 常规流程 |
|||
|
|||
常规(默认)流程如下。 |
|||
|
|||
`FastAPI` 应用(实例)提供了返回 OpenAPI 概图的 `.openapi()` 方法。 |
|||
|
|||
作为应用对象创建的组成部分,要注册 `/openapi.json` (或其它为 `openapi_url` 设置的任意内容)*路径操作*。 |
|||
|
|||
它只返回包含应用的 `.openapi()` 方法操作结果的 JSON 响应。 |
|||
|
|||
但默认情况下,`.openapi()` 只是检查 `.openapi_schema` 属性是否包含内容,并返回其中的内容。 |
|||
|
|||
如果 `.openapi_schema` 属性没有内容,该方法就使用 `fastapi.openapi.utils.get_openapi` 工具函数生成内容。 |
|||
|
|||
`get_openapi()` 函数接收如下参数: |
|||
|
|||
* `title`:文档中显示的 OpenAPI 标题 |
|||
* `version`:API 的版本号,例如 `2.5.0` |
|||
* `openapi_version`: OpenAPI 规范的版本号,默认为最新版: `3.0.2` |
|||
* `description`:API 的描述说明 |
|||
* `routes`:路由列表,每个路由都是注册的*路径操作*。这些路由是从 `app.routes` 中提取的。 |
|||
|
|||
## 覆盖默认值 |
|||
|
|||
`get_openapi()` 工具函数还可以用于生成 OpenAPI 概图,并利用上述信息参数覆盖指定的内容。 |
|||
|
|||
例如,使用 <a href="https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo" class="external-link" target="_blank">ReDoc 的 OpenAPI 扩展添加自定义 Logo</a>。 |
|||
|
|||
### 常规 **FastAPI** |
|||
|
|||
首先,编写常规 **FastAPI** 应用: |
|||
|
|||
```Python hl_lines="1 4 7-9" |
|||
{!../../../docs_src/extending_openapi/tutorial001.py!} |
|||
``` |
|||
|
|||
### 生成 OpenAPI 概图 |
|||
|
|||
然后,在 `custom_openapi()` 函数里使用 `get_openapi()` 工具函数生成 OpenAPI 概图: |
|||
|
|||
```Python hl_lines="2 15-20" |
|||
{!../../../docs_src/extending_openapi/tutorial001.py!} |
|||
``` |
|||
|
|||
### 修改 OpenAPI 概图 |
|||
|
|||
添加 ReDoc 扩展信息,为 OpenAPI 概图里的 `info` **对象**添加自定义 `x-logo`: |
|||
|
|||
```Python hl_lines="21-23" |
|||
{!../../../docs_src/extending_openapi/tutorial001.py!} |
|||
``` |
|||
|
|||
### 缓存 OpenAPI 概图 |
|||
|
|||
把 `.openapi_schema` 属性当作**缓存**,存储生成的概图。 |
|||
|
|||
通过这种方式,**FastAPI** 应用不必在用户每次打开 API 文档时反复生成概图。 |
|||
|
|||
只需生成一次,下次请求时就可以使用缓存的概图。 |
|||
|
|||
```Python hl_lines="13-14 24-25" |
|||
{!../../../docs_src/extending_openapi/tutorial001.py!} |
|||
``` |
|||
|
|||
### 覆盖方法 |
|||
|
|||
用新函数替换 `.openapi()` 方法。 |
|||
|
|||
```Python hl_lines="28" |
|||
{!../../../docs_src/extending_openapi/tutorial001.py!} |
|||
``` |
|||
|
|||
### 查看文档 |
|||
|
|||
打开 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc,查看</a>自定义 Logo(本例中是 **FastAPI** 的 Logo): |
|||
|
|||
<img src="/img/tutorial/extending-openapi/image01.png"> |
|||
|
|||
## 文档 JavaScript 与 CSS 自托管 |
|||
|
|||
FastAPI 支持 **Swagger UI** 和 **ReDoc** 两种 API 文档,这两种文档都需要调用 JavaScript 与 CSS 文件。 |
|||
|
|||
这些文件默认由 <abbr title="Content Delivery Network(内容分发网络): 由多台服务器为 JavaScript 和 CSS 等静态文件支持的服务。一般来说,从靠近客户端的服务器提供静态文件服务可以提高性能。">CDN</abbr> 提供支持服务。 |
|||
|
|||
但也可以自定义设置指定的 CDN 或自行提供文件服务。 |
|||
|
|||
这种做法很常用,例如,在没有联网或本地局域网时也能让应用在离线状态下正常运行。 |
|||
|
|||
本文介绍如何为 FastAPI 应用提供文件自托管服务,并设置文档使用这些文件。 |
|||
|
|||
### 项目文件架构 |
|||
|
|||
假设项目文件架构如下: |
|||
|
|||
``` |
|||
. |
|||
├── app |
|||
│ ├── __init__.py |
|||
│ ├── main.py |
|||
``` |
|||
|
|||
接下来,创建存储静态文件的文件夹。 |
|||
|
|||
新的文件架构如下: |
|||
|
|||
``` |
|||
. |
|||
├── app |
|||
│ ├── __init__.py |
|||
│ ├── main.py |
|||
└── static/ |
|||
``` |
|||
|
|||
### 下载文件 |
|||
|
|||
下载文档所需的静态文件,把文件放到 `static/` 文件夹里。 |
|||
|
|||
右键点击链接,选择**另存为...**。 |
|||
|
|||
**Swagger UI** 使用如下文件: |
|||
|
|||
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a> |
|||
* <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a> |
|||
|
|||
**ReDoc** 使用如下文件: |
|||
|
|||
* <a href="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a> |
|||
|
|||
保存好后,文件架构所示如下: |
|||
|
|||
``` |
|||
. |
|||
├── app |
|||
│ ├── __init__.py |
|||
│ ├── main.py |
|||
└── static |
|||
├── redoc.standalone.js |
|||
├── swagger-ui-bundle.js |
|||
└── swagger-ui.css |
|||
``` |
|||
|
|||
### 安装 `aiofiles` |
|||
|
|||
现在,安装 `aiofiles`: |
|||
|
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ pip install aiofiles |
|||
|
|||
---> 100% |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
### 静态文件服务 |
|||
|
|||
* 导入 `StaticFiles` |
|||
* 在指定路径下**挂载** `StaticFiles()` 实例 |
|||
|
|||
```Python hl_lines="7 11" |
|||
{!../../../docs_src/extending_openapi/tutorial002.py!} |
|||
``` |
|||
|
|||
### 测试静态文件 |
|||
|
|||
启动应用,打开 <a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js。</a> |
|||
|
|||
就能看到 **ReDoc** 的 JavaScript 文件。 |
|||
|
|||
该文件开头如下: |
|||
|
|||
```JavaScript |
|||
/*! |
|||
* ReDoc - OpenAPI/Swagger-generated API Reference Documentation |
|||
* ------------------------------------------------------------- |
|||
* Version: "2.0.0-rc.18" |
|||
* Repo: https://github.com/Redocly/redoc |
|||
*/ |
|||
!function(e,t){"object"==typeof exports&&"object"==typeof m |
|||
|
|||
... |
|||
``` |
|||
|
|||
能打开这个文件就表示 FastAPI 应用能提供静态文件服务,并且文档要调用的静态文件放到了正确的位置。 |
|||
|
|||
接下来,使用静态文件配置文档。 |
|||
|
|||
### 禁用 API 文档 |
|||
|
|||
第一步是禁用 API 文档,就是使用 CDN 的默认文档。 |
|||
|
|||
创建 `FastAPI` 应用时把文档的 URL 设置为 `None` 即可禁用默认文档: |
|||
|
|||
```Python hl_lines="9" |
|||
{!../../../docs_src/extending_openapi/tutorial002.py!} |
|||
``` |
|||
|
|||
### 添加自定义文档 |
|||
|
|||
现在,创建自定义文档的*路径操作*。 |
|||
|
|||
导入 FastAPI 内部函数为文档创建 HTML 页面,并把所需参数传递给这些函数: |
|||
|
|||
* `openapi_url`: API 文档获取 OpenAPI 概图的 HTML 页面,此处可使用 `app.openapi_url` |
|||
* `title`:API 的标题 |
|||
* `oauth2_redirect_url`:此处使用 `app.swagger_ui_oauth2_redirect_url` 作为默认值 |
|||
* `swagger_js_url`:Swagger UI 文档所需 **JavaScript** 文件的 URL,即为应用提供服务的文件 |
|||
* `swagger_css_url`:Swagger UI 文档所需 **CSS** 文件的 URL,即为应用提供服务的文件 |
|||
|
|||
添加 ReDoc 文档的方式与此类似…… |
|||
|
|||
```Python hl_lines="2-6 14-22 25-27 30-36" |
|||
{!../../../docs_src/extending_openapi/tutorial002.py!} |
|||
``` |
|||
|
|||
!!! tip "提示" |
|||
|
|||
`swagger_ui_redirect` 的*路径操作*是 OAuth2 的辅助函数。 |
|||
|
|||
集成 API 与 OAuth2 第三方应用时,您能进行身份验证,使用请求凭证返回 API 文档,并使用真正的 OAuth2 身份验证与 API 文档进行交互操作。 |
|||
|
|||
Swagger UI 在后台进行处理,但它需要这个**重定向**辅助函数。 |
|||
|
|||
### 创建测试*路径操作* |
|||
|
|||
现在,测试各项功能是否能顺利运行。创建*路径操作*: |
|||
|
|||
```Python hl_lines="39-41" |
|||
{!../../../docs_src/extending_openapi/tutorial002.py!} |
|||
``` |
|||
|
|||
### 测试文档 |
|||
|
|||
断开 WiFi 连接,打开 <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs,刷新页面。</a> |
|||
|
|||
现在,就算没有联网也能查看并操作 API 文档。 |
@ -1,244 +0,0 @@ |
|||
# 在 Deta 上部署 FastAPI |
|||
|
|||
本节介绍如何使用 <a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> 免费方案部署 **FastAPI** 应用。🎁 |
|||
|
|||
部署操作需要大约 10 分钟。 |
|||
|
|||
!!! info "说明" |
|||
|
|||
<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">Deta</a> 是 **FastAPI** 的赞助商。 🎉 |
|||
|
|||
## 基础 **FastAPI** 应用 |
|||
|
|||
* 创建应用文件夹,例如 `./fastapideta/`,进入文件夹 |
|||
|
|||
### FastAPI 代码 |
|||
|
|||
* 创建包含如下代码的 `main.py`: |
|||
|
|||
```Python |
|||
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): |
|||
return {"item_id": item_id} |
|||
``` |
|||
|
|||
### 需求项 |
|||
|
|||
在文件夹里新建包含如下内容的 `requirements.txt` 文件: |
|||
|
|||
```text |
|||
fastapi |
|||
``` |
|||
|
|||
!!! tip "提示" |
|||
|
|||
在 Deta 上部署时无需安装 Uvicorn,虽然在本地测试应用时需要安装。 |
|||
|
|||
### 文件夹架构 |
|||
|
|||
`./fastapideta/` 文件夹中现在有两个文件: |
|||
|
|||
``` |
|||
. |
|||
└── main.py |
|||
└── requirements.txt |
|||
``` |
|||
|
|||
## 创建免费 Deta 账号 |
|||
|
|||
创建<a href="https://www.deta.sh/?ref=fastapi" class="external-link" target="_blank">免费的 Deta 账号</a>,只需要电子邮件和密码。 |
|||
|
|||
甚至不需要信用卡。 |
|||
|
|||
## 安装 CLI |
|||
|
|||
创建账号后,安装 Deta <abbr title="Command Line Interface application">CLI</abbr>: |
|||
|
|||
=== "Linux, macOS" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ curl -fsSL https://get.deta.dev/cli.sh | sh |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
=== "Windows PowerShell" |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ iwr https://get.deta.dev/cli.ps1 -useb | iex |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
安装完 CLI 后,打开新的 Terminal,就能检测到刚安装的 CLI。 |
|||
|
|||
在新的 Terminal 里,用以下命令确认 CLI 是否正确安装: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta --help |
|||
|
|||
Deta command line interface for managing deta micros. |
|||
Complete documentation available at https://docs.deta.sh |
|||
|
|||
Usage: |
|||
deta [flags] |
|||
deta [command] |
|||
|
|||
Available Commands: |
|||
auth Change auth settings for a deta micro |
|||
|
|||
... |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
!!! tip "提示" |
|||
|
|||
安装 CLI 遇到问题时,请参阅 <a href="https://docs.deta.sh/docs/micros/getting_started?ref=fastapi" class="external-link" target="_blank">Deta 官档</a>。 |
|||
|
|||
## 使用 CLI 登录 |
|||
|
|||
现在,使用 CLI 登录 Deta: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta login |
|||
|
|||
Please, log in from the web page. Waiting.. |
|||
Logged in successfully. |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
这个命令会打开浏览器并自动验证身份。 |
|||
|
|||
## 使用 Deta 部署 |
|||
|
|||
接下来,使用 Deta CLI 部署应用: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta new |
|||
|
|||
Successfully created a new micro |
|||
|
|||
// Notice the "endpoint" 🔍 |
|||
|
|||
{ |
|||
"name": "fastapideta", |
|||
"runtime": "python3.7", |
|||
"endpoint": "https://qltnci.deta.dev", |
|||
"visor": "enabled", |
|||
"http_auth": "enabled" |
|||
} |
|||
|
|||
Adding dependencies... |
|||
|
|||
|
|||
---> 100% |
|||
|
|||
|
|||
Successfully installed fastapi-0.61.1 pydantic-1.7.2 starlette-0.13.6 |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
您会看到如下 JSON 信息: |
|||
|
|||
```JSON hl_lines="4" |
|||
{ |
|||
"name": "fastapideta", |
|||
"runtime": "python3.7", |
|||
"endpoint": "https://qltnci.deta.dev", |
|||
"visor": "enabled", |
|||
"http_auth": "enabled" |
|||
} |
|||
``` |
|||
|
|||
!!! tip "提示" |
|||
|
|||
您部署时的 `"endpoint"` URL 可能会有所不同。 |
|||
|
|||
## 查看效果 |
|||
|
|||
打开浏览器,跳转到 `endpoint` URL。本例中是 `https://qltnci.deta.dev`,但您的链接可能与此不同。 |
|||
|
|||
FastAPI 应用会返回如下 JSON 响应: |
|||
|
|||
```JSON |
|||
{ |
|||
"Hello": "World" |
|||
} |
|||
``` |
|||
|
|||
接下来,跳转到 API 文档 `/docs`,本例中是 `https://qltnci.deta.dev/docs`。 |
|||
|
|||
文档显示如下: |
|||
|
|||
<img src="/img/deployment/deta/image01.png"> |
|||
|
|||
## 启用公开访问 |
|||
|
|||
默认情况下,Deta 使用您的账号 Cookies 处理身份验证。 |
|||
|
|||
应用一切就绪之后,使用如下命令让公众也能看到您的应用: |
|||
|
|||
<div class="termy"> |
|||
|
|||
```console |
|||
$ deta auth disable |
|||
|
|||
Successfully disabled http auth |
|||
``` |
|||
|
|||
</div> |
|||
|
|||
现在,就可以把 URL 分享给大家,他们就能访问您的 API 了。🚀 |
|||
|
|||
## HTTPS |
|||
|
|||
恭喜!您已经在 Deta 上部署了 FastAPI 应用!🎉 🍰 |
|||
|
|||
还要注意,Deta 能够正确处理 HTTPS,因此您不必操心 HTTPS,您的客户端肯定能有安全加密的连接。 ✅ 🔒 |
|||
|
|||
## 查看 Visor |
|||
|
|||
从 API 文档(URL 是 `https://gltnci.deta.dev/docs`)发送请求至*路径操作* `/items/{item_id}`。 |
|||
|
|||
例如,ID `5`。 |
|||
|
|||
现在跳转至 <a href="https://web.deta.sh/" class="external-link" target="_blank">https://web.deta.sh。</a> |
|||
|
|||
左边栏有个 <abbr title="it comes from Micro(server)">"Micros"</abbr> 标签,里面是所有的应用。 |
|||
|
|||
还有一个 **Details** 和 **Visor** 标签,跳转到 **Visor** 标签。 |
|||
|
|||
在这里查看最近发送给应用的请求。 |
|||
|
|||
您可以编辑或重新使用这些请求。 |
|||
|
|||
<img src="/img/deployment/deta/image02.png"> |
|||
|
|||
## 更多内容 |
|||
|
|||
如果要持久化保存应用数据,可以使用提供了**免费方案**的 <a href="https://docs.deta.sh/docs/base/py_tutorial?ref=fastapi" class="external-link" target="_blank">Deta Base</a>。 |
|||
|
|||
详见 <a href="https://docs.deta.sh?ref=fastapi" class="external-link" target="_blank">Deta 官档</a>。 |
@ -1,83 +0,0 @@ |
|||
# 外部链接与文章 |
|||
|
|||
**FastAPI** 社区正在不断壮大。 |
|||
|
|||
有关 **FastAPI** 的帖子、文章、工具和项目越来越多。 |
|||
|
|||
以下是 **FastAPI** 各种资源的不完整列表。 |
|||
|
|||
!!! tip "提示" |
|||
|
|||
如果您的文章、项目、工具或其它任何与 **FastAPI** 相关的内容尚未收入此表,请在此创建 <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">PR</a>。 |
|||
|
|||
## 文章 |
|||
|
|||
### 英文 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.articles.english %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
### 日文 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.articles.japanese %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
### 越南语 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.articles.vietnamese %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
### 俄语 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.articles.russian %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
### 德语 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.articles.german %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
## 播客 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.podcasts.english %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
## 访谈 |
|||
|
|||
{% if external_links %} |
|||
{% for article in external_links.talks.english %} |
|||
|
|||
* <a href="{{ article.link }}" class="external-link" target="_blank">{{ article.title }}</a> by <a href="{{ article.author_link }}" class="external-link" target="_blank">{{ article.author }}</a>. |
|||
{% endfor %} |
|||
{% endif %} |
|||
|
|||
## 项目 |
|||
|
|||
GitHub 上最新的 `fastapi` 主题项目: |
|||
|
|||
<div class="github-topic-projects"> |
|||
</div> |
Loading…
Reference in new issue