Get product color in color filter by Category wise

I am trying to get a specific category products by category slug.I have Color model,Product model and product variation model in shop app.

class Colour(models.Model):
    title = models.CharField(max_length=100)
    color_code = models.CharField(max_length=50,null=True)
class Product(models.Model):
    product_name = models.CharField(max_length=100,unique=True)
    slug = models.SlugField(max_length=100,unique=True)
    content = RichTextUploadingField()
    price = models.IntegerField()
    images = models.ImageField(upload_to='photos/products')
    is_available = models.BooleanField(default=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE,related_name="procat")
    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)
    is_featured = models.BooleanField()

class ProductVaraiant(models.Model):
    product = models.ForeignKey(Product,on_delete=models.CASCADE)
    color = models.ForeignKey(Colour,on_delete=models.CASCADE,blank=True, null=True)
    size = models.ForeignKey(Size, on_delete=models.CASCADE,blank=True, null=True)
    brand = models.ForeignKey(Brand,on_delete=models.CASCADE,blank=True, null=True)
    amount_in_stock = models.IntegerField()

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['product', 'color', 'size','brand'],
                name='unique_prod_color_size_combo'

In my views.py,

def shop(request,category_slug=None):

    categories = None
    products = None
    if category_slug != None:
        categories = get_object_or_404(Category,slug = category_slug)
        products = Product.objects.filter(category=categories,is_available=True).order_by('id')
        variation = ProductVaraiant.objects.filter(product__category = categories)
        print(variation)
        # color = color.objects.all()
        products_count = products.count()
    else:
        products = Product.objects.all().filter(is_available=True).order_by('id')
        products_count = products.count()
        variation = ProductVaraiant.objects.all()
        print(variation)

    context = {
        'products' : products,
        'products_count' : products_count,
        'variation' : variation
    }
    return render(request,'shop/shop.html',context)

my category model,

class Category(MPTTModel):
    parent = TreeForeignKey('self',blank=True,null=True,related_name='children',on_delete=models.CASCADE)
    category_name = models.CharField(max_length=200,unique=True)
    category_img = models.ImageField(upload_to='photos/categories',blank=True)
    slug = models.SlugField(max_length=100,unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def img_preview(self): 
        return mark_safe('<img src = "{url}" width = "50" height = "50"/>'.format(
             url = self.category_img.url
         ))

    def __str__(self):
        return self.category_name

    class Meta:
        verbose_name_plural = 'categories'

    class MPTTMeta:
        order_insertion_by = ['category_name']

what i am trying to get is like i have 3 child category..Each category will have product of any color.So,if i filter product by category,color will be shown in sidebar of that category products without avoid getting duplicates as many product may have same color.So,i am getting same color multiple times.If i need to use distinct(),how to use it in query that will remove duplicate color based on product category.I tried this in template


                <form>
                    <div class="custom-control custom-checkbox d-flex align-items-center justify-content-between mb-3">
                        <input type="checkbox" class="custom-control-input" checked id="color-all">
                        <label class="custom-control-label" for="price-all">All Color</label>
                        <span class="badge border font-weight-normal">1000</span>
                    </div>
                    {% for i in variation %}
                    {% ifchanged i.color %}
                    <div class="custom-control custom-checkbox d-flex align-items-center justify-content-between mb-3">
                        <input type="checkbox" class="custom-control-input filter-checkbox" id="{{i.color.id}}" data-filter="color">
                        <label class="custom-control-label" for="{{i.color.id}}">{{i.color}}</label>
                        <span class="badge border font-weight-normal">150</span>
                    </div>
                    {% endifchanged %}
                    {% endfor %}
                </form>

But,it just remove duplicate of last iteration.How to avoid getting duplicates for all color?

Just where you have a line # color = color.objects.all() change it to color = products.color.all().distinct('id') and then pass it to your template.

Answer of my problem, what i did:

variation = ProductVaraiant.objects.filter(product__category = categories)

what i changed:

variation = ProductVaraiant.objects.filter(product__category=categories).values('color__title').distinct()

if using postgre database,don't need to use values,just use distinct('color') and you will need to use values for default database to avoid error below,

DISTINCT ON fields is not supported by this database backend
Back to Top