如何根据URL参数过滤Django REST API查询集
实现方案
1. 在视图类中过滤查询集
你需要重写TheatreScreeningList的get_queryset方法,从URL参数中获取影院ID,通过模型关联关系筛选出对应影院的场次数据:
class TheatreScreeningList(ListAPIView): serializer_class = ScreeningSerializer filter_backends = (DjangoFilterBackend,) filterset_fields = ("screen", "film", "date", "time") def get_queryset(self): # 从URL的kwargs中提取影院ID参数 theatre_id = self.kwargs['theatre'] # 通过Screen与Theatre的关联,筛选该影院下的所有场次 queryset = Screening.objects.filter(screen__theatre_id=theatre_id) # 提前关联Screen和Film对象,避免序列化时触发N+1查询 return queryset.select_related('screen', 'film')
注意:移除了原视图中固定的queryset = Screening.objects.all(),因为get_queryset方法会动态生成符合条件的查询集,无需静态定义。
2. 优化序列化器性能
你的序列化器当前通过Screen.objects.get()和Film.objects.get()触发额外数据库查询,会导致N+1性能问题。结合上面的select_related,可以直接从实例的关联对象中获取数据,无需重复查询:
class ScreeningSerializer(serializers.ModelSerializer): class Meta: model = Screening fields = ('id', 'screen','film','date','time') def to_representation(self, instance): data = super().to_representation(instance) # 直接从关联实例中取值,避免额外数据库请求 data['screen'] = f"{instance.screen}" data['film'] = f"{instance.film}" return data
3. 可选:添加影院存在性验证
如果希望在请求无效影院ID时返回404错误,可以在get_queryset中先验证影院是否存在:
from django.shortcuts import get_object_or_404 from .models import Theatre # 请替换为你的影院模型类名 class TheatreScreeningList(ListAPIView): serializer_class = ScreeningSerializer filter_backends = (DjangoFilterBackend,) filterset_fields = ("screen", "film", "date", "time") def get_queryset(self): theatre_id = self.kwargs['theatre'] # 验证影院存在,不存在则返回404响应 get_object_or_404(Theatre, id=theatre_id) # 筛选并返回对应影院的场次数据 return Screening.objects.filter(screen__theatre_id=theatre_id).select_related('screen', 'film')
内容的提问来源于stack exchange,提问作者Cromwell1963
相关产品推荐
相关产品推荐

