Skip to content

Commit

Permalink
feat(bookmark) create delete bookmark
Browse files Browse the repository at this point in the history
- user can create bookmark
- user can delete bookmark

[Delivers #161254679]
  • Loading branch information
Eyansky committed Nov 15, 2018
1 parent 615ace6 commit 23db497
Show file tree
Hide file tree
Showing 15 changed files with 196 additions and 2 deletions.
1 change: 1 addition & 0 deletions authors/apps/article/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ def render(self, data, media_type=None, renderer_context=None):
if not status_code == status.HTTP_200_OK:
return super(FavoriteJSONRenderer, self).render(data)
return super(FavoriteJSONRenderer, self).render(data)

2 changes: 1 addition & 1 deletion authors/apps/article/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from authors.apps.profiles.models import UserProfile

from .models import RateArticle, Comments, CommentHistory, Favorite
from .models import RateArticle, Comments, CommentHistory, Favorite
from authors.apps.profiles.serializers import ProfileListSerializer

TABLE = apps.get_model('article', 'Article')
Expand Down
1 change: 1 addition & 0 deletions authors/apps/article/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,5 @@
path('articles/<slug:slug>/history/<int:id>',
CommentHistoryAPIView.as_view(),
name='comment_history'),

]
Empty file.
14 changes: 14 additions & 0 deletions authors/apps/bookmark/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.db import models
from authors.apps.authentication.models import User
from authors.apps.article.models import Article

class Bookmark(models.Model):
"""Bookmark model"""
article = models.ForeignKey(
Article,
related_name="bookmarked",
on_delete=models.CASCADE)
user = models.ForeignKey(
User,
related_name="bookmarks",
on_delete=models.CASCADE)
11 changes: 11 additions & 0 deletions authors/apps/bookmark/renderers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import json
from rest_framework.renderers import JSONRenderer
from rest_framework import status

class BookmarkJSONRenderer(JSONRenderer):
def render(self, data, media_type=None, renderer_context=None):
if renderer_context:
status_code = renderer_context.get('response').status_code
if not status_code == status.HTTP_200_OK:
return super(BookmarkJSONRenderer, self).render(data)
return super(BookmarkJSONRenderer, self).render(data)
16 changes: 16 additions & 0 deletions authors/apps/bookmark/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
from .models import Bookmark

class BookmarkSerializer(serializers.ModelSerializer):
"""Bookmark serializer class"""
class Meta:
model = Bookmark
fields = ('article', 'user')
validators = [
UniqueTogetherValidator(
queryset=Bookmark.objects.all(),
fields=('article', 'user'),
message="Article already bookmarked"
)
]
Empty file.
Empty file.
68 changes: 68 additions & 0 deletions authors/apps/bookmark/tests/test_bookmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from rest_framework.reverse import reverse
from rest_framework import status

from authors.apps.article.tests.base_like_test import BaseLikeTest


class Bookmark(BaseLikeTest):

def bookmark_article(self, slug):
url = reverse('article:bookmark', args=[slug])
response = self.client.post(
url, format="json", HTTP_AUTHORIZATION="Bearer " + self.token)
return response

def test__user_can_bookmark(self):
"""test user can bookmark"""
response = self.bookmark_article(self.slug)
self.assertIn("True", str(response.data))
self.assertEqual(response.status_code, status.HTTP_200_OK)

def test__user_cant_delete_bookmark_not_bookmarked(self):
"""test user cannot unbookmark before bookmarking"""
url = reverse('article:bookmark', args=[self.slug])
response = self.client.delete(
url, format="json", HTTP_AUTHORIZATION="Bearer " + self.token)
self.assertIn(
"You have not bookmarked this article yet", str(response.data))
self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)

def test__user_can_delete_bookmark(self):
"""test user can delete bookmark"""
self.bookmark_article(self.slug)
url = reverse('article:bookmark', args=[self.slug])
response = self.client.delete(
url, format="json", HTTP_AUTHORIZATION="Bearer " + self.token)
self.assertIn("unbookmarked", str(response.data))
self.assertEqual(response.status_code, status.HTTP_200_OK)

def test__user_cant_bookmark_more_than_once(self):
"""test user cant bookmark twice"""
self.bookmark_article(self.slug)
response = self.bookmark_article(self.slug)
self.assertIn(
"Article already bookmarked", str(response.data))

def test__user_cant_bookmark_article_not_existing(self):
"""test user can bookmark"""
response = self.bookmark_article('collo-deos')
self.assertIn("That article does not exist", str(response.data))
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

def test__user_cant_bookmark_article_with_no_authenticatin(self):
"""test user cant bookmark with no authentication"""
url = reverse('article:bookmark', args=[self.slug])
response = self.client.post(
url, format="json", HTTP_AUTHORIZATION="")
self.assertIn(
"Authentication credentials were not provided", str(response.data))
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test__user_cant_bookmark_article_with_no_authenticatin(self):
"""test user cant unbookmark with no authentication"""
url = reverse('article:bookmark', args=[self.slug])
response = self.client.post(
url, format="json", HTTP_AUTHORIZATION="")
self.assertIn(
"Authentication credentials were not provided", str(response.data))
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
14 changes: 14 additions & 0 deletions authors/apps/bookmark/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.urls import path
from rest_framework_swagger.views import get_swagger_view
from .views import (
BookmarkAPIView
)

schema_view = get_swagger_view(title="Bookmarks")

urlpatterns = [

path('articles/<slug>/bookmark/',
BookmarkAPIView.as_view(),
name="bookmark"),
]
61 changes: 61 additions & 0 deletions authors/apps/bookmark/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from rest_framework.exceptions import NotFound
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated

from authors.apps.bookmark.renderers import BookmarkJSONRenderer
from authors.apps.bookmark.serializers import BookmarkSerializer
from authors.apps.article.serializers import ArticleSerializer
from authors.apps.article.models import Article
from .models import Bookmark


class BookmarkAPIView(APIView):
serializer_class = BookmarkSerializer
permission_classes = (IsAuthenticated,)
queryset = Bookmark.objects.all()
renderer_classes = (BookmarkJSONRenderer,)

def post(self, request, slug):
"""Bookmark article"""
try:
article = Article.objects.get(slug=slug)
except Article.DoesNotExist:
return Response({"Message": [
"That article does not exist"
]}, status.HTTP_204_NO_CONTENT)
bookmark = dict()
bookmark["user"] = request.user.id
bookmark["article"] = article.pk
serializer = self.serializer_class(data=bookmark)
serializer.is_valid(raise_exception=True)
serializer.save()
article_serializer = ArticleSerializer(
instance=article, context={'request': request})
data = dict(article=article_serializer.data)
data["article"]["bookmarked"] = True
data["message"] = "bookmarked"
return Response(data, status.HTTP_200_OK)

def delete(self, request, slug):
"""unbookmark an article"""
try:
article = Article.objects.get(slug=slug)
except Article.DoesNotExist:
raise NotFound({"error": [
"That article does not exist"
]})
try:
bookmark = Bookmark.objects.get(
user=request.user.id, article=article.pk)
except Bookmark.DoesNotExist:
return Response(
{"Message": "You have not bookmarked this article yet"},
status.HTTP_409_CONFLICT)
bookmark.delete()
article_serializer = ArticleSerializer(
instance=article, context={'request': request})
data = dict(article=article_serializer.data)
data["message"] = "unbookmarked"
return Response(data, status.HTTP_200_OK)
1 change: 1 addition & 0 deletions authors/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@

'social_django',
"authors.apps.article",
"authors.apps.bookmark",


]
Expand Down
7 changes: 6 additions & 1 deletion authors/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,9 @@
include(
('authors.apps.report.urls',
'report'),
namespace='report'))]
namespace='report')),
path('api/',
include(
('authors.apps.bookmark.urls',
'report'),
namespace='bookmark'))]
2 changes: 2 additions & 0 deletions release-tasks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ python3 manage.py makemigrations article
python3 manage.py migrate article
python3 manage.py makemigrations report
python3 manage.py migrate report
python3 manage.py makemigrations bookmark
python3 manage.py migrate bookmark
python3 manage.py makemigrations
python3 manage.py migrate

0 comments on commit 23db497

Please sign in to comment.