Add rating aggregates to the add-on review list API, if requested.

This commit is contained in:
Mathieu Pillard 2016-09-19 16:53:37 +02:00
Родитель 893f890296
Коммит 12662f4074
3 изменённых файлов: 44 добавлений и 11 удалений

Просмотреть файл

@ -19,10 +19,12 @@ This endpoint allows you to fetch reviews for a given add-on.
.. http:get:: /api/v3/addons/addon/(int:id|string:slug|string:guid)/reviews/
:query string filter: The :ref:`filter <review-filtering-param>` to apply.
:query int show_grouped_ratings: Whether or not to show ratings aggregates for this add-on in the response.
:>json int count: The number of results for this query.
:>json string next: The URL of the next page of results.
:>json string previous: The URL of the previous page of results.
:>json array results: An array of :ref:`reviews <review-detail-object>`.
:>json object grouped_ratings: Only present if ``show_grouped_ratings`` query parameter is present. An object with 5 key-value pairs, the keys representing each possible rating (Though a number, it has to be converted to a string because of the JSON formatting) and the values being the number of times the corresponding rating has been posted for this add-on, e.g. ``{"1": 4, "2": 8, "3": 15, "4": 16: "5": 23}``.
.. _review-filtering-param:

Просмотреть файл

@ -623,27 +623,30 @@ class TestReviewViewSetGet(TestCase):
self.url = reverse(
'addon-review-list', kwargs={'addon_pk': self.addon.pk})
def test_list(self):
def test_list(self, **kwargs):
review1 = Review.objects.create(
addon=self.addon, body='review 1', user=user_factory())
addon=self.addon, body='review 1', user=user_factory(),
rating=1)
review2 = Review.objects.create(
addon=self.addon, body='review 2', user=user_factory())
addon=self.addon, body='review 2', user=user_factory(),
rating=2)
review1.update(created=self.days_ago(1))
# Add a review belonging to a different add-on, a reply, a deleted
# review and another older review by the same user as the first review.
# They should not be present in the list.
review_deleted = Review.objects.create(
addon=self.addon, body='review deleted', user=review1.user)
addon=self.addon, body='review deleted', user=review1.user,
rating=3)
review_deleted.delete()
Review.objects.create(
addon=self.addon, body='reply to review 1', reply_to=review1,
user=user_factory())
Review.objects.create(
addon=addon_factory(), body='review other addon',
user=user_factory())
user=user_factory(), rating=4)
older_review = Review.objects.create(
addon=self.addon, body='review same user/addon older',
user=review1.user)
user=review1.user, rating=5)
# We change `created` manually after the actual creation, so we need to
# force a full refresh of the denormalized fields, because this
# normally only happens at creation time.
@ -654,7 +657,7 @@ class TestReviewViewSetGet(TestCase):
assert Review.unfiltered.count() == 6
response = self.client.get(self.url)
response = self.client.get(self.url, kwargs)
assert response.status_code == 200
data = json.loads(response.content)
assert data['count'] == 2
@ -662,12 +665,27 @@ class TestReviewViewSetGet(TestCase):
assert len(data['results']) == 2
assert data['results'][0]['id'] == review2.pk
assert data['results'][1]['id'] == review1.pk
return data
def test_list_unknown_addon(self):
def test_list_grouped_ratings(self):
data = self.test_list(show_grouped_ratings=1)
assert data['grouped_ratings']['1'] == 1
assert data['grouped_ratings']['2'] == 1
assert data['grouped_ratings']['3'] == 0
assert data['grouped_ratings']['4'] == 0
assert data['grouped_ratings']['5'] == 0
def test_list_unknown_addon(self, **kwargs):
self.url = reverse(
'addon-review-list', kwargs={'addon_pk': self.addon.pk + 42})
response = self.client.get(self.url)
response = self.client.get(self.url, kwargs)
assert response.status_code == 404
data = json.loads(response.content)
return data
def test_list_grouped_ratings_unknown_addon_not_present(self):
data = self.test_list_unknown_addon(show_grouped_ratings=1)
assert 'grouped_ratings' not in data
def test_list_addon_guid(self):
self.url = reverse(
@ -679,7 +697,7 @@ class TestReviewViewSetGet(TestCase):
'addon-review-list', kwargs={'addon_pk': self.addon.slug})
self.test_list()
def test_list_user(self):
def test_list_user(self, **kwargs):
self.user = user_factory()
self.url = reverse(
'account-review-list', kwargs={'account_pk': self.user.pk})
@ -704,7 +722,7 @@ class TestReviewViewSetGet(TestCase):
assert Review.unfiltered.count() == 5
response = self.client.get(self.url)
response = self.client.get(self.url, kwargs)
assert response.status_code == 200
data = json.loads(response.content)
assert data['count'] == 3
@ -713,6 +731,11 @@ class TestReviewViewSetGet(TestCase):
assert data['results'][0]['id'] == reply.pk
assert data['results'][1]['id'] == review1.pk
assert data['results'][2]['id'] == review2.pk
return data
def test_list_user_grouped_ratings_not_present(self):
data = self.test_list_user(show_grouped_ratings=1)
assert 'grouped_ratings' not in data
def test_list_no_user_or_addon(self):
# We have a fallback in get_queryset() to avoid listing all reviews on

Просмотреть файл

@ -392,6 +392,14 @@ class ReviewViewSet(AddonChildMixin, ModelViewSet):
raise ParseError('Need an addon or user identifier')
return qs
def get_paginated_response(self, data):
response = super(ReviewViewSet, self).get_paginated_response(data)
show_grouped_ratings = self.request.GET.get('show_grouped_ratings')
if 'addon_pk' in self.kwargs and show_grouped_ratings:
response.data['grouped_ratings'] = dict(GroupedRating.get(
self.addon_object.id))
return response
def get_queryset(self):
requested = self.request.GET.get('filter')