mirror of https://github.com/tiangolo/fastapi.git
🌐 Add Japanese translation for `docs/ja/docs/tutorial/extra-models.md` (#1941)
Co-authored-by: ryusuke.miyaji <bluce826@gmail.com> Co-authored-by: ryuckel <36391432+ryuckel@users.noreply.github.com> Co-authored-by: tokusumi <tksmtoms@gmail.com> Co-authored-by: T. Tokusumi <41147016+tokusumi@users.noreply.github.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
79dbb11867
commit
c238292b44
|
|
@ -0,0 +1,195 @@
|
||||||
|
# モデル - より詳しく
|
||||||
|
|
||||||
|
先ほどの例に続き、複数の関連モデルを持つことが一般的です。
|
||||||
|
|
||||||
|
これはユーザーモデルの場合は特にそうです。なぜなら:
|
||||||
|
|
||||||
|
* **入力モデル** にはパスワードが必要です。
|
||||||
|
* **出力モデル**はパスワードをもつべきではありません。
|
||||||
|
* **データベースモデル**はおそらくハッシュ化されたパスワードが必要になるでしょう。
|
||||||
|
|
||||||
|
!!! danger "危険"
|
||||||
|
ユーザーの平文のパスワードは絶対に保存しないでください。常に認証に利用可能な「安全なハッシュ」を保存してください。
|
||||||
|
|
||||||
|
知らない方は、[セキュリティの章](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}で「パスワードハッシュ」とは何かを学ぶことができます。
|
||||||
|
|
||||||
|
## 複数のモデル
|
||||||
|
|
||||||
|
ここでは、パスワードフィールドをもつモデルがどのように見えるのか、また、どこで使われるのか、大まかなイメージを紹介します:
|
||||||
|
|
||||||
|
```Python hl_lines="9 11 16 22 24 29-30 33-35 40-41"
|
||||||
|
{!../../../docs_src/extra_models/tutorial001.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `**user_in.dict()`について
|
||||||
|
|
||||||
|
#### Pydanticの`.dict()`
|
||||||
|
|
||||||
|
`user_in`は`UserIn`クラスのPydanticモデルです。
|
||||||
|
|
||||||
|
Pydanticモデルには、モデルのデータを含む`dict`を返す`.dict()`メソッドがあります。
|
||||||
|
|
||||||
|
そこで、以下のようなPydanticオブジェクト`user_in`を作成すると:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
user_in = UserIn(username="john", password="secret", email="john.doe@example.com")
|
||||||
|
```
|
||||||
|
|
||||||
|
そして呼び出すと:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
user_dict = user_in.dict()
|
||||||
|
```
|
||||||
|
|
||||||
|
これで変数`user_dict`のデータを持つ`dict`ができました。(これはPydanticモデルのオブジェクトの代わりに`dict`です)。
|
||||||
|
|
||||||
|
そして呼び出すと:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
print(user_dict)
|
||||||
|
```
|
||||||
|
|
||||||
|
以下のようなPythonの`dict`を得ることができます:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
{
|
||||||
|
'username': 'john',
|
||||||
|
'password': 'secret',
|
||||||
|
'email': 'john.doe@example.com',
|
||||||
|
'full_name': None,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `dict`の展開
|
||||||
|
|
||||||
|
`user_dict`のような`dict`を受け取り、それを`**user_dict`を持つ関数(またはクラス)に渡すと、Pythonはそれを「展開」します。これは`user_dict`のキーと値を直接キー・バリューの引数として渡します。
|
||||||
|
|
||||||
|
そこで上述の`user_dict`の続きを以下のように書くと:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
UserInDB(**user_dict)
|
||||||
|
```
|
||||||
|
|
||||||
|
以下と同等の結果になります:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
UserInDB(
|
||||||
|
username="john",
|
||||||
|
password="secret",
|
||||||
|
email="john.doe@example.com",
|
||||||
|
full_name=None,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
もっと正確に言えば、`user_dict`を将来的にどんな内容であっても直接使用することになります:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
UserInDB(
|
||||||
|
username = user_dict["username"],
|
||||||
|
password = user_dict["password"],
|
||||||
|
email = user_dict["email"],
|
||||||
|
full_name = user_dict["full_name"],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 別のモデルからつくるPydanticモデル
|
||||||
|
|
||||||
|
上述の例では`user_in.dict()`から`user_dict`をこのコードのように取得していますが:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
user_dict = user_in.dict()
|
||||||
|
UserInDB(**user_dict)
|
||||||
|
```
|
||||||
|
|
||||||
|
これは以下と同等です:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
UserInDB(**user_in.dict())
|
||||||
|
```
|
||||||
|
|
||||||
|
...なぜなら`user_in.dict()`は`dict`であり、`**`を付与して`UserInDB`を渡してPythonに「展開」させているからです。
|
||||||
|
|
||||||
|
そこで、別のPydanticモデルのデータからPydanticモデルを取得します。
|
||||||
|
|
||||||
|
#### `dict`の展開と追加引数
|
||||||
|
|
||||||
|
そして、追加のキーワード引数`hashed_password=hashed_password`を以下のように追加すると:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
UserInDB(**user_in.dict(), hashed_password=hashed_password)
|
||||||
|
```
|
||||||
|
|
||||||
|
...以下のようになります:
|
||||||
|
|
||||||
|
```Python
|
||||||
|
UserInDB(
|
||||||
|
username = user_dict["username"],
|
||||||
|
password = user_dict["password"],
|
||||||
|
email = user_dict["email"],
|
||||||
|
full_name = user_dict["full_name"],
|
||||||
|
hashed_password = hashed_password,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! warning "注意"
|
||||||
|
サポートしている追加機能は、データの可能な流れをデモするだけであり、もちろん本当のセキュリティを提供しているわけではありません。
|
||||||
|
|
||||||
|
## 重複の削減
|
||||||
|
|
||||||
|
コードの重複を減らすことは、**FastAPI**の中核的なアイデアの1つです。
|
||||||
|
|
||||||
|
コードの重複が増えると、バグやセキュリティの問題、コードの非同期化問題(ある場所では更新しても他の場所では更新されない場合)などが発生する可能性が高くなります。
|
||||||
|
|
||||||
|
そして、これらのモデルは全てのデータを共有し、属性名や型を重複させています。
|
||||||
|
|
||||||
|
もっと良い方法があります。
|
||||||
|
|
||||||
|
他のモデルのベースとなる`UserBase`モデルを宣言することができます。そして、そのモデルの属性(型宣言、検証など)を継承するサブクラスを作ることができます。
|
||||||
|
|
||||||
|
データの変換、検証、文書化などはすべて通常通りに動作します。
|
||||||
|
|
||||||
|
このようにして、モデル間の違いだけを宣言することができます:
|
||||||
|
|
||||||
|
```Python hl_lines="9 15 16 19 20 23 24"
|
||||||
|
{!../../../docs_src/extra_models/tutorial002.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
## `Union`または`anyOf`
|
||||||
|
|
||||||
|
レスポンスを2つの型の`Union`として宣言することができます。
|
||||||
|
|
||||||
|
OpenAPIでは`anyOf`で定義されます。
|
||||||
|
|
||||||
|
そのためには、標準的なPythonの型ヒント<a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>を使用します:
|
||||||
|
|
||||||
|
```Python hl_lines="1 14 15 18 19 20 33"
|
||||||
|
{!../../../docs_src/extra_models/tutorial003.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
## モデルのリスト
|
||||||
|
|
||||||
|
同じように、オブジェクトのリストのレスポンスを宣言することができます。
|
||||||
|
|
||||||
|
そのためには、標準のPythonの`typing.List`を使用する:
|
||||||
|
|
||||||
|
```Python hl_lines="1 20"
|
||||||
|
{!../../../docs_src/extra_models/tutorial004.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 任意の`dict`を持つレスポンス
|
||||||
|
|
||||||
|
また、Pydanticモデルを使用せずに、キーと値の型だけを定義した任意の`dict`を使ってレスポンスを宣言することもできます。
|
||||||
|
|
||||||
|
これは、有効なフィールド・属性名(Pydanticモデルに必要なもの)を事前に知らない場合に便利です。
|
||||||
|
|
||||||
|
この場合、`typing.Dict`を使用することができます:
|
||||||
|
|
||||||
|
```Python hl_lines="1 8"
|
||||||
|
{!../../../docs_src/extra_models/tutorial005.py!}
|
||||||
|
```
|
||||||
|
|
||||||
|
## まとめ
|
||||||
|
|
||||||
|
複数のPydanticモデルを使用し、ケースごとに自由に継承します。
|
||||||
|
|
||||||
|
エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password` や `password_hash` やパスワードなしなどのいくつかの「状態」をもつユーザー「エンティティ」の場合の様にすれば良いです。
|
||||||
Loading…
Reference in New Issue