有一个使用REST API的DJANGO项目。
大多数URL模式遵循相同的范式:
/foo_config/1
基本上是/list-view/details-view
但是还有另一种类型的配置 - 只能具有1个对象,因此像/bar_config/1
一样显示它是令人困惑的,因为用户可能会期望#2和#3,等等。
我想"映射" bar_config
详细信息,并使用简单的/bar_config
列出。
尝试使用@detail_route
,但不起作用:
@detail_route(methods=['put'])
def put_config(self, request):
...
如何实现我的目标?
更新:尝试使用detail_route
和Ivan Semochkin答案 - 仍然没有运气。我将提供有关我拥有的内容的更多详细信息:
/accounts/foo_account/bar_config/
< - 列表视图 /accounts/foo_account/bar_config/1
< - 详细信息视图
定义为:
的帐户router = routers.DefaultRouter()
router.register('accounts', AccountViewSet)
目标是:
- 在
bar_config
上显示bar_config/1
(放在列表页面上); - 禁止/隐藏
bar_config/1
; - 允许查看和更新信息,禁止创建/删除;
我将总结:我需要更改子链接在现有项目中的工作方式,该项目已经使用DefaultRouter
用于其所有模式。这个子链接地图单元模型。我想在列表(GET)页面上显示更新(put)数据。
为什么不覆盖list
方法?
class ConfigViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Config.objects.all()
serializer_class = ConfigSerializer
def retrieve(self, request, *args, **kwargs):
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
def list(self, request, *args, **kwargs):
instance = self.get_queryset().first()
# using 'first' will retrieve first instance
serializer = self.get_serializer(instance)
return Response(serializer.data)
它可以正常工作,您不仅显示该模型。如果您想提供一些CRUD,则从ModelViewSet
继承和覆盖delete
和update
方法。
评论更新
另一种方法 - 创建一个自定义路由器,使用此路由器,您不需要使用list
,而是使用检索
from rest_framework.routers import Route, SimpleRouter
class CustomRouter(SimpleRouter):
"""
A router for update and retrieve without lookup field.
"""
routes = [
Route(
url=r'^{prefix}/$',
mapping={'put': 'update'},
name='{basename}-update',
initkwargs={'suffix': 'Update'}
),
Route(
url=r'^{prefix}/$',
mapping={'get': 'retrieve'},
name='{basename}-detail',
initkwargs={'suffix': 'Detail'}
),
]
视图集:
class ConfigViewSet(viewsets.ModelViewSet):
queryset = Config.objects.all()
serializer_class = ConfigSerializer
def retrieve(self, request, *args, **kwargs):
instance = self.get_queryset().first()
# using 'first' will retrieve first instance
serializer = self.get_serializer(instance)
return Response(serializer.data)
def update(self, request, *args, **kwargs):
instance = self.get_queryset().first()
serializer = self.get_serializer(instance, data=request.data)
# you could also provide `partial=True` in serializer for partial update
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)
url:
router = CustomRouter()
router.register('config', ConfigViewSet)
urlpatterns = router.urls