Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Django product variation model – how to get distinct color

I am building a ecommerse store with django. One of the requirement is that a product can have a color and different sizes. I also want to keep track of the quantity of each size.
I can create ProductVariation like product=’test’, size=’small’, color=’red’, quantity=5 , product=’test’, size=’large’, color=’red’, quantity=10. Now in db there are two objects created,how can I query that I only get color red in queryset when I am rendering product details.

I looked at this example – Django Products model for e-commerce site
but did not understand this bit –

Color.objects.filter(productvariant__product=some_product).distinct()

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

These are my models:

class Product(models.Model):
    """
    Product model to allow creating product records and linking with category 
    """
    product_uuid = models.UUIDField(
        default=uuid.uuid4, editable=False, unique=True)
    product_name = models.CharField(max_length=255)
    sub_category = models.ForeignKey(
        'SubCategory', on_delete=models.CASCADE, related_name='products')
    product_description = models.TextField()
    is_featured = models.BooleanField(default=False)
    product_sku = models.CharField(max_length=255, null=True, blank=True)
    product_price = models.DecimalField(max_digits=6, decimal_places=2)

    def __str__(self):
        return self.product_name

    class Meta:
        verbose_name = 'Product'
        verbose_name_plural = 'Products'

class ProductVariation(models.Model):
    """
    ProductVariation model to allow creating product with different size and color
    """
    product_var_uuid = models.UUIDField(
        default=uuid.uuid4, editable=False, unique=True)
    product = models.ForeignKey(
        'Product', on_delete=models.CASCADE, related_name='product_variations')
    size = models.ForeignKey('Size', on_delete=models.CASCADE, related_name="product_sizes")
    color = models.ForeignKey('Color', on_delete=models.CASCADE, related_name="color")
    quantity = models .IntegerField()

    def __str__(self):
        return self.product.product_name

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['product', 'color', 'size'],
                name='unique_prod_color_size_combo'
            )
        ]
        verbose_name = 'Product Variation'
        verbose_name_plural = 'Product Variations'


class Size(models.Model):
    product_size_uuid = models.UUIDField(
        default=uuid.uuid4, editable=False, unique=True)
    product_size = models.CharField(max_length=20)

    def __str__(self):
        return self.product_size

    class Meta:
        verbose_name = 'Product Size'
        verbose_name_plural = 'Product Sizes'

class Color(models.Model):
    product_color_uuid = models.UUIDField(
        default=uuid.uuid4, editable=False, unique=True)
    product_color = models.CharField(max_length=20)

    def __str__(self):
        return self.product_color

    class Meta:
        verbose_name = 'Product Color'
        verbose_name_plural = 'Product Colors'

>Solution :

What we do here is filter by joining on the ProductVariant and then on the Product, so with a query:

Color.objects.filter(color__product=some_product).distinct()

but this is because the related_name of color in ProductVariation is color which makes not much sense. That should be something like:

class ProductVariation(models.Model):
    # …
    color = models.ForeignKey(
        'Color', on_delete=models.CASCADE, related_name='product_variants'
    )
    # …

since it is the name of the relation in reverse. In that case we filter with:

Color.objects.filter(product_variants__product=some_product).distinct()

This will then make a query that looks like:

SELECT DISTINCT color.*
FROM color
INNER JOIN productvariation ON color.id = productvariation.color_id
WHERE productvariation.product_id = some_product_id
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading