Django rest ModelViewSet несколько запросов GET с разными URL

У меня есть модели: в библиотеке может быть много книг.

Прямо сейчас у меня есть URL для выполнения CRUD над книгами в определенной библиотеке:

router.register(r'books/(?P<library_id>[0-9]+)', BookViewSet, base_name='books')

и соответствующий вид:

class BookViewSet(viewsets.ModelViewSet):

    serializer_class = BookSerializer
    def get_queryset(self):

        genre_query = self.request.query_params.get('genre', None)
        status_query = self.request.query_params.get('status', None)
        author_query = self.request.query_params.get('author', None)

        books = Book.objects.filter(which_library=self.kwargs.get('library_id'))
        if genre_query:
            books = books.filter(genre=genre_query)
        if status_query:
            books = books.filter(status=status_query)
        if author_query:
            books = books.filter(author=author_query)
        return books 

Изначально я не использовал ModelViewSet, вместо этого у меня были функции с декораторами @api_view, одним из которых было следующее (возвращая книги, добавленные за последние две недели, у меня был отдельный URL-адрес для этой функции как api/books//new_arrivals):

@api_view(['GET'])
def new_arrivals(request, library_id):
    """
    List all new arrival books in a specific library
    """
    d=timezone.now()-timedelta(days=14)
    if request.method == 'GET':
        books = Book.objects.filter(which_library=library_id)
        books = books.filter(when_added__gte=d)
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

Как использовать это при использовании ModelViewSets? Должен ли я добавить еще один URL, а затем написать другой класс для new_arrivals или написать функцию в существующем BookViewSet? Как добиться обработки этих двух методов GET в этом случае?

1 ответ

Решение

Вы можете расширить традиционный viewSet, добавив специальные методы list_route а также detail_route, С помощью этих декораторов вы можете добавлять новые URL, созданные ViewSet. В этом случае list_route больше подходит:

from rest_framework.decorators import list_route

class BookViewSet(viewsets.ModelViewSet):
    ...
    @list_route()
    def new_arrivals(self, request):
        books = self.get_queryset()
        d=timezone.now()-timedelta(days=14)
        books = books.filter(when_added__gte=d 
        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)

Это добавит дополнительный URL в viewSet: books/{library_id}/new_arrivals,

list_route а также detail_route амортизируются и объединяются с действием декоратора.

https://www.django-rest-framework.org/community/3.8-announcement/

Другие вопросы по тегам