1

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 ?

4
  • Well you iterate over the number 3, you can not iterate over a number. Commented May 29, 2018 at 18:47
  • Can you specify why you use a CharField here instead of an IntegerField? Commented May 29, 2018 at 18:48
  • I have tried to convert it to integer. But it says int object not iterable, Commented May 29, 2018 at 18:54
  • 1
    yes, but you are here solving two different problems. A model should not be aware of the templates in which it is used, you should model things first of all consistently, and then worry about templates. Commented May 29, 2018 at 18:55

1 Answer 1

1

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 %}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot for sharing the code. Going to give a try. :)
@Yunus: well it is possible some details are not entirely correct (since it is hard to solve a problem with a limited amount of information). In that case please edit your question with the errors you are still facing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.