Django-Rest-Framework路由器寄存器

时间:2015-07-08 11:16:51

标签: django rest django-rest-framework

当我尝试使用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

我的localhost中的结果如下:

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个网址(get_vocabget_termget_discipline)。最终结果是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/"
 }

我缺少什么?我想我可以注册尽可能多的路由器。每个型号应该有一个路由器?为什么似乎不适用于共享相同模型的视图集?

2 个答案:

答案 0 :(得分:6)

尝试向每个已注册的视图集显式添加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/

...

答案 1 :(得分:0)

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

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

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

<块引用>

prefix : 用于这组路由的 URL 前缀。

viewset : 视图集类。

什么与 base_name 相邻?

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

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

<块引用>

网址格式:^users/$ 名称:'user-list'

<块引用>

网址格式:^users/{pk}/$ 名称:'user-detail'

<块引用>

网址格式:^accounts/$ 名称:'account-list'

<块引用>

网址格式:^accounts/{pk}/$ 名称:'account-detail'

现在,如果您想创建自定义路线,您应该在用 @link@action 装饰的视图集上编写方法,如下所示:

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

生成的以下网址:

<块引用>

网址格式:^users/{pk}/set_password/$ 名称:'user-set-password'

您使用了 DefaultRouter,该路由器类似于 SimpleRouter,但另外包含一个默认 API 根视图,该视图返回包含指向所有列表视图的超链接的响应。它还为可选的 .json 样式格式后缀生成路由。

<块引用>

See this picture of detail table

在上一个答案中,您得到了正确答案.. 我刚刚给了您一些有关路由器的更多信息