Skip to content

Commit

Permalink
feature(bookmark articles): user can bookmark articles
Browse files Browse the repository at this point in the history
- bookmark article
- remove bookmark
- view all bookmarks
[finishes #164047078]
  • Loading branch information
Swaleh Matongwa authored and Swaleh Matongwa committed Mar 22, 2019
1 parent 60902c8 commit ce5538f
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 106 deletions.
45 changes: 44 additions & 1 deletion authors/apps/article/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class LikeComment(models.Model):
created = models.DateTimeField(auto_now=True)

class Meta:
ordering = ('created',)
ordering = ('like_type',)

@staticmethod
def get_like_status(user_id, comment_id, like_type):
Expand Down Expand Up @@ -240,3 +240,46 @@ class ArticleFavourite(models.Model):
)
favourited = models.BooleanField(default=False)


class ArticleBookmark(models.Model):
"""Articles bookmarked Model"""
user = models.ForeignKey(
User, related_name="bookmarks", on_delete=models.CASCADE)
article = models.ForeignKey(
Article, related_name='bookmarks', on_delete=models.CASCADE, to_field="slug")
created = models.DateTimeField(auto_now=True)

@staticmethod
def get_bookmark(user_id, slug):
"""Fetch bookmark"""
try:
bookmark = ArticleBookmark.objects.get(user=user_id, article=slug)
return bookmark
except ArticleBookmark.DoesNotExist:
pass

return False

@staticmethod
def create_bookmark(user_id, slug):
"""create a bookmark"""
return_message = {"error": "Bookmark already exists"}

if not ArticleBookmark.get_bookmark(user_id, slug):
ArticleBookmark.objects.create(user=user_id, article=slug)
return_message = {"message": "Bookmark created"}

return return_message

@staticmethod
def remove_bookmark(user_id, slug):
"""Remoove a bookmark"""
bookmark_exist = ArticleBookmark.get_bookmark(user_id, slug)
return_message = {"message": "Bookmark removed"}

if not bookmark_exist:
return_message = {"error": "Bookmark does not exist"}
else:
bookmark_exist.delete()

return return_message
27 changes: 7 additions & 20 deletions authors/apps/article/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from rest_framework import response

from authors.apps.authentication.serializers import UserSerializer
from .models import Article, ArticleLikes, Rate, ArticleComment, ArticleFavourite
from .models import Article, ArticleLikes, Rate, ArticleComment, ArticleFavourite, ArticleBookmark
from ..profiles.serializers import ProfileSerializer


Expand Down Expand Up @@ -170,19 +170,6 @@ def get_dislikes_count(self, obj):
"""
return obj.liked.filter(dislikes=-1).count()

def get_rates(self, obj):
"""
Returns rating average
"""
average = Rate.objects.filter(
article__pk=obj.pk).aggregate(Avg('your_rating'))

if average['your_rating__avg'] is None:
average_rating = 0
return average_rating

return average['your_rating__avg']

def get_favourited(self, obj):
"""
This method returns true or false on querying for favourited articel
Expand Down Expand Up @@ -284,12 +271,12 @@ class Meta:
fields = ['is_active']


class GetArticleSerializer(serializers.ModelSerializer):
tag_list = serializers.SerializerMethodField()

def get_tag_list(self, article):
return list(article.tag_list.names())
class BookmarksSerializer(serializers.ModelSerializer):
"""
converts the model into JSON format
"""
article = ArticleSerializer(read_only=True)

class Meta:
model = Article
fields = '__all__'
fields = ['id', 'article']
126 changes: 126 additions & 0 deletions authors/apps/article/tests/test_bookmark_article.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
"""Test API endpoints"""
import json
from rest_framework.test import APITestCase, APIClient
from rest_framework.views import status
from ...authentication.models import User


class CommentsTest(APITestCase):
client = APIClient()

def setUp(self):
# add test data
self.user = {
"user": {
"email": "caro@yahoo.com",
"username": "caro",
"password": "07921513542"
}
}

self.profile = {
"bio": "am fantastic",
"interests": "football",
"favorite_quote": "Yes we can",
"mailing_address": "P.O BOX 1080",
"website": "http://www.web.com",
"active_profile": True
}

self.article = {
"title": "Andela",
"description": "sdsd",
"body": "dsd",
"images": "",
"tag_list": ['kelvin', 'onkundi']
}
# create user
self.client.post('/api/users/', self.user, format='json')
# user login
response = self.client.post(
'/api/users/login/', self.user, format='json')
result = json.loads(response.content)

self.client.credentials(
HTTP_AUTHORIZATION='Token ' + result["user"]["token"])

# create profile
self.client.post(
'/api/profile/create_profile/', self.profile, format='json')

# create article
response = self.client.post(
'/api/articles/', self.article, format='json')

def test_bookmark_article(self):
"""
test bookmark article
"""
response = self.client.post(
'/api/articles/andela/bookmark', format='json')
result = json.loads(response.content)

self.assertEqual(result["message"],
"Bookmark created")
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

def test_bookmark_bookmarked_article(self):
"""
test bookmark an article already bookmarked
"""
# bookmark article
response = self.client.post(
'/api/articles/andela/bookmark', format='json')

# bookmark article again
response = self.client.post(
'/api/articles/andela/bookmark', format='json')
result = json.loads(response.content)

self.assertEqual(result["error"],
"Bookmark already exists")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_remove_bookmark(self):
"""
test remove bookmark
"""
# bookmark article
response = self.client.post(
'/api/articles/andela/bookmark', format='json')

# remove bookmark
response = self.client.delete(
'/api/articles/andela/bookmark', format='json')

self.assertEqual(response.data["message"],
"Bookmark removed")
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

def test_remove_nonexising_bookmark(self):
"""
test remove bookmark that does not exist
"""
# remove bookmark
response = self.client.delete(
'/api/articles/andela/bookmark', format='json')
result = json.loads(response.content)

self.assertEqual(result["error"],
"Bookmark does not exist")
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

def test_get_bookmarks(self):
"""
test get all user bookmarks
"""
# bookmark article
response = self.client.post(
'/api/articles/andela/bookmark', format='json')

# get bookmarks
response = self.client.get('/api/bookmarks/', format='json')
result = json.loads(response.content)

self.assertEqual(result["articlesCount"], 1)
self.assertEqual(response.status_code, status.HTTP_200_OK)
9 changes: 6 additions & 3 deletions authors/apps/article/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.urls import path

from .views import (ArticlesAPIView, RetrieveArticleAPIView, LikeAPIView, DislikeAPIView, RateAPIView, FavouriteAPIView,
CommentsAPIView, RetrieveCommentsAPIView, SubCommentAPIView,LikeUnlikeAPIView, CommentDislikeAPIView)
from .views import (ArticlesAPIView, RetrieveArticleAPIView, LikeAPIView, DislikeAPIView, RateAPIView, FavouriteAPIView, CommentsAPIView,
RetrieveCommentsAPIView, SubCommentAPIView, LikeUnlikeAPIView, CommentDislikeAPIView, BookmarkAPIView, BookmarksAPIView)

app_name = "articles"

Expand All @@ -15,6 +15,9 @@
path('articles/<slug>/comments/<pk>', RetrieveCommentsAPIView.as_view()),
path('articles/<slug>/comments/<pk>/subcomment', SubCommentAPIView.as_view()),
path('articles/<slug>/like_comment/<pk>', LikeUnlikeAPIView.as_view()),
path('articles/<slug>/dislike_comment/<pk>', CommentDislikeAPIView.as_view()),
path('articles/<slug>/dislike_comment/<pk>',
CommentDislikeAPIView.as_view()),
path('articles/<slug>/favorite', FavouriteAPIView.as_view()),
path('articles/<slug>/bookmark', BookmarkAPIView.as_view()),
path('bookmarks/', BookmarksAPIView.as_view()),
]
Loading

0 comments on commit ce5538f

Please sign in to comment.