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

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.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:03:18