Django序列化嵌套JSON时userSerializer报AttributeError解决
嵌套JSON接口问题排查与修正
报错直接原因
你组装返回数据时逻辑错位,传给子序列化器的user字段值是字符串而非用户对象列表;同时嵌套字段的序列化配置错误,DRF执行序列化时,子序列化器在字符串实例上查找email/username属性,就触发了AttributeError。
逐文件问题定位
Serializer 层问题
- 顶层字段名和需求不匹配:需求返回的字段是
rule,代码里写的是rules,字段名不一致会导致取数失败。 - 嵌套字段的
source参数配置错误:source='*'代表将整个当前对象作为值传给子序列化器,和你要取对象中存储用户列表的字典键值的需求完全不符。 - 字段映射和View返回的数据结构没有做对齐,没有明确告诉DRF从哪个键读取用户列表数据。
View 层问题
- 核心组装逻辑错误:你用
dict(zip(keys, row))组装返回字典时,第二个参数row是dictfetchall返回的字典对象,直接迭代字典得到的是字典的键名而非对应的值。最终拼出来的字典里,user键对应的值是字符串'details',根本不是用户列表。 - 子查询参数逻辑错误:循环父规则数据时,子查询传入的参数是全局登录用户,没有传入当前循环规则的关联标识,会导致所有规则拿到完全相同的用户列表,不符合业务逻辑。
- 用户列表存储的键名错误:你已经通过
dictfetchall把子查询结果转成了带email/username的字典列表,却硬编码赋值给了data['details'],没有把用户列表存到Serializer期望的user键下。 - 父数据组装键名不匹配:硬编码的键元组里
rules是复数,和实际数据里的rule字段名不一致,就算组装逻辑对了,也会出现字段值取不到的问题。 - 子查询SQL存在语法错误:代码里子查询字符串末尾多了一个右括号,会导致SQL执行失败。
- 冗余逻辑:循环内部每次都把全量父数据转成JSON打印,没有实际业务作用,还会增加接口开销。
修正后可直接运行的代码
serializer.py
from rest_framework import serializers class UserSerializer(serializers.Serializer): email = serializers.CharField() username = serializers.CharField() class CloudScoreAnalysisSerializer(serializers.Serializer): # 字段名和需求返回结构完全对齐 rule = serializers.CharField() criticality = serializers.CharField() # 移除错误的source配置,默认从对象的user键读取用户列表 user = UserSerializer(many=True)
views.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.db import connection class ScoreAnalysisView(APIView): def queryset_scoreAnalysisView(self, user): cursor = connection.cursor() child_cursor = connection.cursor() # 执行父查询:获取当前用户关联的所有规则数据 cursor.execute("你的父数据MySQL查询SQL", (user,)) parent_rows = self.dictfetchall(cursor) result = [] for row in parent_rows: # 传入当前规则的关联标识到子查询,替换成你实际表结构的关联字段 current_related_id = row["规则关联字段名"] # 执行子查询:获取当前规则关联的所有用户数据 child_cursor.execute("你的子数据MySQL查询SQL", (current_related_id,)) user_rows = self.dictfetchall(child_cursor) # 组装和Serializer结构完全匹配的字典 result.append({ "rule": row["rule"], "criticality": row["criticality"], "user": user_rows }) return result def get(self, request): result = self.queryset_scoreAnalysisView(request.user) serializer = CloudScoreAnalysisSerializer(result, many=True) return Response(serializer.data, status=status.HTTP_200_OK) def dictfetchall(self, cursor): "Returns all rows from a cursor as a dict" desc = cursor.description return [ dict(zip([col[0] for col in desc], row)) for row in cursor.fetchall() ]
代码调整后,接口会返回你需求中指定的嵌套JSON结构,不会再触发字段匹配的AttributeError。
内容的提问来源于stack exchange,提问作者Anurag Kumar Pandey
相关产品推荐
相关产品推荐

