Django-Rest-Framework 路由器寄存器

Django-Rest-Framework router register

当我尝试使用 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 个路由器,期望它们将为每个方法名称(get_vocabget_termget_discipline)显示 3 个 url。最后的结果是 get_discipline 出现了两次而 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/"
 }

我错过了什么?我想我可以注册任意数量的路由器。每个型号应该有一个路由器?为什么似乎不适用于共享同一模型的视图集?

尝试向每个已注册的视图集显式添加 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 都应该指定一个资源,而不是对该资源的操作。这就是 HTTP 动词的用途:

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

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

...

这里有一些关于路由器的更多信息:

router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls

register() 方法有两个强制参数:

prefix : The URL prefix to use for this set of routes.

viewset : The viewset class.

base_name 旁边是什么?

用于创建的 URL 名称的基础。如果不设置base_name,会根据viewset上的model或queryset属性自动生成

这是上面例子生成的URL模式:

URL pattern: ^users/$ Name: 'user-list'

URL pattern: ^users/{pk}/$ Name: 'user-detail'

URL pattern: ^accounts/$ Name: 'account-list'

URL pattern: ^accounts/{pk}/$ Name: 'account-detail'

现在,如果你想创建自定义路由,你应该在装饰有 @link@action 的视图集上编写方法像这样:

@action(permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...

生成了以下URL:

URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password'

您使用了 DefaultRouter,此路由器类似于 SimpleRouter,但还包括一个默认 API 根视图,即 returns 包含对所有列表的 hyperlinks 的响应意见。它还为可选的 .json 样式格式后缀生成路由。

See this picture of detail table

在之前的回答中你得到了正确的答案..我只是给了你一些关于路由器的更多信息