如何使用模型序列化程序将不同的多对多字段添加到 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 的创建方法。
以下是实现您想要的目标的步骤 -
检查具有该 ID 的用户是否已有购物车。
如果他们有购物车,那么您需要获取属于该用户的购物车对象并向其中添加产品。
如果他们不这样做,那么您将不得不创建一个新的购物车对象并执行默认操作。
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。
我正在使用 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 的创建方法。 以下是实现您想要的目标的步骤 -
检查具有该 ID 的用户是否已有购物车。
如果他们有购物车,那么您需要获取属于该用户的购物车对象并向其中添加产品。
如果他们不这样做,那么您将不得不创建一个新的购物车对象并执行默认操作。
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。