Django连接MongoDB查询报错:JSON对象需为str/bytes而非OrderedDict
解决Django+MongoDB获取数据时的TypeError:JSON对象需为str/bytes而非OrderedDict
问题场景
使用Django配合Djongo连接MongoDB获取员工数据时,持续报错:
Exception Type: TypeError at /api/employes/ Exception Value: the JSON object must be str, bytes or bytearray, not OrderedDict
相关环境与代码
员工集合数据格式
{ "_id": { "$oid": "511d0a9f181b16509ae5f7dd" }, "nom": "Leberre", "prenom": "Stephanie", "anciennete": 1, "adresse": { "numero": 79, "codepostal": 9500, "ville": "Toulouse", "rue": "Jean Moulin" }, "tel": 559608352, "prime": 1500 }
models.py
from django.db import models class Employee(models.Model): nom = models.CharField(max_length=100) prenom = models.CharField(max_length=100) anciennete = models.IntegerField() adresse = models.JSONField() tel = models.CharField(max_length=20, blank=True, null=True) prime = models.IntegerField(blank=True, null=True) def __str__(self): return f"{self.nom}, {self.prenom}"
serializers.py
from rest_framework import serializers from .models import Employee class EmployeeSerializer(serializers.ModelSerializer): class Meta: model = Employee fields = '__all__'
views.py
from rest_framework.response import Response from rest_framework import generics from .models import Employee from .serializers import EmployeeSerializer class EmployeeListView(generics.ListAPIView): queryset = Employee.objects.all() serializer_class = EmployeeSerializer def list(self, request, *args, **kwargs): serializer = self.get_serializer(self.get_queryset(), many=True) return Response(serializer.data)
settings.py数据库配置
DATABASES = { 'default': { 'ENGINE': 'djongo', 'NAME': 'employes', } }
解决方法
方案1:自定义JSON字段处理OrderedDict转换
修改models.py,替换默认的JSONField为自定义字段,确保从MongoDB读取的OrderedDict能转为可序列化的字典:
from django.db import models from django.core.serializers.json import DjangoJSONEncoder from collections import OrderedDict class MongoJSONField(models.JSONField): def from_db_value(self, value, expression, connection): if isinstance(value, OrderedDict): return dict(value) return super().from_db_value(value, expression, connection) class Employee(models.Model): nom = models.CharField(max_length=100) prenom = models.CharField(max_length=100) anciennete = models.IntegerField() adresse = MongoJSONField(encoder=DjangoJSONEncoder) tel = models.CharField(max_length=20, blank=True, null=True) prime = models.IntegerField(blank=True, null=True) def __str__(self): return f"{self.nom}, {self.prenom}"
方案2:在序列化器中显式处理adresse字段
修改serializers.py,对adresse字段添加自定义序列化方法,将OrderedDict转为普通字典:
from rest_framework import serializers from .models import Employee from collections import OrderedDict class EmployeeSerializer(serializers.ModelSerializer): adresse = serializers.SerializerMethodField() class Meta: model = Employee fields = '__all__' def get_adresse(self, obj): if isinstance(obj.adresse, OrderedDict): return dict(obj.adresse) return obj.adresse
方案3:调整Djongo配置强制返回普通字典
修改settings.py的数据库配置,添加OPTIONS让Djongo使用普通字典而非OrderedDict:
DATABASES = { 'default': { 'ENGINE': 'djongo', 'NAME': 'employes', 'OPTIONS': { 'use_legacy_json': False, 'json_options': { 'object_pairs_hook': dict } } } }
验证方法
修改完成后,重启Django服务,访问/api/employes/接口,确认数据能正常返回,无TypeError报错。
内容的提问来源于stack exchange,提问作者G.M.T.K
相关产品推荐
相关产品推荐

