Django Rest Framework如何通过show_id和number字段查询剧集详情?
Hey there! Let's sort out that episode lookup issue you're facing with your DRF podcast backend. First off, adding a get_queryset method to your serializer wasn't going to work—serializers don't handle queryset filtering; that's the responsibility of your viewset. Let's fix this with two solid approaches, depending on how you want your API to behave.
Option 1: Add a Custom API Endpoint (Recommended, RESTful)
This creates a dedicated endpoint for looking up episodes by show_id and number, which keeps your API behavior clear and consistent.
Update your views.py with a custom action in the EpisodeViewSet:
from django.shortcuts import get_object_or_404 from rest_framework.decorators import action from rest_framework.response import Response from rest_framework import status class EpisodeViewSet(viewsets.ModelViewSet): queryset = Episode.objects.all().order_by('-published_at') def get_serializer_class(self): if self.action == 'retrieve' or self.action == 'by_show_and_number': return EpisodeDetailSerializer return EpisodeSerializer # Custom action to fetch episode by show_id and number @action(detail=False, methods=['get'], url_path='by-show-number') def by_show_and_number(self, request): # Grab query parameters show_id = request.query_params.get('show_id') number = request.query_params.get('number') # Validate required parameters if not show_id or not number: return Response( {"error": "Both 'show_id' and 'number' query parameters are required"}, status=status.HTTP_400_BAD_REQUEST ) # Try to fetch the episode, handle invalid integer values try: episode = get_object_or_404(self.queryset, show_id=int(show_id), number=int(number)) except ValueError: return Response( {"error": "show_id and number must be valid integers"}, status=status.HTTP_400_BAD_REQUEST ) # Serialize and return the episode using the detail serializer serializer = self.get_serializer(episode) return Response(serializer.data)
Now you can access the episode with a URL like:/api/episodes/by-show-number/?show_id=2&number=24
This endpoint will return the full episode detail (using EpisodeDetailSerializer) just like the default /api/episodes/<pk>/ endpoint.
Option 2: Modify the List Endpoint to Return a Single Episode (Less RESTful)
If you really want to use the existing /api/episodes/ endpoint with query parameters to return a single episode, you can override the list method. Note: This can confuse clients since the same endpoint will return either an array or a single object depending on parameters.
Update your views.py:
from django.shortcuts import get_object_or_404 from rest_framework.response import Response from rest_framework import status class EpisodeViewSet(viewsets.ModelViewSet): queryset = Episode.objects.all().order_by('-published_at') def get_serializer_class(self): if self.action == 'retrieve' or (self.action == 'list' and self.request.query_params.get('show_id') and self.request.query_params.get('number')): return EpisodeDetailSerializer return EpisodeSerializer def list(self, request, *args, **kwargs): show_id = request.query_params.get('show_id') number = request.query_params.get('number') # Check if both parameters are present if show_id and number: try: episode = get_object_or_404(self.queryset, show_id=int(show_id), number=int(number)) except ValueError: return Response( {"error": "show_id and number must be valid integers"}, status=status.HTTP_400_BAD_REQUEST ) serializer = self.get_serializer(episode) return Response(serializer.data) # Fall back to default list behavior if no parameters are present return super().list(request, *args, **kwargs)
With this, accessing /api/episodes/?show_id=2&number=24 will return the single episode detail, while /api/episodes/ without parameters returns the full list.
Why Your Previous Attempt Didn't Work
Just to clarify: Serializers (like EpisodeDetailSerializer) don't have a get_queryset method—this method belongs exclusively to viewsets and generic views. Filtering logic should always live in the view layer, not the serializer.
内容的提问来源于stack exchange,提问作者Helmi

