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?
You need to sign in to view this answers