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

Django中嵌套在其他序列化器内的序列化器如何通过URL参数过滤?

问题描述

我正在开发一个包含嵌套数据的API,需要通过URL参数搜索嵌套数据,要求搜索嵌套序列化器的字段后,仅返回匹配的嵌套条目,过滤掉其他不匹配的嵌套条目。
现有代码如下:

模型定义

class Robot(models.Model):
    robot = models.CharField(max_length=100)
    short_Description = models.CharField(max_length=200)
    status = models.CharField(max_length=20)
    parameter = models.CharField(max_length=200)
    jenkins_job = models.CharField(max_length=100, default='JenkinsJobName')
    jenkins_token = models.CharField(max_length=100, default='JenkinsToken')
    def __str__(self):
        return self.robot

class assignParameter(models.Model): 
    parameterName = models.CharField(max_length=100, blank=True)
    assignRobot= models.ForeignKey(Robot, on_delete=models.CASCADE, related_name='param', blank=True, null=True)

序列化器代码(serializer.py)

from .models import Robot,assignParameter
from rest_framework import serializers

class assignParameterSerializer(serializers.ModelSerializer):
    class Meta: 
        model = assignParameter
        fields = ['id', 'parameterName', 'assignRobot']


class RobotSerializer(serializers.ModelSerializer):
    param = assignParameterSerializer(many=True, read_only=True)
    # 注:原代码中的jenkinsHistorySerializer未提供对应模型定义,可根据实际需求保留或删除
    JenkinJobName = jenkinsHistorySerializer(many=True, read_only=True)
    class Meta: 
        model = Robot
        fields = ['id', 'robot', 'short_Description', 'status', 'parameter', 'jenkins_job',  'jenkins_token', 'param']

视图代码

class RobotViewSet(viewsets.ModelViewSet):
    queryset = Robot.objects.all()
    serializer_class = RobotSerializer
    filter_backends = [filters.DjangoFilterBackend]
    filterset_fields = ['robot', 'JenkinJobName__jenkinsBuildNumber']
    authentication_classes = [BasicAuthentication]
    permission_classes = [IsAuthenticated]

当前问题:可以通过/?robot=robotname搜索指定的Robot实例,但嵌套字段筛选不生效,无法过滤掉不匹配的嵌套条目。


问题原因
  1. 默认的DjangoFilterBackend只会过滤父级模型(Robot)的查询集,筛选逻辑仅判断「该Robot是否存在符合条件的关联子数据」,不会对子数据本身进行过滤,因此返回的Robot实例依然会携带所有关联的子数据。
  2. 原filterset_fields配置的筛选字段和实际需要筛选的嵌套字段不匹配,如果你要筛选param下的parameterName,现有配置没有对应字段声明。

解决方案

步骤1:自定义FilterSet配置正确的筛选字段

先在视图所在文件新增FilterSet定义,指定需要的嵌套筛选字段:

from django_filters.rest_framework import FilterSet, filters
from django.db.models import Prefetch
from .models import Robot, assignParameter

class RobotFilterSet(FilterSet):
    # 定义嵌套筛选参数,parameter_name为URL中传参的参数名
    parameter_name = filters.CharFilter(field_name='param__parameterName', lookup_expr='exact')
    class Meta:
        model = Robot
        fields = ['robot', 'parameter_name']

步骤2:重写视图的get_queryset方法,预过滤关联子数据

修改RobotViewSet,在返回查询集前先对关联的param数据做筛选,同时替换原filterset_fields配置为自定义的FilterSet:

class RobotViewSet(viewsets.ModelViewSet):
    serializer_class = RobotSerializer
    filter_backends = [filters.DjangoFilterBackend]
    filterset_class = RobotFilterSet # 替换为自定义FilterSet
    authentication_classes = [BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        queryset = Robot.objects.all()
        # 获取URL传入的parameter_name筛选参数
        param_name = self.request.query_params.get('parameter_name', None)
        if param_name:
            # 对关联的param数据进行prefetch_related并过滤
            queryset = queryset.filter(param__parameterName=param_name).prefetch_related(
                Prefetch('param', queryset=assignParameter.objects.filter(parameterName=param_name))
            ).distinct()
        return queryset

效果验证

配置完成后访问/?parameter_name=你要搜索的参数名,返回的Robot实例只会携带符合条件的param嵌套条目,其他不匹配的条目会被过滤。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:15:01