-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(bookmark) create delete bookmark
- user can create bookmark - user can delete bookmark [Delivers #161254679]
- Loading branch information
Showing
15 changed files
with
196 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,4 +74,5 @@ | |
path('articles/<slug:slug>/history/<int:id>', | ||
CommentHistoryAPIView.as_view(), | ||
name='comment_history'), | ||
|
||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,6 +55,7 @@ | |
|
||
'social_django', | ||
"authors.apps.article", | ||
"authors.apps.bookmark", | ||
|
||
|
||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters