我已经创建了2个这样的ModelViewSets(为了演示而简化):
class SomeBaseViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = SomeEventSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_queryset(self):
return SomeObjects.objects.filter(owner=self.request.user)
def get_serializer_context(self):
context = super(SomeBaseViewSet, self).get_serializer_context()
context.update({
"user": self.request.user,
"some_context_key": False
})
return context
class AdminViewSet(SomeBaseViewSet):
# Added in the HasAdminPermission
permission_classes = (permissions.IsAuthenticated, HasAdminPermission)
# Different queryset filter (overriding `get_queryset` vs setting queryset for standardization)
def get_queryset(self):
return SomeObjects.objects.all()
# The context should have `some_context_key=True`, and `user=request.user`
def get_serializer_context(self):
context = super(AdminViewSet, self).get_serializer_context()
context.update({
"some_context_key": True
})
return context
我的路由器/网址配置如下所示
router = DefaultRouter()
router.register(r'some_view', SomeBaseViewSet, base_name="some_view")
urlpatterns += [
url(r'^api/', include(router.urls)),
]
如果我想将/api/some_view/admin
路由到AdminViewSet,那么最好的方法是什么?
我尝试过的事情:
@list_route
SomeBaseViewSet
,但无法找到将其连接到AdminViewSet
url(r'^api/some_view/admin$', AdminViewSet.as_view({"get": "list"}))
添加到我的urlpatterns(这种类型可以运行,但是ViewSet稍微适用一些,并且通常是非常手动的):DefaultRouter
视图集提供专用的some_view
,然后我会在url(r'^api/some_view/')
上安装 - 再次hacky和迂腐与大量路由是否有“正确”的方式来完成我想要完成的任务,或者我应该找到针对此问题的不同解决方案(即过滤器或其他内容)?
我见过像https://github.com/alanjds/drf-nested-routers这样的图书馆,但这对我(相当简单)的需求来说似乎有些过分。
答案 0 :(得分:3)
使用列表路径定义管理视图集。这些参数将允许您执行具有指定权限(经过身份验证并具有管理权限)的get请求,该请求扩展了此类。即/someview/admin
或someotherview/admin
from rest_framework.decorators import list_route
class AdminViewSet(viewset.Viewsets):
@list_route(methods=['get'],
permissions=[permissions.IsAuthenticated, HasAdminPermission],
url_path='admin'
)
def admin(self, request):
# All your custom logic in regards to querysets and serializing
return serialized.data
然后,您可以扩展需要管理操作路由的任何视图集。
class SomeBaseViewSet(viewsets.ReadOnlyModelViewSet, AdminViewset):
serializer_class = SomeEventSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_queryset(self):
return SomeObjects.objects.filter(owner=self.request.user)
def get_serializer_context(self):
context = super(SomeBaseViewSet, self).get_serializer_context()
context.update({
"user": self.request.user,
"some_context_key": False
})
return context
你要小心这个,因为通常你的基本路线后面的参数,即/ someview / {param} /是为ID引用保留的。确保您的ID引用不会与您的详细路径冲突。
答案 1 :(得分:1)
我想我已经找到了自己问题的答案,但是如果有人想要加入(@ tom-christie可能吗?),我会在此处加上+50代表赏金。
无论哪种方式,我使用@list_route
和AdminViewSet
的{{1}}函数解决了它的问题。
这样的东西就足够了:
.as_view()
并且允许人们相应地路由URL(基于函数的名称),并强制执行您需要的任何额外的事情。
答案 2 :(得分:1)
http://www.django-rest-framework.org/api-guide/routers/#extra-link-and-actions
答案 3 :(得分:0)
不确定我是否错过了一些东西,但我刚刚测试过,这完美无缺(订单很重要):
router = DefaultRouter()
# this will overrides routes from the line below
router.register(r'some_view/admin', AdminViewSet)
router.register(r'some_view', SomeBaseViewSet)