概要
Djangoのルーティングについて
- Simple Router と Default Routerの概要とその違い
- ルーティングのネスト
の順で解説していきたいと思います
前提
- Djangoのプロジェクトとアプリケーションを作成済み
- SwaggerUIを使用
- 今回使用するパッケージは以下の通りです
- drf-spectacular==0.23.1
- django-extensions==3.2.0
- drf-nested-routers==0.93.4
はじめに
必要なパッケージをインストールします
パッケージ | 概要 |
---|---|
drf-spectacular | SwaggerUI |
django-extensions | 今回はルーティングを確認する際に使用 |
drf-nested-routers | ルーティングのネストに使用 |
ローカル上で使用する時
pip install drf-spectacular
pip install django-extensions
pip install drf-nested-routers
django-extensionsを使用する際はsettings.pyに以下を追加します
INSTALLED_APPS = [
# django_extensionsを追加
"django_extensions",
]
コンテナを使用するとき
一般的にはrequirements.txtに必要なパッケージを書きます
drf-spectacular==0.23.1
django-extensions==3.2.0
drf-nested-routers==0.93.4
Swaggerの設定方法
Swaggerの導入方法について以下の記事に書いたので使ったことがない方は参考にしてください
Simple Router と Default Routerとは
Simple Router
または Default Router
を(viewsets.ModelViewSet
と組み合わせて)使うことで
- GET(一覧)
- GET(詳細)
- POST
- PUT
- PATCH
- DELETE
の一通りのルーティングを自動的に作成できます
includeでHTTPメソッドごとにurlやviewを作成しなくて済みます
詳しく知りたい方は公式ドキュメントを参照してください
どちらも以下のようにrest_framework.routersからimportすれば使用できます
from rest_framework.routers import SimpleRouter
from rest_framework.routers import DefaultRouter
今回はルーティングのネストも行うのでrest_framework_nestedからimportします
from rest_framework_nested import routers
router = routers.SimpleRouter()
router = routers.DefaultRouter()
Simple RouterとDefault Routerの違いって何?
Defalut RouterはSimple Routerと違ってAPIのデフォルトのルートディレクトリを持ちます。以下のようにルートディレクトリにアクセスすると表示されます。Simple Routerでは表示されません
それ以外は特に違いがありません。今回はDefaultRouterを使ってルーティングをします
SimpleRouterを使用されたい方はDefaultRouterをSimpleRouterに置き換えて使用しても同じ挙動になります
ルーティングをしてみよう
まずはrest_framework_nestedからroutersをimportしてインスタンス化します
今回はrouterという名前のインスタンスを作成します
from rest_framework_nested import routers
router = routers.DefaultRouter()
どのようなルーティングにするか設定します
router.register(r'<ディレクトリ名>', <ViewSet名>,basename=<basename名、通常は単数系>)
basename
basenameは自身でviewset内にget_querysetメソッドを定義した場合に使用します
以上を踏まえてルーティングすると以下のようになります
from django.urls import path, include
from rest_framework_nested import routers
from .views import CustomerViewSets,BookViewSets
# Create a router and register our viewsets with it.
router = routers.DefaultRouter()
router.register(r'customers', CustomerViewSets,basename="customer")
# The API URLs are now determined automatically by the router.
urlpatterns = [
path(r'', include(router.urls)),
]
django-extensionsをインストールできたので
python manage.py show_urls
でルーティングを確認できます
今回はCustomerのルーティングを作成したのでadminのルーティングを除くと以下のようになります
python manage.py show_urls
/ rest_framework.routers.view api-root
/\.<format>/ rest_framework.routers.view api-root
/customers/ relationships.views.CustomerViewSets customer-list
/customers/<pk>/ relationships.views.CustomerViewSets customer-detail
/customers/<pk>\.<format>/ relationships.views.CustomerViewSets customer-detail
/customers\.<format>/ relationships.views.CustomerViewSets customer-list
ネスティング
上記のCustomerのルーティングに別のルーティングをネストしたいときはどうすればいいか解説します
今回はCustomerと1対多のリレーションをもつBookのルーティングをネストするとします
rest_framework_nestedのNestedDefaultRouterを使用します
SimpleRouterを使用する際はNestedSimpleRouterを使用することで同じ挙動になります
まずはNestedDefaultRouterをインスタンス化します
<NestedDefalutRouterのインスタンス名> = routers.NestedDefaultRouter(router,r"<ネスト元のurl>",lookup="ネスト元のbasename")
次にネストするurlの設定を行います
customer_router.register(r'books', BookViewSets, basename='book')
最後にurlspatternsにNestedDefaultRouterのurlを加えます
urlpatterns = [
path(r'', include(<NestedDefalutRouterのインスタンス名>.urls)),
]
以上の設定をすると以下のようになります
from django.urls import path, include
from rest_framework_nested import routers
from .views import CustomerViewSets,BookViewSets
# Create a router and register our viewsets with it.
router = routers.DefaultRouter()
router.register(r'customers', CustomerViewSets,basename="customer")
# 今回はcustomer_routerという名前のNestedDefaultRouterのインスタンスを作成
customer_router = routers.NestedDefaultRouter(router,r"customers",lookup="customer")
# customerにネストするbookのルーティング
customer_router.register(r'books', BookViewSets, basename='book')
# The API URLs are now determined automatically by the router.
urlpatterns = [
path(r'', include(router.urls)),
# ネストしたurlのルーティングをurlpatternsに指定
path(r'', include(customer_router.urls)),
]
CustomerとBookのルーティングを作成したのでadminのルーティングを除くと以下のようになります
python manage.py show_urls
/ rest_framework.routers.view api-root
/\.<format>/ rest_framework.routers.view api-root
/customers/ relationships.views.CustomerViewSets customer-list
/customers/<customer_pk>/books/ relationships.views.BookViewSets book-list
/customers/<customer_pk>/books/<pk>/ relationships.views.BookViewSets book-detail
/customers/<customer_pk>/books/<pk>\.<format>/ relationships.views.BookViewSets book-detail
/customers/<customer_pk>/books\.<format>/ relationships.views.BookViewSets book-list
/customers/<pk>/ relationships.views.CustomerViewSets customer-detail
/customers/<pk>\.<format>/ relationships.views.CustomerViewSets customer-detail
/customers\.<format>/ relationships.views.CustomerViewSets customer-list
Swagger上だと以下のようにCustomerのルーティングの後にBookのルーティングが設定されています
以上でルーティングの説明は終わりです
記事の紹介
以下の記事も作成しましたので見ていただけると幸いです
参考