Search code examples
pythondjangomodel

Django If both product and variant models have color model, how to make Product limit which colors can variant have?


I have 4 models, product, variant and color.

class Size(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)

class Color(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)

class Product(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField(max_length=400)
    colors = models.ManyToManyField(Color)
    sizes = models.ManyToManyField(Size)

class Variant(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    price = models.DecimalField(decimal_places=2, max_digits=10,
                                validators=[MinValueValidator(Decimal('0.01'))])
    quantity = models.IntegerField(validators=[MinValueValidator(0)])
    color = models.ForeignKey(Color, on_delete=models.CASCADE)
    size = models.ForeignKey(Size, on_delete=models.CASCADE)

In this example a variant can have 1 product, 1 color and 1 size. The problem is the color and size are chosen among all the colors and sizes in the store. I want to limit the color and size in variant to the options of colors and size that were chosen in Product.

If there anyway please let me know. Thank you :)


Solution

  • Logically to restrict the conditions as per your requirements, you should override the save method of the Variant model and tell the method to verify the colors and sizes are the ones that belong to current product mentioned in the object to be created.

    def save(self, *args, **kwargs):
        if self.color not in self.product.colors.all():
            raise ValidationError("Selected color is not valid <OR ANY MESSAGE YOU WANT TO SHOW>")
        if self.size not in self.product.sizes.all():
            raise ValidationError("Selected color is not valid <OR ANY MESSAGE YOU WANT TO SHOW>")            
        super().save(*args, **kwargs)
    

    Let me know if it helps or not.