dmandres dmandres - 1 year ago 48
Python Question

django - display the human readable when running Avg()

I'm figuring out this piece by piece. I want users to be able to rate blog posts based on 4 criteria (difficulty_rating, workload_rating, book_rating, attendance_rating). I have used choices in my to give users a choice.

After that, thanks to a user from StackOverflow, I was able to calculate the average for each of these values and display them at the top of every single post.

The problem is that they show up as floats with long decimals. Is there a way to show the human readable instead? Which comes from my model tuples?

I have done an {% if %} statement inside my template hardcoding everything, but I'm pretty sure there has to be a better way.

class Post(models.Model):

('draft', 'Draft'),
('published', 'Published'),

category = models.ForeignKey(Category)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique=True)
content = models.TextField()
seo_title = models.CharField(max_length=250)
seo_description = models.CharField(max_length=160)
author = models.ForeignKey(User, related_name='blog_posts', default=settings.AUTH_USER_MODEL)
published = models.DateTimeField(
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=9, choices=STATUS_CHOISES, default='draft')

def get_absolute_url(self):
return reverse('blog:post_detail', args=[self.slug])

def avg_ratings(self):
return self.comments.aggregate(
Avg('difficulty_rating', output_field=FloatField()),
Avg('workload_rating', output_field=FloatField()),
Avg('book_rating', output_field=FloatField()),
Avg('attendance_rating', output_field=FloatField()),

def __str__(self):
return self.title

class Comment(models.Model):
difficulty_rating_choices = (

(1, 'Very Easy'),
(2, 'Easy'),
(3, 'Moderate'),
(4, 'Hard'),
(5, 'Very Hard'),


workload_rating_choices = (

(1, 'Very Light'),
(2, 'Light'),
(3, 'Moderate'),
(4, 'Heavy'),
(5, 'Very Heavy'),


book_rating_choices = (

(1, '$'),
(2, '$$'),
(3, '$$$'),
(4, '$$$$'),
(5, '$$$$$'),


attendance_rating_choices = (

(1, 'Not Required'),
(2, 'Required'),

post = models.ForeignKey(Post, related_name="comments")
user = models.CharField(max_length=250)
email = models.EmailField()
title = models.CharField(max_length=250)
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=False)
difficulty_rating = models.IntegerField(choices=difficulty_rating_choices)
workload_rating = models.IntegerField(choices=workload_rating_choices)
book_rating = models.IntegerField(choices=book_rating_choices)
attendance_rating = models.IntegerField(choices=attendance_rating_choices)

def approved(self):
self.approved = True

def __str__(self):
return self.title

def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
template = 'blog/post/post_detail.html'
context = {

'post': post,

return render(request, template, context)


{% with avg_ratings=post.avg_ratings %}
<h1>Difficulty: {{ avg_ratings.difficulty_rating__avg }}</h1>
<h1>Workload: {{ avg_ratings.workload_rating__avg }}<h1>
<h1>Book Cost: {{ avg_ratings.book_rating__avg }}<h1>
<h1>Attendance: {{ avg_ratings.attendance_rating__avg }}<h1>

{% endwith %}

ivo ivo
Answer Source

Use a django template filter

For example:

{{ avg_ratings.difficulty_rating__avg|floatformat:"-3" }}

If by "human readable" you want to substitute words for ranges of values, create your own custom template filter to do that.


You could do something like (add the ranges for your levels):

from django import template

register = template.Library()

def rating_humanize(value): # Only one argument.
    if value < 1.0:
        return 'Very Easy'
    elif value < 2.0:
        return 'Easy'
        return 'Hard'

A better implementation would be to make a list of range to string mappings and then find the matching range and return the string for it.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download