Django Rest Framework:如何将 uuid 路由到关联对象?

Django Rest Framework: how to route a uuid to an associated object?

我正在使用 Django Rest Framework (DRF) 构建一个简单的相册应用程序。每个相册在其模型中都有一个 UUID 字段。我想创建 'share links' 以便具有 /albums/[uuid] 形式的 link 的人能够访问该相册。

我正在使用 ModelViewSet 作为我的视图,所以我认为实现此所需路由的最简洁方法是通过 action 装饰器,使用 /albums/shared/[uuid] 之类的 url,但是我不清楚如何在 action-decorated shared 方法中获取 uuid。我什至无法解析 URL 因为 DRF 在触发此 shared 方法之前会 404:

### views/album.py

class AlbumViewSet(viewsets.ModelViewSet):
    
    queryset = Album.objects.all()
    serializer_class = AlbumSerializer

    @action(detail=False, methods=['get'])
    def shared(self, request):

        # How do you get the uuid from the supplied URL?
        uuid = ???
        obj = self.get_queryset().objects.get(uuid=uuid)
        return Response([obj])

希望我不必向 urls.py 添加任何花哨的模式,但如果我这样做了,那么这就是我目前所拥有的:

### myapp/urls.py

router = routers.DefaultRouter()
router.register(r'albums', AlbumViewSet)
...

urlpatterns = [
    # ...
    path('', include(router.urls)),
]

format_suffix_patterns(urlpatterns)

谢谢!

这里您需要对 url-pattern 和您的 action-decorater 进行一些更改:

第一个变化:

/albums/shared/[uuid] /albums/[uuid]/shared/ 根据Docs.

第二个变化:

class AlbumViewSet(viewsets.ModelViewSet):
    
    queryset = Album.objects.all()
    serializer_class = AlbumSerializer

                   ⬇⬇⬇⬇
    @action(detail=True, methods=['get'])
    def shared(self,request,pk=None): ⬅⬅⬅⬅
        uuid = pk
        obj = self.get_queryset().objects.get(uuid=uuid)
        return Response([obj])

url中传递UUID并在view中获取它...例如。 /albums/45/shared/

@Pradip 给出的答案是完美的,但为了我自己的参考,这是我使用的不同解决方案(除了查询部分未测试!):

### myapp/views/album.py

class AlbumViewSet(viewsets.ModelViewSet):
    ...

    @action(detail=False, methods=['get'],)
    def shared(self, request,   *args, **kwargs):
        uuid = kwargs.get('uuid', None)
        if uuid:
            try:
                obj = self.get_queryset().get(name=uuid)
                return Response([obj])
            except Album.DoesNotExist:
                obj = None
                raise exceptions.NotFound(f'Album with UUID {uuid} not found')
        else:
            raise exceptions.ParseError('UUID not parseable')


### myproject/urls.py
urlpatterns = [
    ...
    path('albums/<str:uuid>/shared/', AlbumViewSet.as_view({'get': 'shared'})),
]