Skip to content

Commit

Permalink
feat(Articles):Users can report Articles
Browse files Browse the repository at this point in the history
  • Loading branch information
kafuuma Henry authored and kafuuma Henry committed Dec 18, 2018
1 parent 16d90d8 commit 850eb93
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ db.sqlite3
.vscode/
.DS_Store
*.swp
# migrations/
migrations/
18 changes: 18 additions & 0 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,21 @@ class Likes(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)

like = models.BooleanField()


class ReportArticle(models.Model):
"""This class implements a model report articles that violate
terms of agreement
"""
article = models.ForeignKey(Article, on_delete=models.CASCADE)
reported_by = models.ForeignKey(Profile, on_delete=models.CASCADE)
reason = models.CharField(db_index=True, null=False, max_length=255)
reported_at = models.DateTimeField(auto_now_add=True)

objects = models.Manager()

# def __str__(self):
# return self.article

class Meta:
ordering = ['reported_at']
34 changes: 32 additions & 2 deletions authors/apps/articles/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ def render(self, data, media_type=None, renderer_context=None):
the default JSONRenderer to handle rendering errors, so we need to
check for this case.
"""

errors = data.get('errors', None)

if errors is not None:
"""
As mentioned about, we will let the default JSONRenderer handle
rendering errors.
return super(ArticlesJSONRenderer, self).render(data)
"""
return super(ArticleJSONRenderer, self).render(data)
"""Finally, we can render our data under the "user" namespace."""
return json.dumps({
'article': data
Expand All @@ -38,3 +38,33 @@ def render(self, data, media_type=None, renderer_context=None):
})


class ArticleReportJSONRenderer(JSONRenderer):
charset = 'utf-8'

def render(self, data, media_type=None, renderer_context=None):

errors = data.get('errors', None)

if errors is not None:

return super(ArticleReportJSONRenderer, self).render(data)

return json.dumps({
'reported': data
})


class ArticleListReportJSONRenderer(JSONRenderer):
charset = 'utf-8'

def render(self, data, media_type=None, renderer_context=None):

errors = data.get('errors', None)

if errors is not None:

return super(ArticleListReportJSONRenderer, self).render(data)

return json.dumps({
'reported': data
})
26 changes: 24 additions & 2 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
Article,
ArticleImg,
Tag,
Favourites, Likes
Favourites,
Likes,
ReportArticle,
)


Expand Down Expand Up @@ -63,7 +65,7 @@ class ArticleImgSerializer(serializers.ModelSerializer):

class Meta:
model = ArticleImg
fields = ['image_url', 'description',
fields = ['id', 'image_url', 'description',
'position_in_body_before', 'article']


Expand Down Expand Up @@ -108,3 +110,23 @@ class LikeArticleViewSerializer(serializers.ModelSerializer):
class Meta:
model = Likes
fields = ['id', 'article', 'profile', 'like']


class ReportArticleSerializer(serializers.ModelSerializer):
reported_by = ProfileSerializer(read_only=True)
reported_at = serializers.DateTimeField(read_only=True)
# slug = serializers.CharField(read_only=True)

reason = serializers.CharField()

def to_representation(self, instance):
# article = CreateArticleViewSerializer(read_only=True)
response = super().to_representation(instance)
article = Article.objects.all().values()[0]
response['article'] = article['slug']
print(article)
return response

class Meta:
model = ReportArticle
fields = ['reported_by', 'reason', 'reported_at', 'article']
15 changes: 11 additions & 4 deletions authors/apps/articles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,23 @@
ArticleTagsAPIView,
ArticleDeleteAPIView,
FavouritesView,
LikeArticleView
LikeArticleView,
ReporteArticleAPIView,
ReportedArticleListAPIView,
)

urlpatterns = [
path('articles', RetrieveArticlesAPIView.as_view(),),
path('articles/<str:slug>/like/',
LikeArticleView.as_view(), name='article-like'),
path('articles/<str:slug>/', CreateArticleView.as_view()),
path('articles/', CreateArticleView.as_view(), name='article-create'),
path('articles/<str:slug>/', CreateArticleView.as_view(), name='article-create'),
path('articles/', CreateArticleView.as_view()),
path('<slug>/tags/', ArticleTagsAPIView.as_view(), name='article-tags'),
path('<slug>/tags/<tag>/', ArticleDeleteAPIView.as_view(), name='delete-tag'),
path('articles/<slug>/favorite/', FavouritesView.as_view())
path('articles/<slug>/favorite/', FavouritesView.as_view()),
path('articles/<str:slug>/report/',
ReporteArticleAPIView.as_view(), name='report-aticle'),
path('reported/',
ReportedArticleListAPIView.as_view(), name='reported'),

]
95 changes: 90 additions & 5 deletions authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,29 @@
from rest_framework.permissions import (
AllowAny,
IsAuthenticated,
IsAuthenticatedOrReadOnly
IsAuthenticatedOrReadOnly,
IsAdminUser,
)
from rest_framework.response import Response
from rest_framework import exceptions
from django.template.defaultfilters import slugify

from ..authentication.backends import JWTAuthentication
from ..authentication.models import User
from .renderers import ArticleJSONRenderer, ListArticlesJSONRenderer
from .models import ArticleImg, Article, Tag, Favourites, Likes
from .renderers import(
ArticleJSONRenderer,
ListArticlesJSONRenderer,
ArticleReportJSONRenderer,
ArticleListReportJSONRenderer
)
from .models import(
ArticleImg,
Article,
Tag,
Favourites,
Likes,
ReportArticle
)

from ..profiles.models import Profile

Expand All @@ -34,7 +47,8 @@
ArticleImgSerializer,
TagsSerializer,
FavouriteSerializer,
LikeArticleViewSerializer
LikeArticleViewSerializer,
ReportArticleSerializer

)

Expand Down Expand Up @@ -131,7 +145,13 @@ def delete(self, request, slug):
{"error": "You can only delete your own articles"},
status=status.HTTP_401_UNAUTHORIZED
)
article.delete()
try:
article.delete()
except Exception as e:
print('###########################', e)
return Response(
{'error': str(e)}, status=status.HTTP_403_FORBIDDEN
)
except Article.DoesNotExist:
error = {"error": "This article doesnot exist"}
return Response(error, status=status.HTTP_404_NOT_FOUND)
Expand Down Expand Up @@ -412,3 +432,68 @@ def delete(self, request, slug):
serializer.save(article=current_article, profile=profile)

return Response(serializer.data, status=status.HTTP_201_CREATED)


class ReporteArticleAPIView(GenericAPIView):
permission_classes = (IsAuthenticated,)
renderer_classes = (ArticleReportJSONRenderer,)
serializer_class = ReportArticleSerializer

def post(self, request, *args, **kwargs):

user_data = JWTAuthentication().authenticate(request)
profile = Profile.objects.get(user__id=user_data[0].id)
slug = kwargs['slug']
report = request.data.get('report', {})
if report == {}:
return Response(
{"errors": "Provide reason for reporting"},
status=status.HTTP_400_BAD_REQUEST
)
try:
article_ob = Article.objects.get(
slug=slug
)
except Article.DoesNotExist:
return Response(
{"errors": "This article doesnot exist"},
status=status.HTTP_404_NOT_FOUND
)
article_to_repot = ReportArticle.objects.filter(
article_id=article_ob.id).first()

if article_to_repot is not None:
return Response(
data={"errors": "This article has been reported already"},
status=status.HTTP_409_CONFLICT
)
serializer = self.serializer_class(data=report, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save
serializer.save(
article=article_ob,
reported_by=profile
)
article_ob.published = False
reported_art_obj = ReportArticle.objects.filter(
article_id=article_ob.id).first()
serializerized_data = self.serializer_class(reported_art_obj)
images = ArticleImg.objects.filter(
article_id=reported_art_obj.article_id)
image_list = list(images.values())
data = serializerized_data.data
data['images'] = image_list
data['message'] = 'article has been reported'
return Response(data=data, status=status.HTTP_200_OK)


class ReportedArticleListAPIView(GenericAPIView):
serializer_class = ReportArticleSerializer
# renderer_classes = (ArticleListReportJSONRenderer,)
permission_classes = (IsAuthenticated, IsAdminUser)

def get(self, request):
queryset = ReportArticle.objects.all()
serializer = self.serializer_class(queryset, many=True)
data = serializer.data
return Response({"articles": data}, status=status.HTTP_200_OK)
51 changes: 51 additions & 0 deletions authors/data
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
class ReporteArticleAPIView(GenericAPIView):
permission_classes = (IsAuthenticated,)
renderer_classes = (ArticleReportJSONRenderer,)
serializer_class = ReportArticleSerializer

def post(self, request, *args, **kwargs):

user_data = JWTAuthentication().authenticate(request)
profile = Profile.objects.get(user__id=user_data[0].id)
slug = kwargs['slug']
report = request.data.get('report', {})
if report == {}:
return Response(
{"errors": "Provide reason for reporting"},
status=status.HTTP_400_BAD_REQUEST
)
try:
article_ob = Article.objects.get(
slug=slug
)
except Article.DoesNotExist:
return Response(
{"errors": "This article doesnot exist"},
status=status.HTTP_404_NOT_FOUND
)
article_to_repot = ReportArticle.objects.filter(
article_id=article_ob.id).first()

if article_to_repot is not None:
return Response(
data={"errors": "This article has been reported already"},
status=status.HTTP_409_CONFLICT
)
serializer = self.serializer_class(data=report, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save
serializer.save(
article=article_ob,
reported_by=profile
)
article_ob.published = False
reported_art_obj = ReportArticle.objects.filter(
article_id=article_ob.id).first()
serializerized_data = self.serializer_class(reported_art_obj)
images = ArticleImg.objects.filter(
article_id=reported_art_obj.article_id)
image_list = list(images.values())
data = serializerized_data.data
data['images'] = image_list
data['message'] = 'article has been reported'
return Response(data=data, status=status.HTTP_200_OK)

0 comments on commit 850eb93

Please sign in to comment.