如何在Django-Rest-Framework视图集中获取自定义列表视图

11

我有一个电视频道模型,并创建了一个Django-restframework视图,它可以帮我轻松地提供列表和详细视图。在此基础上,我添加了两个自定义的单个对象视图,称为all_events和now_and_next_event,如在此处描述的。到目前为止,这一切都很好。

class ChannelViewSet(viewsets.ModelViewSet):
    """
    A viewset for viewing and editing channel instances.
    """
    serializer_class = serializers.ChannelSerializer
    queryset = Channel.objects.all()

    @link()
    def now_and_next_event(self, request, pk):
        ''' Show current and next event of single channel. '''
        ...

现在我想添加一个自定义视图,它不是单个对象视图而是类似于列表的视图:

class CurrentEvents(generics.ListCreateAPIView):
    ''' Show current event of all channels. '''
    model = Event
    serializer_class = serializers.EventSerializer

    def get(self, request):
        ...

当我禁用我的视图并添加手动的URL模式时,它也可以正常工作。但是我还没有弄清楚如何让它们都使用相同的“api/channel/”前缀,或者更喜欢的是,如何将自定义列表视图类添加到我的视图中。

这是我的视图URL模式:

^api/channel/$ [name='channel-list']
^api/channel/(?P<pk>[^/]+)/$ [name='channel-detail']
^api/channel/(?P<pk>[^/]+)/all_events/$ [name='channel-all-events']
^api/channel/(?P<pk>[^/]+)/now_and_next_event/$ [name='channel-now-and-next-event']

我希望能像这样访问我的列表视图:

^api/channel/current_events/$ [name='event-current']

https://stackoverflow.com/a/46066153/2803344 - Belter
3个回答

9
从Django REST Framework 2.4开始,你现在可以使用@list_route修饰ViewSet方法来获得你需要的内容。
文档中了解更多。

@detail_route装饰器在其URL模式中包含pk,适用于需要单个实例的方法。@list_route装饰器适用于操作对象列表的方法。

这些替代了旧的@link@action装饰器,这些装饰器只能作为详细路由工作。

1
从3.8开始,@detail_route@list_route即将被弃用,取而代之的是@action(detail=True)@action(detail=False)。(它们将在3.9中被弃用,并在3.10中被移除)。 - philngo

6
如果您需要对象列表,则需要在ListApiView中使用list方法: 例如,模型是ModelName,序列化器类是SerializerClassname,则代码将如下所示:
class ExampleView(ListAPIView):
    model = ModelNmae
    serializer_class = SerializerClassName
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        """
        """
        queryset = ModelName.objects.all()
        q = self.request.query_params.get('q', None)
        if q is not None:
            queryset =queryset.filter(name__icontains=q)
        return queryset

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        result = [ x.values()[0] for x in serializer.data ]
        return Response(result)

0

首先,在项目的任何位置创建一个viewsets.py文件并编写以下代码:

from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator

    
class ModelOptsMixin(object):
     """CBV mixin which adds model options to the context."""
    
     def get_context_data(self, **kwargs):
        """Returns the context data to use in this view."""
        ctx = super().get_context_data(**kwargs)
        if hasattr(self, "model"):
            ctx["opts"] = self.model._meta
        return ctx

class BaseListView(
    LoginRequiredMixin,
    PermissionRequiredMixin,
    ModelOptsMixin,
    HasPermissionsMixin,
    ListView,
):
    """ListView CBV with LoginRequiredMixin and PermissionRequiredMixin."""

    def base_paginator(self, instance):
        """
        Set paginator return context of paginator.
        """
        paginator = Paginator(instance, int(settings.DEFAULT_PAGINATION_SIZE))
        page = self.request.GET.get("page", 1)
        try:
            instance_paginator = paginator.page(page)
        except PageNotAnInteger:
            instance_paginator = paginator.page(1)
        except EmptyPage:
            instance_paginator = paginator.page(paginator.num_pages)

        return instance_paginator

导入BaseListView并使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接