Reputation: 75
I am attempting at rendering annotated data into my template
My models looks like this
class Content(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
reviews_total = models.FloatField(null=True)
def _str_(self):
return self.title
class Review(models.Model):
content = models.ForeignKey(Content, null=True, on_delete=models.CASCADE)
readability = models.CharField(max_length=500)
readability_rating = models.IntegerField()
actionability = models.CharField(max_length=500)
actionability_rating = models.IntegerField()
general_comments = models.CharField(max_length=500)
avg_rating = models.IntegerField(null=True)
And my template looks like this
{% for content in content.all %}
<div onclick="window.location='{% url 'details'
content.id %}';">
{{ content.title }}
Reviews: {{ content.review_set.count }}
Avg Rating: {{ ? }}
{% endfor %}
My view looks like this
def details(request, content_id):
content = get_object_or_404(Content, pk=content_id)
return render(request, 'content/details.html', {'content': content})
From the following query
x = Content.objects.annotate(avg=Avg('review__avg_rating'))
y = vars(x[pk])
y['avg']
Which will give me 4.0 for example.
My goal is essentially to to insert y into Avg Rating {{ }}
Is there a way similar to content.review_set.count? Or is it best to do in views?
Upvotes: 1
Views: 959
Reputation: 476574
The annotation is added as an attribute to the objects in the QuerySet
, so you can render this with.
So in your view, you can pass data like:
def some_view(request):
contents = Content.objects.annotate(
nreviews=Count('review'),
avg=Avg('review__avg_rating')
)
return render(request, 'some_template.html', {'contents': contents })
and in the template, you then render this with:
{% for content in contents %}
Reviews: {{ content.nreviews }}
Avg Rating: {{ content.avg }}
{% endfor %}
EDIT: If you want to show the details of one Content
object, you can render this with:
def details(request, content_id):
content = get_object_or_404(
Content.objects.annotate(
nreviews=Count('review'),
avg=Avg('review__avg_rating')
),
pk=content_id
)
return render(request, 'content/details.html', {'content': content})
and in the template:
{{ content.title }}
Reviews: {{ content.nreviews }}
Avg Rating: {{ content.avg }}
so without the {% for content in contents %}
loop.
Upvotes: 3