-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from andela/ft-create-articles-161967014
#161967014 Create CRUD functions for the articles
- Loading branch information
Showing
28 changed files
with
940 additions
and
44 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
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,7 @@ | ||
from django.contrib import admin | ||
from .models import Articles | ||
|
||
# Register your models here. | ||
|
||
|
||
admin.site.register(Articles) |
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,5 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class ArticlesConfig(AppConfig): | ||
name = 'articles' |
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,24 @@ | ||
from django.db import models | ||
from authors.apps.authentication.models import User | ||
|
||
# Create your models here. | ||
|
||
|
||
class Articles(models.Model): | ||
""" Model for all articles """ | ||
slug = models.SlugField(max_length=250, default='non') | ||
title = models.CharField(max_length=50, default='non') | ||
description = models.CharField(max_length=250, default='non') | ||
body = models.CharField(max_length=550, default='non') | ||
tagList = models.CharField(max_length=50, | ||
default='non') # ["dragons", "training"], | ||
createdAt = models.DateTimeField(auto_now_add=True) | ||
updatedAt = models.DateTimeField(auto_now=True) | ||
favorited = models.BooleanField(default=False) | ||
favoritesCount = models.IntegerField(default=0) | ||
readtime = models.IntegerField(default=0) | ||
author = models.ForeignKey(User, default=0, on_delete=models.CASCADE) | ||
|
||
def __str__(self): | ||
""" String representation of db object """ | ||
return ' {}: {}'.format(self.id, self.slug) |
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,143 @@ | ||
from rest_framework import serializers | ||
from .models import Articles | ||
from authors.apps.authentication.models import User | ||
|
||
|
||
class ArticleSerializer(serializers.ModelSerializer): | ||
|
||
class Meta: | ||
model = Articles | ||
fields = ("__all__") | ||
|
||
@staticmethod | ||
def get_all_objects(): | ||
articles = Articles.objects.all() | ||
user = AuthorSerializer() | ||
|
||
articles_list = [] | ||
for article in articles: | ||
article = { | ||
"slug": article.slug, | ||
"title": article.title, | ||
"description": article.description, | ||
"body": article.body, | ||
"tagList": article.tagList.split(","), | ||
"createdAt": article.createdAt, | ||
"updatedAt": article.updatedAt, | ||
"favorited": article.favorited, | ||
"favoritesCount": article.favoritesCount, | ||
"author": user.get_author_objects(article.author.pk) | ||
} | ||
articles_list.append(article) | ||
|
||
return (articles_list) | ||
|
||
def get_specific_objects(self, slug): | ||
self.article = Articles.objects.get(slug=slug) | ||
user = AuthorSerializer() | ||
article = { | ||
"slug": self.article.slug, | ||
"title": self.article.title, | ||
"description": self.article.description, | ||
"body": self.article.body, | ||
"tagList": self.article.tagList.split(","), | ||
"createdAt": self.article.createdAt, | ||
"updatedAt": self.article.updatedAt, | ||
"favorited": self.article.favorited, | ||
"favoritesCount": self.article.favoritesCount, | ||
"author": user.get_author_objects(self.article.author.pk) | ||
} | ||
|
||
return (article) | ||
|
||
def posting_articles(self, value): # dictionary passed from view | ||
author_details = self.get_authors_object( | ||
value['author']) # get user object | ||
article_slug = self.slugify_string(value['title']) | ||
read_time = self.readTime(value['body']) | ||
|
||
self.new_article = Articles( | ||
slug=article_slug, | ||
title=value['title'], | ||
description=value['description'], | ||
body=value['body'], | ||
tagList=value['tagList'], | ||
author=author_details, | ||
readtime=read_time) | ||
|
||
try: | ||
self.new_article.save() | ||
return (self.get_all_objects()) | ||
|
||
except Exception as What_is_this: | ||
print('error {}'.format(What_is_this)) | ||
return ("Could not post") | ||
|
||
def get_authors_object(self, name): | ||
user_details = User.objects.get(username=name) | ||
return user_details | ||
|
||
def slugify_string(self, string): | ||
string = string.lower() | ||
processed_slug = string.replace(" ", "-") | ||
|
||
db_check = Articles.objects.filter(slug=processed_slug).count() | ||
if db_check < 1: # Slug exists in DB | ||
return processed_slug | ||
|
||
else: | ||
new_slug = '{}*'.format(processed_slug) | ||
return self.slugify_string(new_slug) | ||
|
||
def readTime(self, story): | ||
story_list = story.split(" ") | ||
resolved_time = (len(story_list)) / 200 | ||
read_time = round(resolved_time) | ||
return read_time | ||
|
||
def updateArticle(self, value, passed_slug): | ||
try: | ||
Articles.objects.filter( | ||
slug=passed_slug).update( | ||
slug=self.slugify_string( | ||
value['title']), | ||
title=value['title'], | ||
description=value['description'], | ||
body=value['body'], | ||
tagList=value['tagList'], | ||
readtime=self.readTime( | ||
value['body'])) | ||
return ('Update was successful, Title: {}'.format(value['title'])) | ||
|
||
except Exception as What_is_this: | ||
print('Received error is : {}'.format(What_is_this)) | ||
return ('error') | ||
|
||
def deleteArticle(self, passed_slug): | ||
try: | ||
deleted_article = Articles.objects.get(slug=passed_slug) | ||
title = deleted_article.title | ||
deleted_article.delete() | ||
return('Article title: {} deleted successfully'.format(title)) | ||
|
||
except Exception as What_is_this: | ||
print('Received error is : {}'.format(What_is_this)) | ||
return ("Article does not exist") | ||
|
||
|
||
class AuthorSerializer(serializers.ModelSerializer): | ||
|
||
class Meta: | ||
model = User | ||
fields = ("__all__") | ||
|
||
def get_author_objects(self, id): | ||
user = User.objects.get(pk=id) | ||
|
||
author = { | ||
'username': user.username, | ||
'bio': 'profile.bio', | ||
'image': 'profile.image', | ||
# 'following': profile.following | ||
} | ||
return (author) |
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,74 @@ | ||
import json | ||
from django.urls import reverse | ||
from rest_framework import status | ||
from rest_framework.test import APITestCase | ||
from django.contrib.auth import get_user_model | ||
|
||
from authors.apps.articles.models import Articles | ||
from authors.apps.authentication.models import User | ||
|
||
|
||
class TestGetEndpoint(APITestCase): | ||
|
||
def setUp(self): | ||
|
||
self.token = self.get_user_token() | ||
|
||
self.slug = "life-love-death" | ||
self.title = "Life Love and Death" | ||
self.description = "What is life?" | ||
self.body = "This is the real life body." | ||
self.tagList = "life,love,death" | ||
self.favorited = True | ||
self.favoritesCount = 4 | ||
self.author = 'TestAuthor' | ||
|
||
self.article = Articles( | ||
slug=self.slug, | ||
title=self.title, | ||
description=self.description, | ||
body=self.body, | ||
tagList=self.tagList, | ||
favorited=True, | ||
favoritesCount=self.favoritesCount, | ||
author=User.objects.get(username=self.author)) | ||
self.article.save() | ||
|
||
def test_delArticle_status(self): | ||
url = reverse('articleSpecific', kwargs={'slug': 'life-love-death'}) | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
response = self.client.delete(url) | ||
response.render() | ||
self.assertIn( | ||
b'Article title: Life Love and Death deleted successfully', | ||
response.content) | ||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
|
||
def test_wrong_status(self): | ||
url = reverse('articleSpecific', kwargs={'slug': 'life-love'}) | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
response = self.client.delete(url) | ||
response.render() | ||
self.assertIn(b'Article does not exist', response.content) | ||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) | ||
|
||
def get_user_token(self): | ||
user = { | ||
"user": { | ||
"username": "TestAuthor", | ||
"email": "test_user@email.com", | ||
"password": "test123user#Password" | ||
} | ||
} | ||
|
||
response = self.client.post( | ||
reverse('register'), data=user, format='json') | ||
user = get_user_model() | ||
user = user.objects.get(username="TestAuthor") | ||
user.is_active = True | ||
user.save() | ||
response.render() | ||
data = response.content | ||
token = json.loads(data.decode('utf-8'))['user']['token'] | ||
return token | ||
# Token returned after login |
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,103 @@ | ||
import json | ||
|
||
from rest_framework.test import APITestCase | ||
from django.urls import reverse | ||
from rest_framework import status | ||
from django.contrib.auth import get_user_model | ||
|
||
from authors.apps.articles.models import Articles | ||
from authors.apps.authentication.models import User | ||
|
||
|
||
class TestGetEndpoint(APITestCase): | ||
|
||
def setUp(self): | ||
""" Prepares table for tests """ | ||
self.token = self.get_user_token() | ||
|
||
self.slug = "life_love_death" | ||
self.title = "Life Love and Death" | ||
self.description = "What is life?" | ||
self.body = "This is the real life body." | ||
self.tagList = "life,love,death" | ||
self.favorited = True | ||
self.favoritesCount = 4 | ||
self.author = 'TestAuthor' | ||
|
||
self.article = Articles( | ||
slug=self.slug, | ||
title=self.title, | ||
description=self.description, | ||
body=self.body, | ||
tagList=self.tagList, | ||
favorited=self.favorited, | ||
favoritesCount=self.favoritesCount, | ||
author=User.objects.get(username=self.author)) | ||
self.article.save() | ||
|
||
def test_getArticle_status(self): | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
url = reverse('articles') | ||
response = self.client.get(url) | ||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
|
||
# Test for specific article calls | ||
|
||
def test_getArticle_content(self): | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
url = reverse('articles') | ||
response = self.client.get(url) | ||
|
||
response.render() | ||
self.assertIn(b"life_love_death", response.content) | ||
self.assertIn(b"Life Love and Death", response.content) | ||
self.assertIn(b"What is life?", response.content) | ||
self.assertIn(b"This is the real life body.", response.content) | ||
self.assertIn(b"[\"life\",\"love\",\"death\"]", response.content) | ||
self.assertIn(b"4", response.content) | ||
|
||
def test_get_specific_article(self): | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
url = reverse('articleSpecific', kwargs={'slug': 'life_love_death'}) | ||
response = self.client.get(url) | ||
self.assertEqual(response.status_code, status.HTTP_200_OK) | ||
|
||
response.render() | ||
self.assertIn(b"life_love_death", response.content) | ||
self.assertIn(b"Life Love and Death", response.content) | ||
self.assertIn(b"What is life?", response.content) | ||
self.assertIn(b"This is the real life body.", response.content) | ||
self.assertIn(b"[\"life\",\"love\",\"death\"]", response.content) | ||
self.assertIn(b"4", response.content) | ||
|
||
def test_wrong_request(self): | ||
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token) | ||
url = reverse( | ||
'articleSpecific', kwargs={ | ||
'slug': 'life_love_death_live'}) | ||
response = self.client.get(url) | ||
self.assertNotEqual(response.status_code, status.HTTP_200_OK) | ||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) | ||
|
||
response.render() | ||
self.assertIn(b"Article does not exist", response.content) | ||
|
||
def get_user_token(self): | ||
user = { | ||
"user": { | ||
"username": "TestAuthor", | ||
"email": "test_user@email.com", | ||
"password": "test123user#Password" | ||
} | ||
} | ||
|
||
response = self.client.post( | ||
reverse('register'), data=user, format='json') | ||
user = get_user_model() | ||
user = user.objects.get(username="TestAuthor") | ||
user.is_active = True | ||
user.save() | ||
response.render() | ||
data = response.content | ||
token = json.loads(data.decode('utf-8'))['user']['token'] | ||
return token |
Oops, something went wrong.