You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST ModelViewSet中实现多GET请求与不同URL?

Extend Existing BookViewSet for new_arrivals Endpoint

Great question! You don’t need to create a separate viewset or register a new URL—you can seamlessly add the new_arrivals functionality to your existing BookViewSet using custom actions in Django REST Framework (DRF). This keeps your code organized and lets you reuse the viewset’s existing logic (like permissions, serialization, and filtering).

Step 1: Add the Custom Action to BookViewSet

Use DRF’s @action decorator to define the new_arrivals method directly in your BookViewSet. This decorator tells DRF to treat this method as a separate endpoint, and it will automatically generate the correct URL pattern for you.

Here’s the updated code for your viewset:

from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from django.utils import timezone
from datetime import timedelta
from .models import Book
from .serializers import BookSerializer  # 替换成你的序列化器

class BookViewSet(viewsets.ModelViewSet):
    serializer_class = BookSerializer

    def get_queryset(self):
        # 你的现有逻辑:获取指定图书馆的图书,并支持筛选
        library_id = self.kwargs.get('library_id')
        queryset = Book.objects.filter(library_id=library_id)
        
        # 处理genre、status、author筛选
        genre = self.request.query_params.get('genre')
        if genre:
            queryset = queryset.filter(genre=genre)
        
        status = self.request.query_params.get('status')
        if status:
            queryset = queryset.filter(status=status)
        
        author = self.request.query_params.get('author')
        if author:
            queryset = queryset.filter(author__icontains=author)
        
        return queryset

    @action(detail=False, methods=['get'], url_path='new_arrivals')
    def new_arrivals(self, request, library_id=None):
        # 计算近两周的时间阈值
        two_weeks_ago = timezone.now() - timedelta(weeks=2)
        
        # 复用get_queryset()来继承现有筛选逻辑,再叠加时间过滤
        queryset = self.get_queryset().filter(created_at__gte=two_weeks_ago)
        # 注意:如果你的Book模型用的是其他字段记录新增时间(比如added_at),替换成对应的字段名
        
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

Step 2: No Changes Needed to Your URL Registration

Your existing router registration will automatically handle the new endpoint. The @action decorator with url_path='new_arrivals' will generate the exact URL you had before: api/books/<library_id>/new_arrivals.

DRF’s router builds the URL pattern by appending the url_path value to the base path of your viewset’s registered URL. So you can keep using:

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

Why This Approach Works

  • Code Reusability: The new_arrivals method uses self.get_queryset(), so it automatically inherits your existing genre/status/author filtering logic. You don’t have to duplicate code!
  • Consistency: It uses the same serializer, permissions, and pagination settings as your main BookViewSet, keeping your API behavior consistent.
  • Less Maintenance: No extra URLs or view classes to manage—everything lives in one place.

Key Notes

  • Make sure your Book model has a datetime field that tracks when the book was added (like created_at or added_at). Adjust the filter field in new_arrivals to match your actual field name.
  • If you need different permissions or serialization for the new_arrivals endpoint, you can override those in the @action decorator (e.g., permission_classes=[IsAdminUser]).
  • The detail=False parameter tells DRF this action doesn’t operate on a single instance of Book (it’s a list action), which matches your use case of returning multiple new books.

内容的提问来源于stack exchange,提问作者Thinker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:05:33