0

Before my product model doesnt include variants. Now I have added variants which is ManytoMany relationships with Product model. Variants model consists of fields like color,size,price etc. I had already created api endpoints for adding items to wishlist.

Now, if I had added with same api, it will includes all the variants. But,in frontend, user has the flexibility of choosing only a single varaint.

How to change this?

My models:

    class Variants(models.Model):
        SIZE = (
            ('not applicable', 'not applicable',),
            ('S', 'Small',),
            ('M', 'Medium',),
            ('L', 'Large',),
            ('XL', 'Extra Large',),
        )
        AVAILABILITY = (
            ('available', 'Available',),
            ('not_available', 'Not Available',),
        )
        price = models.DecimalField(decimal_places=2, max_digits=20,blank=True,null=True)
        size = models.CharField(max_length=50, choices=SIZE, default='not applicable',blank=True,null=True)
        color = models.CharField(max_length=70, default="not applicable",blank=True,null=True)
        quantity = models.IntegerField(default=10,blank=True,null=True)  # available quantity of given product
        vairant_availability = models.CharField(max_length=70, choices=AVAILABILITY, default='available')
    
        class Meta:
            verbose_name_plural = "Variants"
    
    
    class Product(models.Model):
        AVAILABILITY = (
            ('in_stock', 'In Stock',),
            ('not_available', 'Not Available',),
            )
        WARRANTY = (
            ('no_warranty', 'No Warranty',),
            ('local_seller_warranty', 'Local Seller Warranty',),
            ('brand_warranty', 'Brand Warranty',),
        )
        SERVICES = (
            ('cash_on_delivery', 'Cash On Delivery',),
            ('free_shipping', 'Free Shipping',),
        )
        
        category = models.ManyToManyField(Category, blank=False)
        brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
        collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
        featured = models.BooleanField(default=False)  # is product featured?
        best_seller = models.BooleanField(default=False)
        top_rated = models.BooleanField(default=False)
        tags = TaggableManager(blank=True)  # tags mechanism
        name = models.CharField(max_length=150)            
        picture = models.ManyToManyField(ImageBucket,null=True,blank=True)
        availability = models.CharField(max_length=70, choices=AVAILABILITY, default='in_stock')
        warranty = models.CharField(max_length=100, choices=WARRANTY, default='no_warranty')
        services = models.CharField(max_length=100, choices=SERVICES, default='cash_on_delivery')
        variants = models.ManyToManyField(Variants,blank=True,null=True,related_name='products')

    class Meta:
        ordering = ("name",)

    def __str__(self):
        return self.name

class WishListItems(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE,blank=True)
    #wishlist = models.ForeignKey(WishList,on_delete=models.CASCADE, related_name='wishlistitems')
    item = models.ForeignKey(Product, on_delete=models.CASCADE,blank=True, null=True)

My views:

class AddtoWishListItemsView(CreateAPIView,DestroyAPIView):
    permission_classes = [IsAuthenticated]
    queryset = WishListItems.objects.all()
    serializer_class = WishListItemsTestSerializer

    def perform_create(self, serializer):
        user = self.request.user
        if not user.is_seller:
            item = get_object_or_404(Product, pk=self.kwargs['pk'])
            serializer.save(owner=user, item=item)
        else:                
            raise serializers.ValidationError("This is not a customer account.Please login as customer.")


    def perform_destroy(self, instance):
        instance.delete()

My serializers:

class WishListItemsTestSerializer(serializers.ModelSerializer):    
    class Meta:
        model = WishListItems
        fields = ['id','item']
        depth = 2

My url:

path('api/addwishlistitems/<int:pk>', views.AddtoWishListItemsView.as_view(),name='add-to-wishlist'),
Reactoo
  • 916
  • 2
  • 12
  • 40

1 Answers1

1

I think you need to add the variant in the model WishListItems.

You need to start from to serialize the "father" model Product, like this:

from rest_framework import serializers


class VariantSerializer(serializers.ModelSerializer):    

    class Meta:
       model = Variant
       fields = "__all__"


class ProductSerializer(serializers.ModelSerializer):    
    variants = VariantSerializer(many=True, read_only=True)

    class Meta:
       model = Product
       fields = "__all__"


class WishListItemsTestSerializer(serializers.ModelSerializer): 
    item = ProductSerializer(read_only=True)

    class Meta:
        model = WishListItems
        fields = ['id','item', 'variant']

DRF documentation

Bonus!. If you want simplify to fill the related variants you can use this from drf_writable_nested import WritableNestedModelSerializer drf writable

from rest_framework import serializers
from drf_writable_nested import WritableNestedModelSerializer


class VariantSerializer(serializers.ModelSerializer):    

    class Meta:
       model = Variant
       fields = "__all__"


class ProductSerializer(WritableNestedModelSerializer):    
    variants = VariantSerializer(many=True)

    class Meta:
       model = Product
       fields = "__all__"


class WishListItemsTestSerializer(serializers.ModelSerializer): 
    item = ProductSerializer()

    class Meta:
        model = WishListItems
        fields = ['id','item', 'variant']
  • I have wishlits model in diffrent app named order. So serializers of products and variants are not recognised in orderserializer. I have imported the serializer but this variants = VariantSerializer(many=True, read_only=True) is not recognised, ie many=True is not suggested. – Reactoo Mar 09 '21 at 10:44