まえがき
先日Django-Ninjaでバリデーションエラーをハンドリングする記事を書きました。
その記事の一番最後で、
これ書いている途中で色々試してたら、Python組み込みの型の名前を レスポンスしなくちゃいけないときとかどうしよう って悩みが生まれてしまいました。
listっていうキーを含んだJSONをレスポンスしたいけど、Schemaでlistっていうフィールド名は使っちゃまずいし。
aliasをFieldに設定してみたけど、思ってた挙動とは違ったし。
どうしよう。わかんない。 誰か教えてほしい。
ていう疑問を書いてたんですけど、Django-NinjaのGitHubを読んでたら解決方法が載っていたので、早速試す。
解決策
by_alias=True
を指定してあげるといいみたいです。
Django-Ninjaの内側(?)で動いているPydanticは、デフォルトではby_alias
はFalseなんだそう(当然か)。
実装
実装方法は2パターン見つけました。
1つは全体に作用する方法で、もう一つはViews.pyで定義する関数別に設定する方法。
それと、もう一つRouterクラス別に一括で設定する方法もあるみたいです。
それについては参考にしたIssueを見てみてください……。
レスポンスSchema
class TestOut(Schema):
id: int = Field(
description="ID",
)
str_: str | None = Field( # フィールド名は`str_`
alias="str", # aliasは`str`
description="your message.",
)
1つめ
全体に作用するものです。
urls.pyでURLにAPIを渡す際に、API全体の(APIに含まれる全Routerの?)by_aliasをTrueにする。
api = NinjaAPI(renderer=ORJSONRenderer())
def set_all_by_alias(api):
for _pth, router in api._routers:
for view in router.path_operations.values():
for op in view.operations:
op.by_alias = True
set_all_by_alias(api)
2つめ
個別に作用するものです。
Views.pyで@router.get()
を使う際に、by_aliasをTrueにする。
GitHubでは@router.get()
でサンプルコードが書かれていたんですけど、手元で試したらapi.get("", by_alias=True)
でも大丈夫でした。
Django-Ninjaを見てみるとdefault_routerというものがNinjaAPIの内側にあるようなので、それが勝手に使用されているのかな。
(適当言ってます。api.get()
とapi.default_router.get()
は同じなのかな。)
@api.get("", by_alias=True)
def test(request, parameters: Query[TestIn]):
return {
"id": parameters.id,
"str": parameters.value, # レスポンスのdictではキーにaliasの方を使用してる!
}
結果
こうなりました。
ちゃんとaliasが効いてレスポンスのキーがstrになってる。
by_alias=Falseの状態
フィールド名に使用しているstr_
(アンダースコアが付いてます)がそのまま返っていますね。
これが嫌でなんとかaliasをレスポンスに使えないかなと悩んでました。
{"id":1,"str_":"!!TESTING!!"}
by_alias=Trueの状態
ちゃんとaliasで定義したstr
がレスポンスに使われてます。
やったあ。
{"id":1,"str":"!!TESTING!!"}
あとがき
意外と単純でした。
少し躓いたのは、Views.pyでreturnするdictのキーをaliasで定義した名前にしなくちゃいけないところです。
これをしないでフィールド名のほうをキーに使用すると、レスポンスSchemaでバリデーションエラーが起きちゃいました。
GitHubというか、モジュール自体の実装やIssues, Discussionsを見ることって大切だなって思いました。
私なんかが悩んでることって、当然他の誰かも悩んでいますよね。そりゃ。
矮小な悩みすぎて私以外悩んでいない場合もありそうですけど……。
テストコードを書いた経験が少なくて、pytestのmockとかfixtureとか、あとtoxあたり(toxってなに)が全然わからない。
それが超直近の悩みです。仕事上の。
そんなかんじです。悩んでばかりだ。
じゃあね。
参考