2026年11月8日、DjangoでFastAPIのような書き方でAPIを作れるライブラリDjango Ninjaの1.8.0が公開されました。11月5日のベータ版1.8.0b1を経ての正式版です。
今回の目玉は、Webhookで送るデータの形を、OpenAPIと呼ばれるAPIの説明書に書けるようになったことです。また、省略できる検索条件をまとめたスキーマが、何も送られなかったときに、エラーではなくNoneになるよう直されました。
ほかにも、動きが変わる点がいくつか挙げられています。今回は、1.7.3と1.8.0で同じAPIを動かしながら、何が変わったのかを見ていきます。
まずはDjango Ninjaとはどんなものか¶
最初に、Django Ninjaを知らない方のために、どんなライブラリなのかを簡単に紹介します。Django Ninjaは、DjangoでAPIを作るための追加のライブラリです。
APIとは、プログラム同士がデータをやりとりするための窓口のことです。Django Ninjaでは、型ヒントを書くだけで、受け取るデータの検証や、APIの説明書の作成までを自動で行ってくれます。
最小のAPIを動かしてみた¶
まずは、どんな書き方なのかを見ておきましょう。商品の名前と値段を受け取って、登録したことにするだけの小さなAPIです。
from ninja import NinjaAPI, Schema
api = NinjaAPI()
class Item(Schema):
name: str
price: int
@api.post("/items")
def create_item(request, item: Item):
return {"message": f"{item.name}を{item.price}円で登録しました"}
1.8.0を入れた仮想環境で、テスト用のClientから、正しいデータと、値段に文字を入れたデータを送ってみました。
200 {'message': 'りんごを120円で登録しました'}
422 Input should be a valid integer, unable to parse string as an integer
値段に安いという文字を送ると、整数ではないという422のエラーが自動で返りました。型ヒントを書くだけで、受け取るデータの検証まで済むのが、このライブラリの持ち味です。
FastAPIとの関係¶
型ヒントで受け取るデータを決める書き方は、FastAPIとよく似ています。どちらも、データの検証にPydanticというライブラリを使っています。
| 項目 | FastAPI | Django Ninja |
|---|---|---|
| 土台 | Starlette | Django |
| データの検証 | Pydantic | Pydantic |
| APIの説明書 | OpenAPIを自動で作成 | OpenAPIを自動で作成 |
| 向いている場面 | APIだけの新しいサービス | Djangoの管理画面やORMをそのまま使いたいとき |
すでにDjangoで作ったサイトに、APIを足したいときに便利な選択肢です。FastAPIについては、こちらで紹介しています。【関連記事】PythonのFastAPIとは?
Djangoそのものの基本は、こちらで紹介しています。【関連記事】PythonのDjangoとは?
1.8で何が変わったのかを整理しよう¶
続いて、1.8.0の主な変更を表にまとめます。内容は、Django NinjaのGitHubにある1.8.0のリリースノートにもとづいています。
| 分類 | 主な変更 |
|---|---|
| 新機能 | Webhookで送るデータの形を、OpenAPIの説明書に書ける |
| 新機能 | ドキュメントを、Quick Start、Tutorial、Guide、Aboutに整理 |
| 改善 | 省略できるスキーマの検索条件が、何も送られないときNoneに |
| 改善 | ファイルと一緒に送られた値を、型に合わせて読むように |
| 対応範囲 | Python 3.15を、Django 5.2、6.0、6.1と組み合わせて検証 |
ドキュメントの整理では、TaskFlowという作業管理アプリを8回に分けて作るチュートリアルが加わりました。AIのアシスタントが読みやすいように、llms.txtというファイルも用意されています。
リリースノートには、Python、Django、Pydanticの最低限の版が変わったという記載はありませんでした。Python 3.15で動かしたい方には、嬉しい知らせです。
省略できる検索条件が、422にならなくなった¶
まずは、多くの人に関係しそうな修正から見ていきましょう。検索のAPIでは、カテゴリーや値段の範囲などの条件を、1つのスキーマにまとめて受け取ることがよくあります。
リリースノートによると、こうした省略できるスキーマを、QueryやHeader、Formの引数として使ったとき、どの項目も送られなかった場合は、既定値が使われるようになりました。これまでは、422のエラーになることがあったそうです。
1.7.3と1.8.0で試してみた¶
実際に試してみましょう。カテゴリーを必須、最低価格を省略できる項目にした検索条件のスキーマを、まるごと省略できる形で受け取るAPIを作りました。
from ninja import NinjaAPI, Query, Schema
api = NinjaAPI()
class Filters(Schema):
category: str
min_price: int = 0
@api.get("/products")
def products(request, filters: Filters | None = Query(None)):
return {"filters": filters.dict() if filters else None}
Django 5.2と組み合わせ、1.7.3と1.8.0をそれぞれ新しい仮想環境に入れて、テスト用のClientから呼び出しました。手元のPython 3.11で実行した結果です。
django-ninja 1.7.3
/api/products 422 {"detail": [{"type": "missing", "loc": ["query", "category"], "msg": "Field required"}]}
/api/products?category=fruit 200 {"filters": {"category": "fruit", "min_price": 0}}
django-ninja 1.8.0
/api/products 200 {"filters": null}
/api/products?category=fruit 200 {"filters": {"category": "fruit", "min_price": 0}}
1.7.3では、条件をまるごと省略したつもりなのに、categoryが足りないという422のエラーになりました。1.8.0では、省略されたものとしてNoneが渡され、ふつうに200で応答しています。
すべての項目に既定値があるときは¶
ちなみに、categoryにも既定値を付けて同じことを試すと、1.7.3では{"category": "all", "min_price": 0}と、既定値の入ったスキーマが渡されました。1.8.0では、この場合もNoneになりました。
つまり1.8.0では、何も送られなかったときは、中身の既定値ではなく、引数の既定値のNoneが使われるようになったわけです。既定値の入ったスキーマを前提にしていたコードは、上げたあとに確かめておきましょう。
Webhookの形を、説明書に書けるようになった¶
続いて、新機能のWebhookです。Webhookとは、何かが起きたときに、こちらから相手のサーバーへ通知を送る仕組みのことです。
たとえば、注文の支払いが終わったら、取引先のシステムへお知らせを送る、といった使い方をします。送る側は、どんな形のデータを送るのかを、相手に伝えておく必要があります。
試しに書いてみた¶
リリースノートによると、@api.webhookをスキーマのクラスに付けると、そのデータの形が、OpenAPI 3.1の説明書のwebhooksという欄に書かれます。実際に試してみました。
@api.webhook("order.paid")
class OrderPaid(Schema):
"""注文の支払いが終わったときに送る通知"""
order_id: int
amount: int
1.8.0で、作られた説明書のwebhooksの欄を取り出した結果です。一部を短くしています。
"order.paid": {
"post": {
"summary": "Order Paid",
"requestBody": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/OrderPaid"}
...
1.7.3では、webhookという機能がまだないので、AttributeErrorになりました。リリースノートには、これは説明書を書くための機能で、Django Ninjaが実際に通知を送るわけではない、とも明記されています。
送る処理そのものは、requestsなどで自分で書く必要があります。【関連記事】Pythonのrequestsとは?
動きが変わる点¶
リリースノートには、上げると動きが変わる点も、まとめて書かれています。初心者にも関係しそうなものを表にまとめます。
| 変更 | 中身 |
|---|---|
| ModelSchemaの並び順 | モデルの項目が先、自分で足した項目が後になり、応答のキーの順番が変わる |
| 二重の指定 | 自分で定義した項目をMeta.fieldsにも並べると、DeprecationWarningが出る |
| 外部キーの型 | to_fieldで文字列の項目を指定した外部キーは、文字列として扱われる |
| 空になりうる関係 | null=Trueの外部キーなどは、スキーマでもOptionalになる |
| 設定の削除 | NINJA_PAGINATION_MAX_OFFSETがなくなり、残っていても無視される |
ModelSchemaとは、Djangoのモデルから、APIで使うスキーマを自動で作る仕組みです。応答のキーの順番に頼ったテストがある場合は、上げたあとに失敗するかもしれません。
警告は、将来のエラーの予告¶
2つ目の二重の指定について、リリースノートには、将来はConfigErrorというエラーになる予定だと書かれています。今のうちに警告を直しておくと、次の版で慌てずに済みます。
Pydanticでの型の扱いについては、こちらで紹介しています。【関連記事】Pydantic v2とは?
上げる前にやっておきたいこと¶
最後に、Django Ninjaを1.8.0へ上げる前に確かめておきたいことを整理します。
| 順番 | 確認すること |
|---|---|
| 1 | 省略できるスキーマの引数で、既定値の入ったスキーマを前提にしていないか |
| 2 | 応答のキーの順番に頼ったテストがないか |
| 3 | DeprecationWarningが出ていないか |
| 4 | NINJA_PAGINATION_MAX_OFFSETを設定していないか |
私は10年ほどエンジニアとして開発に関わってきましたが、検索条件を省略しただけで422が返るAPIに、利用者から問い合わせが続いたことがあります。何も指定しなければ全件を返す、という自然な動きにしやすくなったのは、使う側にとっても作る側にとってもありがたい変更です。
まとめ¶
2026年11月8日、Django Ninja 1.8.0が公開されました。Webhookで送るデータの形をOpenAPIの説明書に書けるようになり、省略できる検索条件のスキーマが、何も送られなかったときに422ではなくNoneになるよう改善されています。
ModelSchemaの並び順など、動きが変わる点もあります。上げたら、まずテストを流して、警告が出ていないかを確かめておきましょう。
ここまでお読みいただきありがとうございました。