Skip to main content
 首页 » 编程设计

python之Django 休息 : map 'update' to 'list' using CustomRouter

2025年02月15日36hnrainll

问题说明:

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

router = routers.DefaultRouter() 

帐户路由器:

router.register('accounts', AccountViewSet) 
accounts_router = NestedSimpleRouter(router, r'accounts') 

accounts_router 下还有其他路由器使用标准范例(如 Django Reference 中所述),例如:

URL pattern: ^accounts/$ Name: 'account-list' 
URL pattern: ^accounts/{pk}/$ Name: 'account-detail' 

问题:

现在有一个只有 1 个实例的对象 - singleton_foo。将其详细信息 View 显示为 /accounts/foo_acc/singleton_foo/1 将是一个坏主意,因为用户可能期望 #2、#3 等。

目标:

我想使用自定义路由器将“/accounts/foo_acc/singleton_foo/1”映射到“/accounts/foo_acc/singleton_foo”。基本上,我想在 ListView (list) 中显示和更新 singleton_foo 详细信息 (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') 

有什么建议吗?

请您参考如下方法:

如果这在您的项目中可行,您可以通过重写 View 集的一些方法来实现相同的行为。这里的核心内容:

  • 仅获取查询集中的第一项(在 get_queryset 中使用“[:1]”),
  • 如果一个新项目已经存在(在 create() 中),则拒绝创建新项目,
  • 重写 get_object() 方法,这样当我们没有为 lookup_field 传递值时它就不会引发异常。

views.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 

urls.py

urlpatterns = [ 
    url(r'^$', SingletonView.as_view({'get':'list', 'post': 'create', 'delete': 'destroy', 'put': 'update'})), 
] 

现在您可以通过相同的 url 访问所有方法(GET、PUT、POST、DELETE),无需 pk 和“仅一个项目”控制。