Django分组嵌套序列化器聚合报错:int对象无code属性
解决嵌套序列化器聚合时的AttributeError问题
嘿,我来帮你搞定这个报错!你遇到的AttributeError本质原因是查询返回的数据格式和序列化器期望的不匹配,具体来说:
你的get_queryset方法里用了Trade.objects.values('country').annotate(...),这个写法返回的是一组字典,其中country字段的值是国家的ID(整数类型),而不是完整的Country模型实例。但你的TradeAggregateSerializers里的country字段用的是CountrySerializers,它需要接收一个Country对象才能序列化出code、name等字段,面对整数ID自然就会报错说“int对象没有code属性”。
下面给你两种解决方案,优先推荐第一种(性能更优):
方案一:从Country模型入手做聚合(推荐)
这种方式直接从Country模型出发,关联Trade表完成聚合查询,返回的是完整的Country实例,完美适配嵌套序列化器。
1. 修改序列化器
新增一个继承自CountrySerializers的序列化器,添加聚合结果字段:
class CountryWithAggregateSerializer(CountrySerializers): # 字段参数和Trade里的decimal字段匹配 value = serializers.DecimalField(max_digits=15, decimal_places=2, read_only=True) class Meta(CountrySerializers.Meta): # 保留原有的国家字段,新增value字段 fields = CountrySerializers.Meta.fields + ('value',)
2. 调整视图逻辑
修改视图的查询集,从Country模型做聚合,同时增加参数合法性校验:
class TradeAggragateViewSet(viewsets.ModelViewSet): queryset = Country.objects.all() serializer_class = CountryWithAggregateSerializer def get_queryset(self): data_type = self.request.GET.get('data_type') # 验证传入的参数是否合法,避免非法字段或SQL注入风险 allowed_fields = ['imports', 'exports'] if data_type not in allowed_fields: # 可以返回空查询集,或者抛出400 Bad Request错误 return Country.objects.none() # 关联Trade表,动态指定聚合字段,计算平均值 queryset = Country.objects.annotate( value=models.Avg(f'trade__{data_type}') ).filter(value__isnull=False) # 过滤掉没有贸易数据的国家(可选) return queryset
方案二:修改序列化器适配字典数据(不推荐,有N+1查询问题)
如果你坚持要从Trade模型查询,可以用SerializerMethodField手动根据ID获取国家信息,但这种方式会触发N+1查询(每个国家单独查一次数据库),性能较差:
class TradeAggregateSerializers(serializers.ModelSerializer): country = serializers.SerializerMethodField() value = serializers.DecimalField(max_digits=15, decimal_places=2) def get_country(self, obj): # obj是values返回的字典,obj['country']是国家ID country = Country.objects.get(id=obj['country']) return CountrySerializers(country).data class Meta: model = Trade fields = ('country','value')
额外提醒
- 一定要做参数合法性校验,避免用户传入
imports/exports之外的字段,防止错误或安全问题。 - 方案一中的
filter(value__isnull=False)可以过滤掉没有任何贸易记录的国家,如果你需要保留这些国家(value为null),可以去掉这个过滤条件。
内容的提问来源于stack exchange,提问作者Hassam.C
相关产品推荐
相关产品推荐

