Django REST Framework嵌套序列化器报错:QuerySet类型对象无法JSON序列化
解决QuerySet无法JSON序列化的问题
你遇到的这个TypeError: Object of type QuerySet is not JSON serializable错误,说白了就是Python的json.dumps()根本认不出Django返回的QuerySet对象,而且你的视图代码里还有几个逻辑问题,我来帮你一步步理顺:
错误核心原因
FreeTime.objects.all().values()返回的是Django特有的QuerySet对象,不是原生Python的可序列化类型(比如列表、字典),所以json.dumps()直接处理它就会报错。而且你手动拼接字典再转JSON的操作完全多余,DRF的序列化器本来就可以帮你搞定这一切。
修正后的完整代码
首先你的序列化器部分没问题,直接保留:
class UsersInfoSeriliazerByUsers(serializers.ModelSerializer): class Meta: model = FreeTime fields = '__all__' class SetTimeZoneSerializer(serializers.Serializer): TIMEZONES = tuple(zip(pytz.all_timezones, pytz.all_timezones)) meeting_date = serializers.DateField(format="%d-%m-%Y", input_formats= ['%d-%m-%Y', 'iso-8601']) time_zone_destination = serializers.ChoiceField(choices=TIMEZONES) time_table = UsersInfoSeriliazerByUsers(many=True, read_only=True)
然后是彻底修正后的视图方法:
from rest_framework.response import Response from rest_framework import status @action(detail=False, methods=['post']) def common(self, request): # 先验证前端传入的请求数据 serializer = SetTimeZoneSerializer(data=request.data) if serializer.is_valid(): # 从验证后的数据里取字段(比直接用data更靠谱,已经是转换后的数据类型) meeting_date = serializer.validated_data['meeting_date'] time_zone_destination = serializer.validated_data['time_zone_destination'] # 这里可以根据业务需求过滤FreeTime,比如按meeting_date筛选,暂时用all()示例 free_time_list = FreeTime.objects.all() # 拼接要返回的完整数据结构 response_data = { 'meeting_date': meeting_date, 'time_zone_destination': time_zone_destination, 'time_table': free_time_list } # 用序列化器处理完整数据,嵌套的time_table会自动用UsersInfoSeriliazerByUsers序列化 result_serializer = SetTimeZoneSerializer(response_data) # DRF的Response会自动帮你把数据转成JSON返回 return Response(result_serializer.data) # 如果验证失败,返回错误信息 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
关键修复点说明
- 抛弃手动JSON序列化:完全用DRF的序列化器来处理数据,它会自动处理嵌套字段的序列化,包括把QuerySet转成可序列化的列表。
- 用validated_data而非data:
validated_data是经过DRF验证和类型转换后的正确数据(比如日期已经是datetime.date对象,不是字符串),比直接取request.data或者serializer.data更安全。 - 正确初始化序列化器:第二次初始化的时候直接传Python字典,不需要转成JSON字符串,也不需要加
many=True(因为这是单个数据对象,不是列表)。 - 返回Response对象:DRF会自动处理JSON序列化和响应头,不需要手动调用
json.dumps()。
备选方案(如果你非要手动处理QuerySet)
如果因为某些特殊情况,你不想用DRF序列化器处理time_table,可以把QuerySet转成原生Python列表:
j['time_table'] = list(FreeTime.objects.all().values())
但这种方式不如用序列化器优雅,因为values()返回的只是简单字典列表,没办法处理模型字段的自定义逻辑、关联关系等,还是推荐用DRF的序列化器方案。
内容的提问来源于stack exchange,提问作者Niloofar
相关产品推荐
相关产品推荐

