Skip to content

Commit

Permalink
feat(favorite an article): favorite articles
Browse files Browse the repository at this point in the history
- add tests for favoriting an article
- add a favorites field to the article model
- add a method in the serializer for favoriting an article
- add a view for favoriting an article

[Delivers #161966617]
  • Loading branch information
salma-nyagaka committed Dec 13, 2018
1 parent d007f82 commit 730abfb
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 2 deletions.
1 change: 1 addition & 0 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Article(models.Model):
# auto_now is updated with change
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
favorite = models.ManyToManyField(User, blank=True, related_name='favorite')

def __str__(self):
"""
Expand Down
11 changes: 11 additions & 0 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ class ArticleAuthorSerializer(serializers.ModelSerializer):
description = serializers.CharField()
body = serializers.CharField()
author = UserSerializer(read_only = True)
favorite = serializers.SerializerMethodField(read_only=True)

def favorite(self, instance):
"""favorite an article"""
request = self.context.get('request')
favorite = False
if request is not None and request.user.is_authenticated:
user_id = request.user.id
favorite = instance.favorite.all().filter(id=user_id).count() == 1
return {'favoritesCount': instance.favorite.count(), 'favorite':favorite}

class Meta:
model = Article
fields = '__all__'
Expand Down
39 changes: 37 additions & 2 deletions authors/apps/articles/tests/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ def setUp(self):
# urls
self.register_url = reverse("authentication:user-signup")
self.login_url = reverse("authentication:user-login")
self.register_url = reverse("authentication:user-signup")
self.login_url = reverse("authentication:user-login")
self.articles_url = reverse("articles:articles")

# self.article_url = reverse("articles:get_article", kwargs={slug:'slug'})
self.comments_url = ''#reverse("articles:comments")
self.comment_url = ''#reverse("articles:comment")
self.favoritearticle_url = reverse("articles:favorite", kwargs={'slug':"salma123445"})

self.register_data = {
"user":{
"user":{
"username": "JohnDoe",
"email": "John@andela.com",
"password": "jaja12ldd34&56"
Expand Down Expand Up @@ -170,6 +176,7 @@ def create_comment(self, token, article_slug):
)
return response


def create_article(self):
"""
Metrhgod to create articles for the first user
Expand All @@ -184,9 +191,37 @@ def create_article(self):

return article_url, saved_article, token



def create_article_user2(self):
"""Method to create articles for user 2"""
self.test_client.post(self.register_url ,self.register_data2, format='json')
login = self.test_client.post(self.login_url ,self.login_data2, format='json')
token = 'Token ' + login.data['token']
return token

def favorite_article(self):
"""method to favorite articles"""
self.user_signup()
token = 'Token ' + self.user_login()
saved_article = self.test_client.post(self.articles_url,
self.article_data, format='json',
HTTP_AUTHORIZATION=token)
slug = saved_article.data['slug']
favorite_url = reverse("articles:favorite", kwargs={'slug': slug})

return favorite_url

def unfavorite_article(self):
"""method to unfavorite articles"""
self.user_signup()
token = 'Token ' + self.user_login()
saved_article = self.test_client.post(self.articles_url,
self.article_data, format='json',
HTTP_AUTHORIZATION=token)
slug = saved_article.data['slug']
favorite_url = reverse("articles:favorite", "articles:favorite", kwargs={'slug': slug})

return favorite_url


31 changes: 31 additions & 0 deletions authors/apps/articles/tests/test_favorite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from rest_framework import status
from .base_test import BaseTestCase
from django.urls import reverse


class TestArticles(BaseTestCase):
"class to test making an article a favorite"

def test_favorite(self):
"""test for favoriting an article"""
self.user_signup()
token = self.user_login()
response = self.client.put(self.favorite_article(), format='json', HTTP_AUTHORIZATION='Token ' + token)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'You have favorited this article'})

def unfavorite_article(self):
"""test for favoriting an article that does not exist"""
self.user_signup()
token = self.user_login()
response = self.client.put(self.unfavorite_article(), format='json', HTTP_AUTHORIZATION='Token ' + token)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'You have removed this article from your favorites'})

def non_existing_article(self):
"""test for favoriting an article that does not exist"""
self.user_signup()
token = self.user_login()
response = self.client.put(self.favoritearticle_url, format='json', HTTP_AUTHORIZATION='Token ' + token)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'You have removed this article from your favorites'})
4 changes: 4 additions & 0 deletions authors/apps/articles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
UpdateDestroyCommentsAPIView, ReplyListAPIView, \
UpdateDestroyReplyAPIView

from .views import ArticleAPIView, SpecificArticleAPIView
from .views import ArticleAPIView, SpecificArticleAPIView, FavoriteArticles


urlpatterns = [
Expand All @@ -13,4 +15,6 @@
path('articles/<str:article_slug>/comments/<int:comment_pk>/', UpdateDestroyCommentsAPIView.as_view(), name='update-delete-comment'),
path('articles/<str:article_slug>/comments/<int:comment_pk>/replies/', ReplyListAPIView.as_view(), name='list-create-reply'),
path('articles/<str:article_slug>/comments/<int:comment_pk>/replies/<int:reply_pk>/', UpdateDestroyReplyAPIView.as_view(), name='update-delete-reply' ),
path('articles/<slug>', SpecificArticleAPIView.as_view(), name='get_article'),
path('articles/<slug>/favorite/', FavoriteArticles.as_view(), name='favorite')
]
32 changes: 32 additions & 0 deletions authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
ArticleSerializer, ArticleAuthorSerializer, CommentSerializer,
ReplySerializer
)
from .models import Article
from .serializers import ArticleSerializer, ArticleAuthorSerializer
from rest_framework.generics import UpdateAPIView


class ArticleAPIView(APIView):
Expand Down Expand Up @@ -350,3 +353,32 @@ def update(self, request, article_slug=None, comment_pk=None, reply_pk=None):
'message': 'Reply Updated Successfully',
'reply': serializer.data
}, status=status.HTTP_200_OK)


class FavoriteArticles(UpdateAPIView):
"""Class for making an article a favorite"""
serializer_class = ArticleSerializer

def update(self, request, slug):
"""This method updates the making of an article a favorite"""
try:
article = Article.objects.get(article_slug=slug)
except Article.DoesNotExist:
return Response({
'Error': 'Article does not exist'
}, status.HTTP_404_NOT_FOUND)

# gets the user of that specific session
user = request.user

# checks for the boolean value of making an article a favorite
confirm = bool(user in article.favorite.all())
if confirm is True:
article.favorite.remove(user.id)
message = {"You have removed this article from your favorites"}
return Response(message, status.HTTP_200_OK)

# if favoriting is false, the article is made a favorite
article.favorite.add(user.id)
message = {"You have favorited this article"}
return Response(message, status.HTTP_200_OK)

0 comments on commit 730abfb

Please sign in to comment.