I want to order all stories by average rating, when i type in url.../stories?ordering=average_rating it brings error: 'list' object has no attribute 'model'
def get_queryset(self):
queryset = Story.objects.all()
ordering = self.request.query_params.get('ordering', None)
if ordering == 'average_rating':
return sorted(queryset, key=lambda s: s.average_rating)
return queryset
class Story(models.Model):
...
@property
def average_rating(self):
average_rating = self.ratings.all().aggregate(Avg('rating'))['rating__avg']
if average_rating is not None:
return round(float(average_rating), 2)
return None
Solution
class StoryViewSet(viewsets.ModelViewSet):
queryset = Story.objects.all()
def filter_queryset(self, queryset):
ordering = self.request.query_params.get('ordering')
if ordering == 'average_rating':
return sorted(queryset, key=lambda s: s.average_rating, reverse=True)
return queryset
sorted(queryset, key=lambda s: s.average_rating)
this returns a list, while get_queryset
should return a queryset
You can try something like this:
def get_queryset(self):
queryset = Story.objects.all()
ordering = self.request.query_params.get('ordering', None)
if ordering == 'average_rating':
return queryset.annotate(rating_avg=Avg('ratings__rating')).order_by('rating_avg')
return queryset
As the name implies, get_queryset
needs to return a queryset, not a list.
Luckily your entire query and ordering can be done in the database; you don't need the average_rating
method.
queryset = Story.objects.annotate(average_rating= Avg('ratings__rating'))
ordering = self.request.query_params.get('ordering', None)
if ordering == 'average_rating':
queryset = queryset.order_by("average_rating")
return queryset
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.