Django中如何返回含序列化外键及分页字段的查询集结果
解决方案
一、解决外键仅返回ID的问题:使用嵌套序列化器
要让外键返回完整的序列化对象,需要为每个外键关联的模型定义独立的序列化器,然后在主序列化器中嵌套使用这些子序列化器。
示例代码:
from rest_framework import serializers from .models import Bolsa, Nivel, Modalidade, Periodo, Ano, Instituicao # 为每个外键模型定义序列化器 class NivelSerializer(serializers.ModelSerializer): class Meta: model = Nivel fields = ('id', 'nome') class ModalidadeSerializer(serializers.ModelSerializer): class Meta: model = Modalidade fields = ('id', 'nome') class PeriodoSerializer(serializers.ModelSerializer): class Meta: model = Periodo fields = ('id', 'nome') class AnoSerializer(serializers.ModelSerializer): class Meta: model = Ano fields = ('id', 'nome') class InstituicaoSerializer(serializers.ModelSerializer): class Meta: model = Instituicao fields = ('id', 'nome') # 主序列化器,嵌套使用上述子序列化器 class BolsaSerializer(serializers.ModelSerializer): nivel = NivelSerializer() modalidade = ModalidadeSerializer() periodo = PeriodoSerializer() ano = AnoSerializer() instituicao = InstituicaoSerializer() class Meta: model = Bolsa fields = ('id', 'nome', 'nivel', 'modalidade', 'periodo', 'ano', 'instituicao')
二、解决get_queryset无法返回自定义结构的问题:重写视图的list方法
get_queryset只能返回QuerySet对象,不能直接返回自定义字典结构。需要在视图中重写list方法,完成查询集分页、序列化、组装自定义响应结构的逻辑。
示例代码(基于DRF的ViewSet实现):
from rest_framework import viewsets, status from rest_framework.response import Response from django.core.paginator import Paginator from .models import Bolsa from .serializers import BolsaSerializer class BolsaViewSet(viewsets.ViewSet): def list(self, request): # 获取分页参数,默认值可根据需求调整 pagina = int(request.query_params.get('pagina', 0)) limite = int(request.query_params.get('limite', 10)) # 获取原始查询集 queryset = Bolsa.objects.all() totalElementos = queryset.count() # 处理分页(Django Paginator页号从1开始,需转换pagina参数) paginator = Paginator(queryset, limite) try: bolsas_page = paginator.page(pagina + 1) except: bolsas_page = [] # 序列化分页后的查询集 serializer = BolsaSerializer(bolsas_page, many=True) elementos = len(serializer.data) # 计算自定义分页参数(修正原逻辑的错误,判断是否为首尾页) totalPaginas = paginator.num_pages primeiro = (pagina == 0) ultimo = (pagina + 1 == totalPaginas) # 组装目标响应结构 retorno = { 'bolsas': serializer.data, 'paginacao': { 'ultimo': ultimo, 'primeiro': primeiro, 'totalPaginas': totalPaginas, 'totalElementos': totalElementos, 'elementos': elementos, 'offset': pagina } } return Response(retorno, status=status.HTTP_200_OK)
关键说明
- 嵌套序列化器:通过为外键模型定义独立序列化器并在主序列化器中引用,实现外键数据的完整序列化,替代默认的仅返回ID的行为。
- 视图重写:
get_queryset仅负责提供原始查询集,所有自定义响应结构的组装、分页逻辑都在list方法中完成,符合DRF的视图规范。 - 分页逻辑修正:原代码中
ultimo的判断逻辑存在误差,改为判断当前页是否为最后一页,确保分页状态的准确性。
内容的提问来源于stack exchange,提问作者Andrey Lima Ramos
相关产品推荐
相关产品推荐

