コンテンツにスキップ

HTTPリクエスト総論#

2024 iThome鉄人レース

これはDjango Ninjaシリーズチュートリアルの第9回です。

第3章第2節へようこそ!

APIのコアロジックの実装として、view関数は間違いなくDjango Ninja APIの魂と言える部分です。

Django Ninjaは、FastAPIやFlaskと同様に、主にfunction-based views(以下、FBVsと略します)を採用しています。そのため、学習の焦点はほとんどすべてview関数のinputとoutputの周りに集中します。

言い換えれば、Django Ninjaフレームワーク全体の能力は、view関数のこれらの重要な部分を構成しているのです。これには以下のようなものが含まれます(ただしこれらに限定されません)。

  1. HTTPリクエストのパラメータとbodyの処理。
  2. HTTPレスポンス内容のシリアライズとフォーマット。
  3. データ検証とエラー処理。

これらが共同してDjango Ninjaの主な機能を構成しています。

本節と次節では、上記の3つのポイントのうち、最初の2つ(リクエストとレスポンス)について集中的に議論します。3つ目のポイントについては、第5章で紹介するために残しておきます。

GitHubサンプルプロジェクト#

👉 Django-Ninja-Tutorial


この節のガイド#

前節の「ルーティング」に続き、本節ではDjango NinjaがどのようにHTTPリクエストを処理するか、つまりpath、URLクエリパラメータ、そしてbodyをどのように解析するかについて探求します。

本節は全4回の記事で構成されています。

さらに、view関数によるリクエスト処理機能は、Django Ninjaが型ヒント(型ヒント)をどのように使用してリクエストデータを検証するかに関わってくるため、サンプルコードにはPythonの型ヒントを追加し始めます

Type hintsの構文はPython 3.12に準拠しています。

公式ドキュメント#

本シリーズの執筆では、「Django Ninja公式ドキュメント」、特にアーキテクチャの表現について随時参考にしています。

しかし、ドキュメントはあくまで全体の開発者向けに書かれたものであり、学習の順序までは十分に考慮されていません。

一方で、本シリーズは主に入門者を対象としているため、実際の実装や入門者のニーズにより重きを置き、適宜背景知識を補足することで、学習曲線が比較的緩やかになるよう努めています

また、フレームワーク自体に関しても、より多くの実例や説明を提供し、新しい概念を理解しやすく、習得しやすいようにしています。

とはいえ、公式ドキュメントはDjango Ninjaを使用する際に常に参照すべき内容です(DjangoやDjango REST frameworkのドキュメントと比べると、比較的「簡単」に書かれていますが!)。


この記事の目的#

本記事は第2節の概論として、Django Ninjaのview関数とそれがHTTPリクエストをどのように処理するかについて基本的な理解を持ってもらうことを目標としています。

以下の3つの重点を通じて、段階的に慣れていただけるようにします。

  1. FBVsのメリット。
  2. Django NinjaによるHTTPリクエストの処理フロー。
  3. Django Ninjaと型ヒントの密接な結合。

前置きはこれくらいにして、早速始めましょう。


Class-based views(CBVs)とFBVsは、どちらもDjango MTVアーキテクチャにおけるViewsを実現する手段であり、それぞれに適した用途があります。

CBVsにはコードの再利用という強みがあり、大規模なプロジェクトに適しています。一方、FBVsはシンプルかつ直接的であることを売りにしており、中小規模のプロジェクトの迅速な開発に便利です。

両者の比較については、こちらの記事〈Day27 : CBV vs. FBV〉を参考にしてください。

Django NinjaはFBVsを採用しているため、本記事ではFBVsのメリットのみを探求します。

一、FBVのメリット#

FBVsはDjango Ninjaが採用しているviewの形式です。CBVsと比較して、FBVsはより簡潔で柔軟性があり、開発者がAPIロジックを簡単に書くことができます。「あるCBVの属性をどうやって正しくオーバーライドするか」といった、背景知識をあまり知る必要はありません

簡潔さと柔軟性#

FBVsは、クラスメソッドを継承したりオーバーライドしたりする必要がなく、すべてのロジックが1つの関数に集中しています。

これにより、コードの記述やメンテナンスがより直感的になります。

FBVsは本質的に関数であるため、様々なロジックや条件をより柔軟に適用でき、開発者はクラスの構造や継承関係を考慮することなく単一の関数内でリクエストの処理フロー全体を完全に制御できます。

デバッグのしやすさ#

FBVsのコードは比較的直感的であり、初心者にとっても読んで理解するのがより容易です。エラーが発生した際、問題を素早く特定でき、これはCBVsでは達成しにくい利便性です。

私の見解#

Djangoは機能が充実したフレームワークですが、「重たすぎる」と批判されることもよくあります。FBVsはある程度、この重厚感を和らげてくれます

少し考えてみてください。Djangoに触れたばかりの初心者が、様々なフレームワークの環境設定を理解した後に、さらにCBVsの世界を深く掘り下げるのは、あまりにも負担が大きすぎないでしょうか?

とにかく、もし私に尋ねるなら、私は絶対にFBVsを好みます。それに、「軽量化」は現代の開発におけるトレンドでもあります。


二、Django NinjaによるHTTPリクエストの処理フロー#

Django Ninjaによる「リクエスト」の処理は、いくつかの重要なステップに分けることができます。

  1. ルーティングの照合:リクエストが来たとき、フレームワークはまず送信元URLを定義されたパスのルール(エンドポイント)と照合します。照合に成功した場合、HTTPリクエストと関連パラメータをview関数に渡します。
  2. パラメータの解析:URLからパスパラメータpath parameters)とクエリパラメータquery parameters)を抽出し、それらをview関数の「引数」(arguments)に変換します。関数の型ヒントに基づいて、自動的に型変換と検証が行われます。
  3. Request bodyの処理:POSTやPUTなどのbodyを伴うリクエストに対して、Django Ninjaは開発者がスキーマ(Pydantic BaseModel)を使用してbodyのデータモデルを定義できるようにし、入力されたデータをこれらのモデルに自動的に対応させます。

Django NinjaによるHTTPリクエストの処理フロー

上記の第1のポイントは、本章第1節で詳細に説明しました。

第2および第3のポイントは、本節の全4回の記事の主要な内容となります。


三、Django Ninjaと型ヒントの密接な結合#

Django Ninjaは、HTTPリクエスト内のデータを処理する際に、Pythonの型ヒントに非常に大きく依存しています。

そしてPydanticを通じて、自動データ検証型変換を実現し、開発者が手動でデータをチェックしたり変換したりする負担を軽減しています。

例えば以下のコードです。

@router.get("/posts/{post_id}")
def get_post(request, post_id: int):
    return {"post_id": post_id}

post_idパラメータにintという型が指定されているとき、Django Ninjaは型チェックを行います。入力されたパラメータがintに変換できない場合、フレームワークは直接ステータスコード422のHTTPレスポンスを返します。

言い換えれば、もしpost_idstrを指定すれば、Django Ninjaは自動的にpost_idを文字列に変換します。

Django Ninjaに初めて触れたとき、Pythonの型ヒントをここまで活用できることに非常に驚いたのを覚えています。それが単なる型安全のためだけでなく、API開発プロセス全体に組み込まれていたからです。

view関数におけるrequestパラメータ#

上の例には、注目すべき詳細があります。それはview関数の第一引数であるrequestです。

Djangoにおいて、view関数の第一引数は必ずrequestになります。このパラメータの名称は自由に定義できますが、通常はrequestと命名されます。

HTTPリクエストを受け取ると、Djangoはリクエスト全体を1つのHttpRequestオブジェクトにパッケージ化し、それを第一引数としてview関数に渡すため、これは不可欠なものです。

関連記事:Django HttpRequestのよく使う属性の紹介

requestパラメータは、DjangoおよびDjango REST frameworkにおいて非常に重要です。なぜなら、リクエストのクエリパラメータやbodyなどを取得するためによく使用されるからです。

Django Ninjaでは、これらのデータは関数の引数を通じて直接取得できるため、requestは依然として不可欠ですが、使用頻度は低くなります


次へのステップ#

次に、Django Ninjaがリクエストを処理する具体的な詳細を深く掘り下げていきます。

次回はパスパラメータpath parameters)に焦点を当て、Djangoネイティブのpath convertersと組み合わせて使用する方法を探ります。お楽しみに!