Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🌐 Add Chinese translation for docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md #4971

Merged
247 changes: 247 additions & 0 deletions docs/zh/docs/tutorial/dependencies/classes-as-dependencies.md
@@ -0,0 +1,247 @@
# 类作为依赖项

在深入探究 **依赖注入** 系统之前,让我们升级之前的例子。

## 来自前一个例子的`dict`

在前面的例子中, 我们从依赖项 ("可依赖对象") 中返回了一个 `dict`:

=== "Python 3.6 以及 以上"

```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```

=== "Python 3.10 以及以上"

```Python hl_lines="7"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```

但是后面我们在路径操作函数的参数 `commons` 中得到了一个 `dict`

我们知道编辑器不能为 `dict` 提供很多支持(比如补全),因为编辑器不知道 `dict` 的键和值类型。

对此,我们可以做的更好...

## 什么构成了依赖项?

到目前为止,您看到的依赖项都被声明为函数。

但这并不是声明依赖项的唯一方法(尽管它可能是更常见的方法)。

关键因素是依赖项应该是 "可调用对象"。

Python 中的 "**可调用对象**" 是指任何 Python 可以像函数一样 "调用" 的对象。

所以,如果你有一个对象 `something` (可能*不是*一个函数),你可以 "调用" 它(执行它),就像:

```Python
something()
```

或者

```Python
something(some_argument, some_keyword_argument="foo")
```

这就是 "可调用对象"。

## 类作为依赖项

您可能会注意到,要创建一个 Python 类的实例,您可以使用相同的语法。

举个例子:

```Python
class Cat:
def __init__(self, name: str):
self.name = name


fluffy = Cat(name="Mr Fluffy")
```

在这个例子中, `fluffy` 是一个 `Cat` 类的实例。

为了创建 `fluffy`,你调用了 `Cat`

所以,Python 类也是 **可调用对象**

因此,在 **FastAPI** 中,你可以使用一个 Python 类作为一个依赖项。

实际上 FastAPI 检查的是它是一个 "可调用对象"(函数,类或其他任何类型)以及定义的参数。

如果您在 **FastAPI** 中传递一个 "可调用对象" 作为依赖项,它将分析该 "可调用对象" 的参数,并以处理路径操作函数的参数的方式来处理它们。包括子依赖项。

这也适用于完全没有参数的可调用对象。这与不带参数的路径操作函数一样。

所以,我们可以将上面的依赖项 "可依赖对象" `common_parameters` 更改为类 `CommonQueryParams`:

=== "Python 3.6 以及 以上"

```Python hl_lines="11-15"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```

=== "Python 3.10 以及 以上"

```Python hl_lines="9-13"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```

注意用于创建类实例的 `__init__` 方法:

=== "Python 3.6 以及 以上"

```Python hl_lines="12"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```

=== "Python 3.10 以及 以上"

```Python hl_lines="10"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```

...它与我们以前的 `common_parameters` 具有相同的参数:

=== "Python 3.6 以及 以上"

```Python hl_lines="9"
{!> ../../../docs_src/dependencies/tutorial001.py!}
```

=== "Python 3.10 以及 以上"

```Python hl_lines="6"
{!> ../../../docs_src/dependencies/tutorial001_py310.py!}
```

这些参数就是 **FastAPI** 用来 "处理" 依赖项的。

在两个例子下,都有:

* 一个可选的 `q` 查询参数,是 `str` 类型。
* 一个 `skip` 查询参数,是 `int` 类型,默认值为 `0`
* 一个 `limit` 查询参数,是 `int` 类型,默认值为 `100`

在两个例子下,数据都将被转换、验证、在 OpenAPI schema 上文档化,等等。

## 使用它

现在,您可以使用这个类来声明你的依赖项了。

=== "Python 3.6 以及 以上"

```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial002.py!}
```

=== "Python 3.10 以及 以上"

```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial002_py310.py!}
```

**FastAPI** 调用 `CommonQueryParams` 类。这将创建该类的一个 "实例",该实例将作为参数 `commons` 被传递给你的函数。

## 类型注解 vs `Depends`

注意,我们在上面的代码中编写了两次`CommonQueryParams`

```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```

最后的 `CommonQueryParams`:

```Python
... = Depends(CommonQueryParams)
```

...实际上是 **Fastapi** 用来知道依赖项是什么的。

FastAPI 将从依赖项中提取声明的参数,这才是 FastAPI 实际调用的。

---

在本例中,第一个 `CommonQueryParams`

```Python
commons: CommonQueryParams ...
```

...对于 **FastAPI** 没有任何特殊的意义。FastAPI 不会使用它进行数据转换、验证等 (因为对于这,它使用 `= Depends(CommonQueryParams)`)。

你实际上可以只这样编写:

```Python
commons = Depends(CommonQueryParams)
```

..就像:

=== "Python 3.6 以及 以上"

```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial003.py!}
```

=== "Python 3.10 以及 以上"

```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial003_py310.py!}
```

但是声明类型是被鼓励的,因为那样你的编辑器就会知道将传递什么作为参数 `commons` ,然后它可以帮助你完成代码,类型检查,等等:

<img src="/img/tutorial/dependencies/image02.png">

## 快捷方式

但是您可以看到,我们在这里有一些代码重复了,编写了`CommonQueryParams`两次:

```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```

**FastAPI** 为这些情况提供了一个快捷方式,在这些情况下,依赖项 *明确地* 是一个类,**FastAPI** 将 "调用" 它来创建类本身的一个实例。

对于这些特定的情况,您可以跟随以下操作:

不是写成这样:

```Python
commons: CommonQueryParams = Depends(CommonQueryParams)
```

...而是这样写:

```Python
commons: CommonQueryParams = Depends()
```

您声明依赖项作为参数的类型,并使用 `Depends()` 作为该函数的参数的 "默认" 值(在 `=` 之后),而在 `Depends()` 中没有任何参数,而不是在 `Depends(CommonQueryParams)` 编写完整的类。

同样的例子看起来像这样:

=== "Python 3.6 以及 以上"

```Python hl_lines="19"
{!> ../../../docs_src/dependencies/tutorial004.py!}
```

=== "Python 3.10 以及 以上"

```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial004_py310.py!}
```

... **FastAPI** 会知道怎么处理。

!!! tip
如果这看起来更加混乱而不是更加有帮助,那么请忽略它,你不*需要*它。

这只是一个快捷方式。因为 **FastAPI** 关心的是帮助您减少代码重复。
1 change: 1 addition & 0 deletions docs/zh/mkdocs.yml
Expand Up @@ -89,6 +89,7 @@ nav:
- tutorial/body-updates.md
- 依赖项:
- tutorial/dependencies/index.md
- tutorial/dependencies/classes-as-dependencies.md
- tutorial/dependencies/sub-dependencies.md
- tutorial/dependencies/dependencies-in-path-operation-decorators.md
- tutorial/dependencies/global-dependencies.md
Expand Down