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

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的写法没有问题,不需要调整。

核心知识点盲区
  1. DRF序列化器两类使用场景的参数差异
    • 序列化输出(数据库 -> 前端响应):将查询得到的模型实例/QuerySet作为第一个位置参数(即instance参数)传入序列化器,处理多条数据必须加many=True,不需要调用is_valid()做校验,直接访问.data属性即可得到可返回的JSON结构数据。
    • 反序列化输入(前端请求 -> 校验入库):将前端提交的请求数据传给data参数,必须先调用is_valid()校验通过,才能访问validated_data执行创建/更新数据库的操作。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 17:30:50