Python Django REST:map';更新';至';列表';使用自定义路由器
问题解释: 有一个Django项目使用RESTAPI。路由器定义为:Python Django REST:map';更新';至';列表';使用自定义路由器,python,django,django-rest-framework,Python,Django,Django Rest Framework,问题解释: 有一个Django项目使用RESTAPI。路由器定义为: router = routers.DefaultRouter() 帐户路由器: router.register('accounts', AccountViewSet) accounts_router = NestedSimpleRouter(router, r'accounts') accounts\u router下还有其他路由器使用标准范例(如中所述),例如: 问题: 现在有一个对象只有一个实例-singleton\u
router = routers.DefaultRouter()
帐户路由器:
router.register('accounts', AccountViewSet)
accounts_router = NestedSimpleRouter(router, r'accounts')
accounts\u router
下还有其他路由器使用标准范例(如中所述),例如:
问题:
现在有一个对象只有一个实例-singleton\u foo
。将其详细信息视图显示为/accounts/foo_acc/singleton_foo/1
将是一个坏主意,因为用户可能期望2、3等
目标:
我想使用自定义路由器将“/accounts/foo_acc/singleton_foo/1”映射到“/accounts/foo_acc/singleton_foo”。基本上,我想在列表视图(list)中显示和更新singleton\u foo
details(update)
我尝试过使用类似于:
class SingletonNestedRouter(NestedSimpleRouter):
routes = [
Route(
url=r'^{prefix}/$',
mapping={'get': 'list'},
name='{basename}-list',
initkwargs={'suffix': 'List'}
),
Route(
url=r'^{prefix}/{pk}/$',
mapping={'put': 'retrieve'},
name='{basename}-retrieve',
initkwargs={'suffix': 'Retrieve'}
),
]
并将路由器连接到帐户:
accounts_router.register('singleton_foo', SingletonFooViewSet, 'singletonfoo')
ConfigNestedRouter(domains_router, singleton_foo', lookup='singleton_foo')
有什么建议吗?如果在项目中可以这样做,您可以通过覆盖某些视图集的方法来实现相同的行为。这里的核心是:
- 仅获取查询集中的第一项(在get_queryset中使用“[:1]”)
- 如果已存在新项目(在create()中),则拒绝创建新项目
- 重写get_object()方法,以便在未传递lookup_字段的值时不会引发异常
class SingletonView(viewsets.ModelViewSet):
serializer_class = SingletonSerializer
def get_queryset(self):
return SingletonModel.objects.all()[:1]
def create(self, request, *args, **kwargs):
if not self.get_queryset().exists():
return super(SingletonView, self).create(request, *args, **kwargs)
else:
return Response({
'message': 'Already exists and can be only one!'
}, status=status.HTTP_400_BAD_REQUEST)
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
obj = shortcuts.get_object_or_404(queryset)
# May raise a permission denied
self.check_object_permissions(self.request, obj)
return obj
urlpatterns = [
url(r'^$', SingletonView.as_view({'get':'list', 'post': 'create', 'delete': 'destroy', 'put': 'update'})),
]
url.py
class SingletonView(viewsets.ModelViewSet):
serializer_class = SingletonSerializer
def get_queryset(self):
return SingletonModel.objects.all()[:1]
def create(self, request, *args, **kwargs):
if not self.get_queryset().exists():
return super(SingletonView, self).create(request, *args, **kwargs)
else:
return Response({
'message': 'Already exists and can be only one!'
}, status=status.HTTP_400_BAD_REQUEST)
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
obj = shortcuts.get_object_or_404(queryset)
# May raise a permission denied
self.check_object_permissions(self.request, obj)
return obj
urlpatterns = [
url(r'^$', SingletonView.as_view({'get':'list', 'post': 'create', 'delete': 'destroy', 'put': 'update'})),
]
现在,您可以通过相同的url访问所有方法(GET、PUT、POST、DELETE),而无需使用“仅一项”控件进行pk。您的答案看起来不错,但不起作用-它在列表页面上显示POST(无PUT)。想知道在Django REST API中是否有可能做到这一点。@h3d0“它在列表页上显示帖子(没有放置)”是什么意思?有一个Django REST GUI。当您导航到列表视图url时,它将具有POST按钮(这将创建对象的新实例)。导航到“详细信息”视图时,显示的按钮为“放置”、“删除”。我需要在列表级url中显示-这是目标。@h3d0根据我在任务中的理解,不应该有列表或详细视图(分别是-url)。所以URL“/accounts/foo_acc/singleton_foo”应该列出您的帐户(只有1个),并提供POST、PUT和DELETE方法。如果您使用路由器为SingletonFooViewSet构建url配置,路由器会将方法拆分为多个url(通常一个用于list+post,一个用于detail+put+delete)。为了在一个url上获取所有方法,我创建了urlpattern,如我在url.py中的示例所示。你试过使用它吗?整个项目使用
DefaultRouter
作为基础。假设数据库中有一个模型。但是模型总是只有一个实例-因此没有理由像/some_model/1
那样显示它(因为没有2、3等)。因此,我想在/some_model
上显示这1个实例,并提供与细节相关的操作(PUT),而不是与列表相关的操作(list,POST)。