1. ホーム
  2. django

[解決済み] Django-Rest-Framework ルータ登録

2022-02-09 06:11:42

質問

Django-REST-FRAMEWORKを使って2台以上のルータを登録しようとすると、問題が発生するのですが。私の例をご覧ください。

urls.py

from rest_framework import routers
from collaborativeAPP import views

router = routers.DefaultRouter()
router.register(r'get_vocab', views.VocabViewSet)
router.register(r'get_term', views.TermViewSet)
router.register(r'get_discipline', views.DisciplineViewSet)

urlpatterns = patterns(
...
    url(r'^service/', include(router.urls))
)

views.py

class VocabViewSet(viewsets.ModelViewSet):
    queryset = Vocab.objects.all()
    serializer_class = VocabSerializer

class TermViewSet(viewsets.ModelViewSet):
    queryset = Term.objects.all()
    serializer_class = TermSerializer

class DisciplineViewSet(viewsets.ModelViewSet):
    queryset = Vocab.objects.filter(kwdGroup=4)
    serializer_class = DisciplineSerializer

を実行した結果、私のローカルホストでは以下のようになりました。

http://localhost:8000/service/

HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: GET, HEAD, OPTIONS

{
    "get_vocab": "http://127.0.0.1:8000/service/get_discipline/",
    "get_term": "http://127.0.0.1:8000/service/get_term/",
    "get_discipline": "http://127.0.0.1:8000/service/get_discipline/"
}

ご覧の通り、3つのルータを登録し、それぞれのメソッド名に対して3つのURLを表示することを想定しています( get_vocab , get_term , get_discipline ). 最終的な結果は get_discipline が2回発生し、get_vocabのurlが欠落しています。

しかし、get_discipline と get_vocab の場合、同じモデルを使用しているため、このような混乱が発生します。それぞれのモデルに対してビューセットを使用すべきでしょうか?もしそうなら、どのようにビューセットで異なるメソッドを定義することができますか?

以下のような結果になるはずです。

 HTTP 200 OK
 Content-Type: application/json
 Vary: Accept
 Allow: GET, HEAD, OPTIONS

 {
     "get_vocab": "http://127.0.0.1:8000/service/get_vocab/",
     "get_term": "http://127.0.0.1:8000/service/get_term/",
     "get_discipline": "http://127.0.0.1:8000/service/get_discipline/"
 }

何が足りないのでしょうか?ルーターはいくつでも登録できると思っていたのですが。1つのモデルに1つのルーターがあるはずなのですが?同じモデルを共有するビューセットでは動作しないようですが?

解決方法は?

登録したビューセットに明示的にbase_nameを追加してみてください。

router = routers.DefaultRouter()
router.register(r'vocabs', views.VocabViewSet, 'vocabs')
router.register(r'terms', views.TermViewSet, 'terms')
router.register(r'disciplines', views.DisciplineViewSet, 'disciplines')

余談ですが get_ という接頭辞はRESTfulではないため、URLの中に入れてください。各URLはリソースを指定すべきであり、リソースに対するアクションを指定するべきではありません。HTTP動詞はそのために使われるのです。

GET http://127.0.0.1:8000/service/vocabs/

# or this to create resource
POST http://127.0.0.1:8000/service/vocabs/

...