Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get custom list view in django-rest-framework viewset

I have a tv channel model and created a django-restframework viewlet which gives me a list and a detail view out of the box. On top I added two custom single-object views called all_events and now_and_next_event, as described here: Marking extra methods for routing. That works great so far.

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

Now I would like to add a custom view which is NOT a single-object view but a list-like view:

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

    def get(self, request):
        ...

When I disable my viewlet and add a manual url pattern for it, it works as well. But I haven't figured out how to make them both work with the same 'api/channel/' prefix, or what I would like more, how to add the custom list view class into my viewlet.

Here are my viewlet url patterns:

^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']

And I would like to access my list view like:

^api/channel/current_events/$ [name='event-current']
like image 302
djangonaut Avatar asked Nov 12 '13 05:11

djangonaut


People also ask

What is ViewSet in Django REST framework?

A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as . get() or . post() , and instead provides actions such as . list() and . create() .

What is difference between View and ViewSet in django?

While regular views act as handlers for HTTP methods, viewsets give you actions, like create or list . The great thing about viewsets is how they make your code consistent and save you from repetition. Every time you write views that should do more than one thing, a viewset is the thing that you want to go for.

What is difference between APIView and ViewSet?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

What is Lookup_field in django?

lookup_field - The model field that should be used to for performing object lookup of individual model instances. Defaults to 'pk' . Note that when using hyperlinked APIs you'll need to ensure that both the API views and the serializer classes set the lookup fields if you need to use a custom value.


2 Answers

if you want list of objects then you need list method in your ListApiView: For example, model is ModelName and serializer class is SerializerClassname then code will be:

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)
like image 97
Arpit Singh Avatar answered Sep 19 '22 19:09

Arpit Singh


As of Django REST Framework 2.4, you can now decorate ViewSet methods with @list_route to get what you are looking for.

From the documentation

The @detail_route decorator contains pk in its URL pattern and is intended for methods which require a single instance. The @list_route decorator is intended for methods which operate on a list of objects.

These replace the old @link and @action decorators which were only able to work as detail routes.

like image 40
Kevin Brown-Silva Avatar answered Sep 19 '22 19:09

Kevin Brown-Silva