Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django REST:map';更新';至';列表';使用自定义路由器_Python_Django_Django Rest Framework - Fatal编程技术网

Python Django REST:map';更新';至';列表';使用自定义路由器

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

问题解释:

有一个Django项目使用RESTAPI。路由器定义为:

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_字段的值时不会引发异常
视图.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.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)。