Skip to content

Commit

Permalink
Feature #162883146: User should be able to view popular and recent ar…
Browse files Browse the repository at this point in the history
…ticles

- add urls and views for recent and popular articles
- add tests for these endpoints
- adjust average_rating field in model to DecimalField from IntegerField
[Feature #162883146]
  • Loading branch information
njeri-ngigi committed Dec 29, 2018
1 parent 5f3d3bf commit 0eb21fc
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 24 deletions.
18 changes: 18 additions & 0 deletions authors/apps/articles/migrations/0011_auto_20181229_2022.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.1.2 on 2018-12-29 20:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('articles', '0010_auto_20181213_1156'),
]

operations = [
migrations.AlterField(
model_name='article',
name='average_rating',
field=models.DecimalField(decimal_places=1, default=0, max_digits=5),
),
]
2 changes: 1 addition & 1 deletion authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Article(models.Model):
time_updated = models.DateTimeField(auto_now=True, db_index=True)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="articles")
average_rating = models.IntegerField(default=0)
average_rating = models.DecimalField(default=0, max_digits=5, decimal_places=1)

likes = models.ManyToManyField(
User, blank=True, related_name='LikesDislikes.user+')
Expand Down
17 changes: 3 additions & 14 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'''articles/serializers'''
import math
from decimal import Decimal
from django.db.models import Avg
from rest_framework import serializers
from django.utils.text import slugify
from rest_framework.validators import UniqueTogetherValidator
Expand Down Expand Up @@ -39,7 +38,7 @@ class ArticleSerializer(serializers.ModelSerializer):
favoritesCount = serializers.SerializerMethodField(
method_name='get_favorites_count')
rating = serializers.SerializerMethodField()
average_rating = serializers.SerializerMethodField()
average_rating = serializers.DecimalField(required=False, read_only=True, max_digits=5, decimal_places=1, coerce_to_string=False)
# ...............................................................
url = serializers.SerializerMethodField(read_only=True)
facebook = serializers.SerializerMethodField(read_only=True)
Expand Down Expand Up @@ -123,23 +122,13 @@ def create(self, validated_data):
def get_rating(self, obj):
request = self.context.get('request')
try:
rating = Rating.objects.filter(
rating = Rating.objects.get(
article=obj.id, rater=request.user.id)
user_rating = rating.values('rating')[0]['rating']
user_rating = rating.rating
except Exception as e:
user_rating = 0
return user_rating

def get_average_rating(self, obj):
avarage = 0
try:
ratings = Rating.objects.filter(article=obj.id)
avarage = ratings.all().aggregate(
Avg('rating'))['rating__avg']
except Exception as e:
print(e)
return avarage

def update(self, instance, validated_data):
'''method updating articles'''
email = self.context.get('email')
Expand Down
18 changes: 13 additions & 5 deletions authors/apps/articles/tests/test_articles.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ def test_get_all_articles(self):
response = self.client.get(self.ARTICLES)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertGreaterEqual(len(json.loads(response.content)), 0)
# test get popular artcles
response = self.client.get(self.ARTICLE.format("popular"))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertGreaterEqual(len(json.loads(response.content)), 0)
# test get recent artcles
response = self.client.get(self.ARTICLE.format("recent"))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertGreaterEqual(len(json.loads(response.content)), 0)

def test_get_user_articles(self):
'''test get a user's articles'''
Expand Down Expand Up @@ -234,11 +242,11 @@ def test_time_to_read(self):
def test_if_article_returns_share_links(self):
"""This method tests whether the API returns share links"""
res = self.client.get(self.TESTARTICLE)
self.assertIn("facebook", json.dumps(res.data))
self.assertIn("Linkedin", json.dumps(res.data))
self.assertIn("twitter", json.dumps(res.data))
self.assertIn("mail", json.dumps(res.data))
self.assertIn("url", json.dumps(res.data))
self.assertIn("facebook", json.loads(res.content))
self.assertIn("Linkedin", json.loads(res.content))
self.assertIn("twitter", json.loads(res.content))
self.assertIn("mail", json.loads(res.content))
self.assertIn("url", json.loads(res.content))

def test_get_tags(self):
"""Tests whether we can get all article tags"""
Expand Down
10 changes: 10 additions & 0 deletions authors/apps/articles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@
articles_list = ArticlesView.as_view({
'get': 'list',
'post': 'create',
})

recent_articles = ArticlesView.as_view({
'get': 'list_by_recent',
})

popular_articles = ArticlesView.as_view({
'get': 'list_by_popular',
})

articles_detail = ArticlesView.as_view({
'get': 'retrieve',
'put': 'update',
Expand Down Expand Up @@ -49,6 +57,8 @@

urlpatterns = [
path('articles/', articles_list),
path('articles/recent/', recent_articles),
path('articles/popular/', popular_articles),
path('articles/feed/', ArticlesFeedAPIView.as_view()),
path('articles/bookmarks/', BookMarksView.as_view()),
path('articles/<slug>/', articles_detail, name='articles_detail'),
Expand Down
12 changes: 12 additions & 0 deletions authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ def list(self, request):
page, context=serializer_context, many=True)
return self.get_paginated_response(serializer.data)

def list_by_recent(self, request):
page = self.paginate_queryset(self.get_queryset().order_by('-time_created'))
serializer = self.serializer_class(
page, context={"request": request}, many=True)
return self.get_paginated_response(serializer.data)

def list_by_popular(self, request):
page = self.paginate_queryset(self.get_queryset().order_by('-average_rating'))
serializer = self.serializer_class(
page, context={"request": request}, many=True)
return self.get_paginated_response(serializer.data)

def create(self, request):
'''method creating a new article(post)'''
serializer = self.serializer_class(
Expand Down
24 changes: 20 additions & 4 deletions authors/apps/rating/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Rating Serializers module
"""

from django.db.models import Sum
from django.db.models import Sum, Avg

from rest_framework import serializers

Expand Down Expand Up @@ -36,6 +36,18 @@ class Meta():
model = Rating
fields = ('rating', 'article', 'rater')

def set_average_rating(self, obj, rating):
average = rating
try:
ratings = Rating.objects.filter(article=obj.id)
if ratings:
average = ratings.all().aggregate(
Avg('rating'))['rating__avg']
obj.average_rating = average
obj.save()
except Exception as e:
print(e)

def create(self, validated_data):
"""
:params: validated_data:
Expand Down Expand Up @@ -73,14 +85,18 @@ def create(self, validated_data):
try:
rating_instance = Rating.objects.get(rater=user, article=article)
except:
"Error, article does not exist"
"Error, article does not exist"

if rating_instance:
""" Update the rating """
rating_instance.rating = rate
rating_instance.save()
return validated_data
else:
Rating.objects.create(**validated_data)

self.set_average_rating(article, rate)

return Rating.objects.create(**validated_data)
return validated_data


def check_article_exists(slug):
Expand Down

0 comments on commit 0eb21fc

Please sign in to comment.