MENU

Django Ninjaチュートリアル15(routerを用いたルーティング)

Django-Ninjaチュートリアル15(routerを用いたルーティング)

前回までの記事はこちらです。

前回までの記事が読まれている前提で書いていきますので、まだ読んでいない方はこちらから読み進めて追いついてください。

それでは始めていきましょう。

目次

routerを用いたルーティング

今回は、公式ドキュメントで紹介されているrouterを用いたルーティング設定についてみていきたいと思います。

実際のアプリケーションでは、すべてのロジックを 1 つのファイルに収めることはほとんどできません。
Django Ninjaでは、このようなケースに対応するため、routerを使用してAPIを複数のモジュールに分割する簡単な方法が用意されています。

次のような構造のDjangoプロジェクトがあるとすると、それぞれのアプリケーションにapi.pyを作成し、個々のアプリケーションでAPIを作成することになるケースが多いです。

├── myproject
│   └── settings.py
├── events/
│   ├── __init__.py
│   ├── api.py
│   └── models.py
├── news/
│   ├── __init__.py
│   ├── api.py
│   └── models.py
├── blogs/
│   ├── __init__.py
│   ├── api.py
│   └── models.py
└── manage.py

このような場合に、それぞれのapi.pyで個別のAPIを作成する場合は、これまで使用してきたNinjaAPIによるappインスタンスの使用ではなく、Routerを使用します。

それでは実際にアプリケーションを作成し、Routerを使用してみます。

まずは、以下のコマンドにより例と同じように、eventsアプリケーションを作成します。

docker-compose run backend python manage.py startapp events

Djangoのプロジェクトディレクトリのsettings.pyに作成したアプリケーションを読み込ませます。

〜略〜

INSTALLED_APPS = [
  'events.apps.EventsConfig', # add
  'example.apps.ExampleConfig',
  'register.apps.RegisterConfig',
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

〜略〜

次にeventsアプリケーションでモデルを設定します。
今回のモデルは、イベントの情報を持つモデルにします。
idは自動的に付番されるものとし、titleとdetailsを持つモデルとして定義します。

from django.db import models

class Event(models.Model):
  title = models.CharField(max_length=100)
  details = models.TextField()

ここまで作成したら、マイグレーションを行います。
docker-compose upをした状態で、別のターミナルから以下のコマンドを順番に実行します。

docker-compose run backend python manage.py makemigrations
docker-compose run backend python manage.py migrate

次に作成されたeventsディレクトリにapi.pyを作成します。
そのapi.pyの中に、以下のようにコードを記述します。

from ninja import Router
from .models import Event

router = Router()

@router.get("/")
def list_events(request):
  return [
    {
      "id": e.id,
      "title": e.title
    }
    for e in Event.objects.all()
  ]

@router.get("/{event_id}")
def event_details(request, event_id: int):
  event = Event.onbjects.get(id = event_id)
  return  {
    "title": event.title,
    "details": event.details
  }

今回はEventsアプリケーションのみの作成になりますgあ、他のアプリケーションを作成する場合も同様の流れとなります。

そして、この作成したapi.pyrouterをプロジェクトディレクトリにapi.py(ここでは便宜上、main_api.pyとし、区別しておきます)を作成し、グループ化します。

from ninja import NinjaAPI
from events.api import router as events_router

main_api = NinjaAPI(
  title = "Django-Ninja Sample App6.5",
  version = "1.0.65",
)

main_api.add_router("/events/", events_router)

さらに、プロジェクトディレクトリのurls.pyで他のAPIと同様に読み込みます。

from django.contrib import admin
from django.urls import path
from example.api_v1 import app
from example.api_v2 import app_v2
from example.api_v3 import app_v3
from example.api_v4 import app_v4
from example.api_v5 import app_v5
from example.api_v6 import app_v6
from .main_api import main_api # add

urlpatterns = [
  path('admin/', admin.site.urls),
  path("api/", app.urls),
  path("api_v2/", app_v2.urls),
  path("api_v3/", app_v3.urls),
  path("api_v4/", app_v4.urls),
  path("api_v5/", app_v5.urls),
  path("api_v6/", app_v6.urls),
  path("main_api/", main_api.urls) # add
]

自動生成ドキュメントで結果を表示してみます。
http://127.0.0.1:8000/main_api/docsにアクセスします。

自動生成ドキュメントでルーティングが生成されている
List形式のGETメソッドも機能する
idを指定したGETメソッドも実行できる

このようにしっかりとルーティングが機能することが確認できます。

事前にEventモデルに対応するデータをadminから入力しておくとGETメソッドを実行したときに結果がわかりやすいです。

Router authentication

Django Ninjaでは、 auth 引数を使用することで、routerで定義したすべてのオペレーションに対して、認証機能を適用することができます。
例えば以下のように設定します。

main_api.add_router("/events/", events_router, auth = BasicAuth())

もしくは以下のようにします。

router = Router(auth=BasicAuth())

Django Ninjaにおける認証機能は、別の記事で取り上げる予定です。
詳細はその際にまとめます。

Router tags

tags引数を使用することで、routerで定義したすべてのオペレーションに対して、タグを適用することができます。
使用例をみていきます。

main_api.add_router("/events/", events_router, tags = ["Events"])

このようにすることで、以下のように自動生成ドキュメントの表示が変更されます。

defaultがEventsに変わった自動生成ドキュメント

もしくは、個別のアプリケーション毎のrouterに対して、以下のように記述しても同様の結果が得られます。

Routerのネスト

さらに細かくロジックを分ける必要が出てくる場合、Django Ninjaでは、何回でも他のrouterrouterを含めることができるようになっています。
そして、最終的に最上位のrouterをメインのapiインスタンスに含めることになります。

基本的に、add_routerapiインスタンスやrouterインスタンスのどちらにも適用することになります。
公式ドキュメントの例を見てみます。

from django.contrib import admin
from django.urls import path
from ninja import NinjaAPI, Router

api = NinjaAPI() # メインのapiインスタンスを作成

# 3つのrouterインスタンスを作成
first_router = Router()
second_router = Router()
third_router = Router()

# メインのapiインスタンスから作成したAPI
# →「/api/add」 が生成される
@api.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}

# 1つ目のrouterインスタンスから作成したAPI
@first_router.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}

# 2つ目のrouterインスタンスから作成したAPI
@second_router.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}

# 3つ目のrouterインスタンスから作成したAPI
@third_router.get("/add")
def add(request, a: int, b: int):
    return {"result": a + b}

# --------------------------------------------------------------------------
# first_routerを「/l1」を起点として設定⇨(/l1/add)
# 最終的に「/api/l1/add」ができる
api.add_router("l1", first_router)

#  first_router(/l1)に対し、「/l2」を起点としてsecond_routerを設定⇨(/l2/add)
# 最終的に「/api/l1/l2/add」ができる
first_router.add_router("l2", second_router)

# second_router(/l2)に対し、「/l3」を起点としてthird_routerを設定(/l3/add)
# 最終的に「/api/l1/l2/l3/add」
second_router.add_router("l3", third_router)

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/", api.urls),
]

少し複雑ですが、このようにrouterで設定した各APIをネストして、新たにルーティグを設定することができます。

最後に

今回は、Django NinjaにおけるRouterの使い方を見てきました。
これまでは、各pythonファイルでapiを書いてきましたが、routerを使用することで、アプリケーション単位でrouterを設定し、プロジェクトディレクトリでAPIをまとめることができます。
その際に、起点となるURL用の文字列(/events/など)を含めて、各routerを紐付けするだけで、ルーティングの管理ができでしまいます。

また複雑なルーティングをネストにより作成することができるため、幅が広がりそうです。

次回は、Django Ninjaにおける認証機能についてみていきます。

それではまた次回もよろしくお願いします。

Django-Ninjaチュートリアル15(routerを用いたルーティング)

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

はじめまして、ふじです。
Python、Django、FastAPI、React.js、Next.jsを学習している、ずっと文系のプログラミング独学者です。

目次