当我尝试使用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_vocab
,get_term
,get_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/"
}
我缺少什么?我想我可以注册尽可能多的路由器。每个型号应该有一个路由器?为什么似乎不适用于共享相同模型的视图集?
答案 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
在上一个答案中,您得到了正确答案.. 我刚刚给了您一些有关路由器的更多信息