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

如何在Django DRF的ModelSerializer中设置特定QuerySet

解决DRF序列化时过滤关联对象的问题

嘿,我刚好处理过类似的DRF序列化过滤需求,针对你用Django 1.11和DRF 3.8.2的场景,给你两种可行的解决方案,都能实现让PerguntaSerializerModel的respostas字段只返回关联且tipo="alt"的Resposta对象:

方法一:使用SerializerMethodField(简单直接)

这种方式最容易上手,通过自定义序列化字段来过滤关联数据:

首先,先定义好Resposta的基础序列化器:

from rest_framework import serializers
from .models import Resposta

class RespostaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Resposta
        fields = ('id', 'texto', 'tipo')  # 替换成你需要返回的字段

然后修改PerguntaSerializerModel,用SerializerMethodField来替代默认的关联字段序列化:

from .models import Pergunta

class PerguntaSerializerModel(serializers.ModelSerializer):
    # 自定义respostas字段
    respostas = serializers.SerializerMethodField()

    class Meta:
        model = Pergunta
        fields = ('id', 'texto', 'respostas')  # 加上你的其他字段

    def get_respostas(self, obj):
        # 过滤当前Pergunta关联的tipo为"alt"的Resposta对象
        filtered_respostas = obj.respostas.filter(tipo="alt")
        # 用RespostaSerializer序列化过滤后的结果
        return RespostaSerializer(filtered_respostas, many=True).data

这样当你从Questionario级联序列化到Pergunta时,respostas字段就只会返回符合条件的对象了。

方法二:使用Prefetch优化性能(适合大数据量)

如果你的系统数据量较大,上面的方法会为每个Pergunta触发一次额外的数据库查询,性能不够理想。这时候可以用Django的Prefetch对象,在查询Questionario时就预取过滤好的Resposta数据:

步骤1:在视图层优化查询集

from django.db.models import Prefetch
from rest_framework import viewsets
from .models import Questionario, Pergunta, Resposta
from .serializers import QuestionarioSerializer

class QuestionarioViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Questionario.objects.all() \
        # 预取关联的Pergunta,同时预取每个Pergunta下符合条件的Resposta
        .prefetch_related(
            Prefetch(
                'perguntas',  # 这里要对应Questionario到Pergunta的related_name
                queryset=Pergunta.objects.prefetch_related(
                    Prefetch(
                        'respostas',  # 对应Pergunta到Resposta的related_name
                        queryset=Resposta.objects.filter(tipo="alt"),
                        to_attr='filtered_respostas'  # 给过滤后的结果起个名字
                    )
                )
            )
        )
    serializer_class = QuestionarioSerializer

步骤2:修改序列化器使用预取的数据

class PerguntaSerializerModel(serializers.ModelSerializer):
    respostas = serializers.SerializerMethodField()

    class Meta:
        model = Pergunta
        fields = ('id', 'texto', 'respostas')

    def get_respostas(self, obj):
        # 直接使用预取好的filtered_respostas,避免重复查询数据库
        return RespostaSerializer(obj.filtered_respostas, many=True).data

这种方法通过一次数据库查询就完成了所有过滤和预取,性能会好很多,推荐在数据量大的场景下使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:51:33