'Django: cannot display variations to the template
I am trying to implement variations for the products. The issue is that when I am trying to display products on the webpage via a drop-down menu, instead of sizes I am getting the product name. My application already has product that are filtered by categories. I want to show sizes in my product detailed html
models.py
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE, default=1)
name = models.CharField(max_length=200)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=True)
image = models.ImageField(null=True, blank=True)
description = models.TextField(null=True, blank=True)
slug = models.SlugField(max_length=255, unique=True, default=uuid.uuid1)
def __str__(self):
return self.name
@property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
class Meta:
unique_together = ('name', 'slug')
def get_price(self):
return self.price
def get_absolute_url(self):
return reverse('single_product', kwargs={'slug': self.slug})
class VariationManager(models.Manager):
def sizes(self):
return super(VariationManager, self).filter(category='size')
def colors(self):
return super(VariationManager, self).filter(category='colors')
VAR_CATEGORIES = (
('size', 'size'),
('color', 'color')
)
class Variation(models.Model):
title = models.CharField(max_length=50)
category = models.CharField(max_length=120, choices=VAR_CATEGORIES, default='size')
price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=100)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
objects = VariationManager
def __str__(self):
return self.title
product.html
Here is HTML for my product detailed view
{% extends "store/main.html" %}
{% block content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tutorial</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<!-- CSS -->
<link href="static/css/style.css" rel="stylesheet">
<meta name="robots" content="noindex,follow" />
</head>
<body>
<main class="container">
<!-- Left Column / Headphones Image -->
<!-- Right Column -->
<div class="right-column">
<!-- Product Description -->
<div class="product-description">
<span></span>
<h1>{{product.name}}</h1>
<div class="left-column">
<img data-image="black" src="{{ product.imageURL }}"
width="400"
height="500">
</div>
<p>"{{product.description}}"</p>
</div>
<div class="col-sm-4 pull-right">
{% if product.variation_set.all %}
<select class="form-control" name="size">
{% for products in product.variation_set.all %}
<option value="{{ product.name|lower }}">{{ product.name|capfirst }}</option>
{% endfor %}
</select>
{% endif %}
<!-- Product Configuration -->
</div>
<!-- Product Pricing -->
<div class="product-price">
<button data-product="{{product.id}}" data-action="add" class="btn btn-outline-secondary add-btn update-cart">Add to Cart</button>
<div class="product-configuration">
<a href="#">How to take the measurements</a>
</div>
</div>
</div>
</main>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" charset="utf-8"></script>
<script src="static/js/script.js" charset="utf-8"></script>
</body>
</html>
{% endblock %}
Solution 1:[1]
The mystery with displaying the name of the variation was that in my product.html template I have used product.name|lower which returned the name of the product by ID.
{% for products in product.variation_set.all %}
<option
value="{{ product.name|lower }}">{{product.name|capfirst}}
</option>
product returns objects of the class in my views.py:
def product_detail(request, category_slug, slug):
product = Product.objects.get(slug=slug)
variation = Variation.objects.all()
context = {
'product': product,
'variation': variation
}
return render(request, 'store/product.html', context)
Therefore, instead, I needed the name of the category name by slug
This is what products returns:
def category_detail(request, slug):
category = get_object_or_404(Category, slug=slug)
products = category.products.all()
context = {
'category': category,
'products': products,
}
return render(request, 'store/category_detail.html', context)
We need all products in the category and run find the name of the variation. The search for the product's corresponding variation is implemented through the for loop in product.html
Solution 2:[2]
You have typo in
{% for products in product.variation_set.all %}
<option value="{{ product.name|lower }}">{{ product.name|capfirst }}</option>
{% endfor %}
I think it should be
<option value="{{ products.name|lower }}">{{ products.name|capfirst }}</option>
Because you are looping over product.variations with products as element.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Artemii Khristich |
| Solution 2 | TrueGopnik |
