Reputation: 653
I have these models in my Django app:
class Book(models.Model):
title = models.CharField(max_length=50, unique=True)
owner = models.CharField(max_length=30)
price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
book_rating = models.ForeignKey('Rating', null=True)
RATE_CHOICES = zip(range(1,6), range(1,6))
class Rating(models.Model):
user = models.ForeignKey(User)
this_book = models.ForeignKey(Book)
rate = models.DecimalField(max_digits=2, decimal_places=1, choices=RATE_CHOICES)
comment = models.TextField(max_length=4000, null=True)
I am trying to access the Ratings of each instance of the Book model. Here is what I've tried so far in the shell:
from django.contrib.contenttypes.models import ContentType
>>> ctype = ContentType.objects.get_for_model(Rating)
>>> ctype
<ContentType: rating>
>>> book_titles = ctype.model_class().objects.filter(this_book__title='My Test Book')
>>> book_titles
<QuerySet [<Rating: My Test Book - parrot987 - 3.0>, <Rating: My Test Book - [email protected] - 5.0>]>
How can I access the two rating values of each object (5.0 and 3.0) without all of this other data?
Can this be done in such a way that I am able to average the numbers and return the final value?
Upvotes: 6
Views: 26894
Reputation: 8071
For 1. you can use (relevant documentation):
Rating.objects.filter(this_book__title='My Test Book').values('rate')
If you just want a flat list you can use values_list('rate', flat=True)
instead of values('rate')
.
For 2 (relevant documentation):
from django.db.models import Avg
Rating.objects.filter(this_book__title='My Test Book').aggregate(Avg('rate'))
This will return a dictionary where the key is rate__avg
and the value is the average of the ratings.
Upvotes: 18
Reputation: 374
Please see the following for Many to One fields django - Get the set of objects from Many To One relationship
To access the rating, you can use a for loop and access the individual values e.g.
total = 0
for rating in book_titles.book_set.all()
total += rating.rate
Good luck!
Upvotes: 1