validated_data 在更新时返回空字典

问题描述 投票:0回答:1

我正在构建一个像Udemy这样的后端系统,在这个Cart API中,我试图更新一个caritem对象(一个学生想要添加另一门课程而不是这门课程),所以我想更改caritem中的课程并更改total_price购物车。发生的情况是,当我更新课程字段时,它返回 HTTP_200_OK 响应状态,但响应正文是更新前完全相同的对象的 JSON 对象,并且该对象未更新

模型.py

class Cart(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4)
    student = models.OneToOneField(
        User, on_delete=models.CASCADE, related_name='cart')
    total_price = models.IntegerField(default=0)


class CartItem(models.Model):
    cart = models.ForeignKey(
        Cart, on_delete=models.CASCADE, related_name='items')
    course = models.ForeignKey(Course, on_delete=models.CASCADE)

views.py

class CartItemViewSet(ModelViewSet):
    http_method_names = ['get', 'post', 'put', 'delete']

    def get_queryset(self):
        return CartItem.objects.filter(cart_id=self.kwargs['cart_pk'])

    def get_serializer_class(self):
        if self.request.method == 'PUT':
            return UpdateCartItemSerializer
        elif self.request.method == 'POST':
            return CreateCartItemSerializer
        else:
            return CartItemSerializer

    def get_serializer_context(self):
        return {
            'cart_id': self.kwargs['cart_pk']
        }

序列化器.py

class CartItemSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    student_id = serializers.SerializerMethodField(read_only=True)

    def get_student_id(self, cart_item):
        return Cart.objects.filter(id=self.context['cart_id'])[0].student_id

    class Meta:
        model = CartItem
        fields = ['id', 'student_id', 'course_id']


class CreateCartItemSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)

    def create(self, validated_data):
        instance = CartItem.objects.get(cart_id=validated_data['cart_id'],
                course_id=validated_data['course_id'])

        try:
            return instance
        except CartItem.DoesNotExist:
            instance = CartItem.objects.create(**validated_data)
            instance.save()

        return instance

    class Meta:
        model = CartItem
        fields = ['id', 'course_id']


class UpdateCartItemSerializer(serializers.ModelSerializer):
    def update(self, instance, validated_data):
        print(instance.__dict__, validated_data)
        current_course_id = instance.course_id
        new_course_id = validated_data.get('course_id', instance.course_id)

        if current_course_id != new_course_id:
            condition = CartItem.objects\
                .filter(cart_id=instance.cart_id) \
                .filter(course_id=new_course_id) \
                .exists()

            if not condition:
                with transaction.atomic():
                    CartItem.objects \
                        .filter(id=instance.id) \
                        .update(course_id=new_course_id)

                    old_price = Course.objects \
                        .filter(id=current_course_id)[0].price

                    new_price = Course.objects \
                        .filter(id=new_course_id)[0].price

                    current_cart_price = Cart.objects \
                        .filter(id=instance.cart_id)[0].total_price

                    current_cart_price -= old_price
                    current_cart_price += new_price

                    Course.objects \
                        .filter(id=new_course_id) \
                        .update(total_price=current_cart_price)

                    instance.save()
            else:
                CartItem.objects.filter(id=instance.id).delete()
                return Response(status=status.HTTP_204_NO_CONTENT)

        return instance

    class Meta:
        model = CartItem
        fields = ['id', 'course_id']
        read_only_fields = ('id', )

在发出 PUT 请求之前 before 发出 PUT 请求后 after

额外问题: 为什么序列化器的 HTML 表单无法识别我的字段?HTML Form

我试图评论所有内容以到达错误的位置,但徒劳。

django django-rest-framework django-serializer
1个回答
0
投票

我认为问题就出在这里。如果我快速浏览后正确理解了您的代码,那么您期望此时

Course.objects.filter(id=new_course_id).update(total_price=current_cart_price)
instance.save()

对象

instance
和对象
Course.objects.filter(id=new_course_id)
是相同的,并且使用
update
后两者具有相同的值。

如果我对你尝试做的事情的理解是正确的,你不应该使用这个逻辑。

update
直接对数据库进行查询,
instance
不刷新,并且不调用模型的
save
方法。

因此,当您在方法结束时返回

instance
时,您将返回模型的旧版本。

所以,使用类似:

Course.objects.filter(id=new_course_id).update(total_price=current_cart_price)
# instance.save() # not needed
instance.refresh_from_db()

# Course.objects.filter(id=new_course_id).update(total_price=current_cart_price)
instance.total_price = current_cart_price
instance.save() # not needed
© www.soinside.com 2019 - 2024. All rights reserved.