使用cart_serializer触发AttributeError:QuerySet无user属性求助
问题原因
你遇到的AttributeError: 'QuerySet' object has no attribute 'user'核心原因是序列化器与传入的数据类型不匹配:
cart_serializer的Meta类指定了model = Cart,说明它是用来序列化Cart模型实例的;- 但你在视图中传给序列化器的是
cart_items,这是CartItems模型的QuerySet(集合),而CartItems实例并没有user属性(user是Cart模型的字段),所以序列化器尝试读取user字段时直接抛出错误。
修正方案
方案1:匹配序列化器与数据类型(推荐)
因为你的序列化器是为Cart模型设计的,所以应该把获取到的cart对象传给它,同时通过嵌套序列化器返回购物车项数据:
- 先创建
CartItems的序列化器:
# Serializer.py class CartItemsSerializer(ModelSerializer): class Meta: model = CartItems fields = ["id", "product", "quantity", "sub_total"]
- 修改
cart_serializer,添加嵌套字段并优化汇总逻辑:
# Serializer.py class cart_serializer(ModelSerializer): total = SerializerMethodField() delivery = SerializerMethodField() grand_total = SerializerMethodField() cart_items = CartItemsSerializer(many=True, source='cartitems_set') # 关联CartItems反向集合 class Meta: model = Cart fields = ["id", "user", "cart_items", "total", "delivery", "grand_total"] def get_total(self, obj): # 直接通过Cart实例关联的购物车项计算总价 return sum(item.sub_total() for item in obj.cartitems_set.all()) def get_delivery(self, *args, **kwargs): return 150 # 固定配送费直接返回,也可从配置/context传入 def get_grand_total(self, obj): return self.get_total(obj) + self.get_delivery()
- 调整视图,传入
Cart实例给序列化器:
# Views.py class view_cart(APIView): permission_classes = [IsAuthenticated] def get(self, request): cart = Cart.objects.get(user=request.user) serializer = cart_serializer(cart) return Response(serializer.data)
方案2:若仅需返回购物车项与汇总数据
如果你不需要Cart模型的其他字段,也可以重新设计序列化器针对CartItems,但此时要移除user字段(因为CartItems没有该属性):
# Serializer.py class CartItemsWithTotalSerializer(ModelSerializer): total = SerializerMethodField() delivery = SerializerMethodField() grand_total = SerializerMethodField() class Meta: model = CartItems fields = ["id", "product", "quantity", "sub_total", "total", "delivery", "grand_total"] def get_total(self, obj): return self.context.get("total", 0) def get_delivery(self, obj): return self.context.get("delivery", 0) def get_grand_total(self, obj): return self.context.get("grand_total", 0)
视图中保持总价计算逻辑,传入cart_items时添加many=True(因为是QuerySet):
# Views.py serializer = CartItemsWithTotalSerializer( cart_items, many=True, context={"total": total, "grand_total": grand_total, "delivery": delivery}, )
额外说明
- Django外键反向关联默认名称为
模型名小写_set,比如Cart实例通过cart.cartitems_set.all()获取关联的购物车项;若要自定义名称,可在CartItems的外键中添加related_name参数,例如cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items'),之后即可用cart.items.all()访问。
内容的提问来源于stack exchange,提问作者Sins97
相关产品推荐
相关产品推荐

