如何使用模型序列化程序将不同的多对多字段添加到 django-rest-framework 中的单个实例或外键行中

How to add different many-to-many field into a single instance or row of a foreign key in django-rest-framework using model serializer

我正在使用 Django-rest-framework 和 React 创建一个电子商务网站。我正在尝试将商品添加到购物车。我可以在前端将商品添加到购物车,但我想将购物车数据存储到后端(Django)数据库,这样每当用户将商品添加到购物车并重新加载页面时,商品仍应像任何商品一样在他的购物车中其他电子商务网站。这是我的 Django 模型、序列化程序、视图集代码。

class Products(models.Model):
    title = models.CharField(max_length=100)
    image = models.URLField()
    description = models.TextField(max_length=500, blank=True, null=True)
    category = models.CharField(max_length=50, blank=True, null=True)
    rating = models.IntegerField(blank=True, null=True)
    price = models.FloatField()

    def __str__(self):
        return f"{self.id}"

class Cart(models.Model):
    product = models.ManyToManyField(
        Products, related_name="cart")
    buyer = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="cart")

    def __str__(self) -> str:
        return f"{self.buyer}"
class ProductsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Products
        fields = '__all__'

class CartSerializer(serializers.ModelSerializer):
    class Meta:
        model = Cart
        fields = '__all__'

class ProductsViewSet(viewsets.ModelViewSet):
    queryset = Products.objects.all()
    serializer_class = ProductsSerializer

class CartViewSet(viewsets.ModelViewSet):
    queryset = Cart.objects.all()
    authentication_classes = [JWTAuthentication]
    permission_classes = [
        permissions.IsAuthenticated
    ]
    serializer_class = CartSerializer

router = routers.DefaultRouter()
router.register('products', ProductsViewSet, 'products')
router.register('cart', CartViewSet, 'cart')

我正在使用 post人工 post 购物车商品。我可以为单个买家添加多个产品。

但问题是,当我再次使用之前添加的 postman 向同一用户添加另一个产品时,它会为同一用户创建另一行。

我不想这样。我想要购物车 table 中的单个用户实例或行,并添加任意数量的产品。当我 post 同一用户的其他产品时,该产品也应该添加到单个用户行或实例中。实现我的目标的最佳方法是什么。

这是问题所在,Django 无法自动执行此操作,因为它不知道预期的行为是什么。如果您查看添加产品的代码和添加购物车的代码,它们是完全一样的。所以行为也会是一样的。

对于您想要的行为,您必须重写 ModelViewSet 的创建方法。 以下是实现您想要的目标的步骤 -

  1. 检查具有该 ID 的用户是否已有购物车。

  2. 如果他们有购物车,那么您需要获取属于该用户的购物车对象并向其中添加产品。

  3. 如果他们不这样做,那么您将不得不创建一个新的购物车对象并执行默认操作。

    class CartViewSet(viewsets.ModelViewSet):
        queryset = Cart.objects.all()
        authentication_classes = [JWTAuthentication]
        permission_classes = [
            permissions.IsAuthenticated
        ]
        serializer_class = CartSerializer
    
        def create(self, request):
            # Checking whether the Cart object already exists for the buyer
            cart = Cart.objects.filter(buyer_id = request.data.get("buyer"))
    
            if len(cart)=1:
                #If cart exists, we loop through the list of product ids and add them
                for product_id in request.data.get("product"):
                    cart[0].product.add(get_object_or_404(Product, id = product_id ))
    
            if len(cart)=0:
                # Doing what normally happens.
                return super().create(request)
    
            if len(cart)>1:
                #Error in database. One person having multiple carts. Custom error message.
    

要查看如何将数据添加到多对多字段,请查看 this