Issue Displaying All Colors of a Product Variant in Django Template

I'm working on a Django application where I have a Product model with a many-to-many relationship with a Color model. I want to display all colors associated with a product variant on its detail page. However, when I click on a specific color (e.g., white), the page only shows that color instead of all available colors for the product variant.

Here’s the relevant code:

Models:

class Color(models.Model):
    code = models.CharField(max_length=7)  # Hex color code
    image = models.ImageField(upload_to='colors/')  # Image field for color representation
    product_varients = models.ManyToManyField('Product', related_name='color_variants', blank=True)

class Product(models.Model):
    pid = ShortUUIDField(length=10, max_length=100, prefix="prd", alphabet="abcdef")
    user = models.ForeignKey(CustomUser , on_delete=models.SET_NULL, null=True)
    category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name="category")
    color = models.ManyToManyField(Color, blank=True)

View Function:

def product_varient_detail_view(request, pid):  
    try:  
        product_variant = Product.objects.get(pid=pid)  
    except Product.DoesNotExist:  
        return render(request, "core/error_page.html")  
    
    wishlist = wishlist_model.objects.filter(user=request.user) if request.user.is_authenticated else None  
    sub_category = SubCategory.objects.all()  
    categories = Category.objects.prefetch_related('subcategories').order_by('?')[:4]  
    nav_category = Category.objects.filter(special_category=True).prefetch_related('subcategories').order_by('?')[:4]  
    
    # Initialize variables  
    colors = product_variant.color_variants.all()  # Get the colors of the product variant
    linked_colors = set()  # Use a set to avoid duplicates
    
    # Get linked colors  
    for color in colors:  
        for linked_product in color.product_varients.exclude(id=product_variant.id):  # Exclude current product
            linked_colors.update(linked_product.color_variants.all())  # Update the set with linked product colors
    
    # Convert linked_colors back to a list for the template
    linked_colors = list(linked_colors)
    
    sizes = product_variant.size.filter(product=product_variant)  
    p_image = product_variant.p_images.filter(product=product_variant)  
    
    # Getting review  
    reviews = ProductReview.objects.filter(product=product_variant)  
    review_count = reviews.count()  
    average_rating = ProductReview.objects.filter(product=product_variant).aggregate(rating=Avg('rating'))  
    
    # Product Review Form  
    review_form = ProductReviewForm()  
    
    if request.GET.get('color'):  
        color_id = request.GET.get('color')  
        color = Color.objects.get(coid=color_id)  
        product_varient = color.product_varients.first()  
        if product_varient:  
            return redirect('core:product_varient_detail', pid=product_varient.pid)  
    
    try:  
        product_p = Product.objects.get(pid=pid)  
        context1 = {'product_p': product_p}  
        if request.GET.get('size'):  
            size_name = request.GET.get('size')  
            size_object = Size.objects.get(name=size_name)  
            price = product_variant.get_product_price_by_size(size_object)  
            context1['selected_size'] = size_name  
            context1['updated_price'] = price  
    
    except Exception as e:  
        print(e)  
        return render(request, "core/error_page.html")  
    
    main_product_color = product_variant.main_product_color  
    
    context = {  
        "p": product_variant,  
        "w": wishlist,  
        "p_image": p_image,  
        "sub_category": sub_category,  
        "categories": categories,  
        "nav_category": nav_category,  
        'colors': colors,  
        'linked_colors': linked_colors,  
        'sizes': sizes,  
        'reviews': reviews,  
        'review_count': review_count,  
        'average_rating': average_rating,  
        'review_form': review_form,  
        'main_product_color': main_product_color,  
    }  
    
    context.update(context1)  
    return render(request, "core/product_varient_detail.html", context)

Template Code:

{% if colors %}
    {% for c in colors %}
        <div class="color__radio">
            <input type="radio" id="color_{{ c.id }}" name="color" 
                   data-image-url="{{ c.image.url }}" 
                   class="color-input" 
                   data-url="{% url 'core:product_varient_detail' c.product_varients.first.pid %}?color={{ c.coid }}">
            <label class="color__radio-label" 
                   for="color_{{ c.id }}" 
                   style="background-color: {{ c.code }};"></label>
        </div>
    {% endfor %}
{% endif %}

{% if linked_colors %}
    <h3>Linked Product Colors</h3>
    {% for c in linked_colors %}
        <div class="color__radio">
            <input type="radio" id="linked_color_{{ c.id }}" name="linked_color" 
                   data-image-url="{{ c.image.url }}" 
                   class="color-input" 
                   data-url="{% url 'core:product_varient_detail' c.product_varients.first.pid %}?color={{ c.coid }}">
            <label class="color__radio-label" 
                   for="linked_color_{{ c.id }}" 
                   style="background-color: {{ c.code }};"></label>
        </div>
    {% endfor %}
{% endif %}

The issue I'm facing is that when I click on a specific color, the page only shows that color instead of all available colors for the product variant. How can I modify my code to ensure that all colors are displayed on the product variant detail page, regardless of which color I click on?

To ensure that all colors for the product variant are displayed, you'll need to adjust the logic that filters products based on the selected color. Currently, when a color is clicked, you are redirecting to the product variant associated with that color, which limits the displayed colors to only those linked to the clicked color variant.

Here's the modified code snippet. (You can add your own logic)

def product_varient_detail_view(request, pid):  
    try:  
        product_variant = Product.objects.get(pid=pid)  
    except Product.DoesNotExist:  
        return render(request, "core/error_page.html")  

    wishlist = wishlist_model.objects.filter(user=request.user) if request.user.is_authenticated else None  
    sub_category = SubCategory.objects.all()  
    categories = Category.objects.prefetch_related('subcategories').order_by('?')[:4]  
    nav_category = Category.objects.filter(special_category=True).prefetch_related('subcategories').order_by('?')[:4]  
    
    colors = product_variant.color_variants.all()

    selected_color = None
    if request.GET.get('color'):
        color_id = request.GET.get('color')
        selected_color = Color.objects.get(pk=color_id)
    
    sizes = product_variant.size.filter(product=product_variant)  
    p_image = product_variant.p_images.filter(product=product_variant)  

    reviews = ProductReview.objects.filter(product=product_variant)  
    review_count = reviews.count()  
    average_rating = ProductReview.objects.filter(product=product_variant).aggregate(rating=Avg('rating'))  

    review_form = ProductReviewForm()  

    context = {  
        "p": product_variant,  
        "w": wishlist,  
        "p_image": p_image,  
        "sub_category": sub_category,  
        "categories": categories,  
        "nav_category": nav_category,  
        'colors': colors,  
        'selected_color': selected_color,  # Add selected color to context
        'sizes': sizes,  
        'reviews': reviews,  
        'review_count': review_count,  
        'average_rating': average_rating,  
        'review_form': review_form,  
    }  
    
    return render(request, "core/product_varient_detail.html", context)

This is the modified template.

{% if colors %}
    {% for c in colors %}
        <div class="color__radio">
            <input type="radio" id="color_{{ c.id }}" name="color" 
                   data-image-url="{{ c.image.url }}" 
                   class="color-input" 
                   data-url="{% url 'core:product_varient_detail' product_variant.pid %}?color={{ c.id }}"
                   {% if selected_color and selected_color.id == c.id %}checked{% endif %}>
            <label class="color__radio-label" 
                   for="color_{{ c.id }}" 
                   style="background-color: {{ c.code }};"></label>
        </div>
    {% endfor %}
{% endif %}
Вернуться на верх