Reputation: 415
First see my code please :
My model :
class review_product_individual(models.Model):
product_id = models.CharField(max_length=30)
product_star = models.CharField(max_length=30)
product_review_message = models.CharField(max_length=255,blank=True)
product_reviewed_by = models.CharField(max_length=30)
product_review_date = models.DateTimeField(auto_now_add=True, blank=True)
In views :
product_review = review_product_individual.objects.filter(product_id = productID).order_by('-product_review_date')
Here product_star will contain 1 to 5 rating and stored as char. Now what I want to do is this I will access each product_review object in Django template in for loop and inside the for loop I will iterate product_review.product_star times.please see the template code here :`
{% for product_review in product_review %}
<li>
<div class="review-heading">
<h5 class="name">{{product_review.product_reviewed_by}}</h5>
<p class="date">27 DEC 2018, 8:0 PM</p>
<div class="review-rating">
{% for i in product_review.product_star %}
<i class="fa fa-star"></i>
{% endfor %}
<i class="fa fa-star-o empty"></i>
</div>
</div>
<div class="review-body">
<p>{{product_review.product_review_message}}</p>
</div>
</li>
{% endfor %}
But only one star is printing as the value of {{product_review.product_star}} =3 I want 3 stars. I could not do in views because product_review contains many objects. So how can I do it ?
Upvotes: 1
Views: 545
Reputation: 476503
I find it weird that you store the rating as a CharField
(so a string), instead of using an IntegerField
, with an IntegerField
, you can calculate sums, averages, order elements numerically (not lexicographically), etc.
So I would advice you to use an IntegerField
instead:
class ReviewProductIndividual(models.Model):
product_id = models.CharField(max_length=30)
product_star = models.IntegerField()
product_review_message = models.CharField(max_length=255,blank=True)
product_reviewed_by = models.CharField(max_length=30)
product_review_date = models.DateTimeField(auto_now_add=True, blank=True)
So now we can store ratings with a numerical rating.
Next your problem with the template is that you iterate over a string. If you iterate over a string, you iterate over its characters. So that means that if you stored '5'
, it will iterate once: and the iterator will obtain the character 5
. But you want to iterate five times.
What you can do is for example define a {% range ... %}
tag, like this snippet does. We can for example create a package (with an __init__.py
file) in appname/templatetags/range.py
(and thus add an empty file appname/templatetags/__init__.py
):
from django.template import Library, Node, TemplateSyntaxError register = Library() class RangeNode(Node): def __init__(self, num, context_name): self.num = Variable(num) self.context_name = context_name def render(self, context): context[self.context_name] = range(int(self.num.resolve(context))) return "" @register.tag def num_range(parser, token): """ Takes a number and iterates and returns a range (list) that can be iterated through in templates Syntax: {% num_range 5 as some_range %} {% for i in some_range %} {{ i }}: Something I want to repeat\n {% endfor %} Produces: 0: Something I want to repeat 1: Something I want to repeat 2: Something I want to repeat 3: Something I want to repeat 4: Something I want to repeat """ try: fnctn, num, trash, context_name = token.split_contents() except ValueError: raise TemplateSyntaxError, "%s takes the syntax %s number_to_iterate\ as context_variable" % (fnctn, fnctn) if not trash == 'as': raise TemplateSyntaxError, "%s takes the syntax %s number_to_iterate\ as context_variable" % (fnctn, fnctn) return RangeNode(num, context_name)
Note that this is a slighly modified version (updated with the comment in the snippet).
Now we can use this {% num_range ... %}
tag:
{% for product_review in product_review %}
<li>
<div class="review-heading">
<h5 class="name">{{product_review.product_reviewed_by}}</h5>
<p class="date">27 DEC 2018, 8:0 PM</p>
<div class="review-rating">
{% num_range product_review.product_star as star_range %}
{% for _ in star_range %}
<i class="fa fa-star"></i>
{% endfor %}
<i class="fa fa-star-o empty"></i>
</div>
</div>
<div class="review-body">
<p>{{product_review.product_review_message}}</p>
</div>
</li>
{% endfor %}
Upvotes: 1