Django+Djongo集成MongoDB时DRF序列化器报QuerySet类型错误求助
问题概述
- 开发场景:基于Django + Djongo驱动对接MongoDB,实现订单列表查询接口
- 报错信息:
"non_field_errors": [ "Invalid data. Expected a dictionary, but got QuerySet." ] - 报错截图:

- 原有代码实现:
models.py
from djongo import models class OrderItem(models.Model): itemDescription = models.TextField(name = "itemDescription") itemQuantity = models.FloatField(name = "itemQuantity") itemPrice = models.FloatField(name = "itemPrice") class Meta: abstract = True class Order(models.Model): email = models.EmailField(primary_key = True, name = "email") customerName = models.CharField(max_length=30, help_text="Enter Customer Name", name = "customerName") customerAddress = models.TextField(help_text="Enter customer's Address", name = "customerAddress") orderItems = models.ArrayField( model_container = OrderItem, ) objects = models.DjongoManager()serializers.py
from .models import Order, OrderItem from rest_framework.serializers import ModelSerializer class OrderItemsSerializer(ModelSerializer): class Meta: model = OrderItem fields = '__all__' class OrderSerializer(ModelSerializer): orderItems = OrderItemsSerializer(many=True) class Meta: model = Order fields = "__all__"views.py
@api_view(['GET']) def getOrders(request): orders = Order.objects.values() serializer = OrderSerializer(data = orders) if serializer.is_valid(): print("Valid") return Response(data = serializer.data) else: print("invalid") print(serializer.errors) return Response(serializer.errors) - MongoDB中存储的测试数据结构:
[ { "email": "himanshu@gmail.com", "customerName": "Himanshu Maiyani", "customerAddress": "B-4-102, Gadhpur Township", "orderItems": [ { "itemDescription": "pencil", "itemQuantity": 10, "itemPrice": 35.0 }, { "itemDescription": "books", "itemQuantity": 12, "itemPrice": 600.0 }, { "itemDescription": "school bag", "itemQuantity": 1, "itemPrice": 800.0 } ] }, { "email": "jayesh@gmail.com", "customerName": "Jayesh Maiyani", "customerAddress": "C-1-103, Gadhpur Township", "orderItems": [ { "itemDescription": "watch", "itemQuantity": 5, "itemPrice": 5000.0 }, { "itemDescription": "earphone", "itemQuantity": 2, "itemPrice": 995.5 }, { "itemDescription": "USB cable", "itemQuantity": 1, "itemPrice": 100.0 } ] } ]
问题根因
报错完全由视图层DRF序列化器的错误调用方式导致,具体问题点:
- 混淆了DRF序列化器序列化输出和反序列化校验两个场景的传参规则:当前接口是查询类接口,需要把数据库查出的结果转成JSON返回,属于序列化输出场景,但代码把QuerySet传给了
data参数——data参数是专门用来接收前端提交的、待校验入库的原始数据的,序列化器默认预期data是单条字典结构,拿到QuerySet类型直接报类型不匹配错误。 - 处理多条数据的QuerySet时,没有给序列化器加
many=True参数,序列化器会默认按单条对象的结构解析,无法处理列表/QuerySet类型的数据集。 - 存在冗余写法:
Order.objects.values()返回的是ValuesQuerySet,并不是直接的原生字典列表,做序列化输出时完全不需要调用values(),直接查询模型实例即可。
注:当前models层和serializers层的嵌套映射逻辑是正确的,Djongo的ArrayField搭配嵌套序列化器加many=True的写法没有问题,不需要调整。
核心知识点盲区
- DRF序列化器两类使用场景的参数差异
- 序列化输出(数据库 -> 前端响应):将查询得到的模型实例/QuerySet作为第一个位置参数(即
instance参数)传入序列化器,处理多条数据必须加many=True,不需要调用is_valid()做校验,直接访问.data属性即可得到可返回的JSON结构数据。 - 反序列化输入(前端请求 -> 校验入库):将前端提交的请求数据传给
data参数,必须先调用is_valid()校验通过,才能访问validated_data执行创建/更新数据库的操作。
- 序列化输出(数据库 -> 前端响应):将查询得到的模型实例/QuerySet作为第一个位置参数(即
- Djongo查询集特性:
Order.objects.all()返回的模型实例QuerySet已经自动加载了嵌套的orderItems数组字段数据,不需要额外调用values()做字段转换,DRF序列化器可以自动完成嵌套字段的映射输出。
修正方案
仅需要调整views.py中的逻辑即可,models和serializers代码不需要改动:
from rest_framework.decorators import api_view from rest_framework.response import Response from .models import Order from .serializers import OrderSerializer @api_view(['GET']) def getOrders(request): # 直接查询所有订单的模型实例,不需要调用values() orders = Order.objects.all() # 序列化输出:传入查询集,多条数据加many=True,不需要传data参数 serializer = OrderSerializer(orders, many=True) # 直接返回序列化后的数据,不需要走is_valid校验 return Response(serializer.data)
单条数据查询的参考写法(不需要加many=True):
@api_view(['GET']) def getOrder(request, email): order = Order.objects.get(pk=email) serializer = OrderSerializer(order) return Response(serializer.data)
内容的提问来源于stack exchange,提问作者Jayesh Maiyani
相关产品推荐
相关产品推荐

