Skip to content

Commit

Permalink
Merge b5ad087 into d40c9c7
Browse files Browse the repository at this point in the history
  • Loading branch information
KITHU committed Nov 9, 2018
2 parents d40c9c7 + b5ad087 commit 391be4e
Show file tree
Hide file tree
Showing 17 changed files with 469 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var/
*.egg
.idea/
.vscode/
.pylintrc

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
Binary file modified authors/apps/.DS_Store
Binary file not shown.
8 changes: 2 additions & 6 deletions authors/apps/articles/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
# Generated by Django 2.1.2 on 2018-11-08 20:53
# Generated by Django 2.1.2 on 2018-11-06 07:54

from django.conf import settings
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
Expand All @@ -21,14 +18,13 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(db_index=True, max_length=255)),
('body', models.TextField()),
('images', django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), blank=True, default=None, null=True, size=None)),
('image', models.ImageField(blank=True, height_field=100, null=True, upload_to='photos/%Y/%m/%d/', width_field=100)),
('description', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=40, unique=True)),
('tags', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=30), blank=True, default=None, null=True, size=None)),
('time_to_read', models.IntegerField()),
('time_created', models.DateTimeField(auto_now_add=True, db_index=True)),
('time_updated', models.DateTimeField(auto_now=True, db_index=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ('time_created', 'time_updated'),
Expand Down
22 changes: 22 additions & 0 deletions authors/apps/articles/migrations/0002_article_author.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 2.1.2 on 2018-11-06 08:05

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('articles', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='article',
name='author',
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]
23 changes: 23 additions & 0 deletions authors/apps/articles/migrations/0003_auto_20181107_0615.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 2.1.2 on 2018-11-07 06:15

import django.contrib.postgres.fields
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('articles', '0002_article_author'),
]

operations = [
migrations.RemoveField(
model_name='article',
name='image',
),
migrations.AddField(
model_name='article',
name='images',
field=django.contrib.postgres.fields.ArrayField(base_field=models.TextField(), blank=True, default=None, null=True, size=None),
),
]
28 changes: 28 additions & 0 deletions authors/apps/articles/migrations/0004_comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 2.1.2 on 2018-11-09 07:40

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('articles', '0003_auto_20181107_0615'),
]

operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('body', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('article', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='articles.Article')),
('author', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='comments', to=settings.AUTH_USER_MODEL)),
('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='thread', to='articles.Comment')),
],
),
]
31 changes: 28 additions & 3 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@

from authors.apps.authentication.models import User


class Article(models.Model):
'''Model representing articles'''
title = models.CharField(db_index=True, max_length=255)
body = models.TextField()
images = ArrayField(models.TextField(), default=None, blank=True, null=True)
images = ArrayField(models.TextField(), default=None,
blank=True, null=True)
description = models.CharField(max_length=255)
slug = models.SlugField(max_length=40, unique=True)
tags = ArrayField(models.CharField(max_length=30), default=None, blank=True, null=True)
tags = ArrayField(models.CharField(max_length=30),
default=None, blank=True, null=True)
time_to_read = models.IntegerField()
# auto_now_add automatically sets the field to now when the object is first created.
time_created = models.DateTimeField(auto_now_add=True, db_index=True)
Expand All @@ -29,5 +32,27 @@ def save(self, *args, **kwargs):
super(Article, self).save(*args, **kwargs)

def __str__(self):
'''return string representation of object'''
return self.title


class Comment(models.Model):
"""
This class implement a database table.
This table has seven fields one is automatically generated by django
The relationship between articles and comments is one to many
The relationship between comment and reply is one to many.
the relationship between Author and comments is one to many
"""
parent = models.ForeignKey(
'self', null=True, blank=False, on_delete=models.CASCADE, related_name='thread')
article = models.ForeignKey(
Article, blank=True, null=True, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(
User, blank=True, null=True, on_delete=models.CASCADE, related_name='comments')
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return self.body

83 changes: 76 additions & 7 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,33 @@
from rest_framework.exceptions import PermissionDenied

from .models import Article
from .models import Comment
from authors.apps.authentication.serializers import UserSerializer
from authors.apps.authentication.models import User
from authors.apps.profiles.serializers import ProfileSerializer
from authors.apps.profiles.models import Profile


class ArticleSerializer(serializers.ModelSerializer):
'''Article model serializer'''
author = UserSerializer(read_only=True)
title = serializers.CharField(required=True, max_length=100)
body = serializers.CharField()
images = serializers.ListField(child=serializers.CharField(max_length=1000), min_length=None, max_length=None, required=False)
images = serializers.ListField(child=serializers.CharField(
max_length=1000), min_length=None, max_length=None, required=False)
description = serializers.CharField()
slug = serializers.CharField(required=False)
tags = serializers.ListField(child=serializers.CharField(max_length=25), min_length=None, max_length=None, required=False)
tags = serializers.ListField(child=serializers.CharField(
max_length=25), min_length=None, max_length=None, required=False)

time_to_read = serializers.IntegerField(required=False)
time_created = serializers.SerializerMethodField()
time_updated = serializers.SerializerMethodField()
favorited = serializers.SerializerMethodField()
favoritesCount = serializers.SerializerMethodField(method_name='get_favorites_count')

favoritesCount = serializers.SerializerMethodField(
method_name='get_favorites_count')

class Meta:
'''Class defining fields passed to database'''
model = Article
fields = ('title', 'body', 'images', 'description', 'slug', 'tags',
'time_to_read', 'author', 'time_created', 'time_updated', 'favorited', 'favoritesCount')
Expand Down Expand Up @@ -54,9 +64,11 @@ def update(self, instance, validated_data):
raise PermissionDenied
instance.title = validated_data.get('title', instance.title)
instance.body = validated_data.get('body', instance.body)
instance.description = validated_data.get('description', instance.description)
instance.description = validated_data.get(
'description', instance.description)
instance.tags = validated_data.get('tags', instance.tags)
instance.time_to_read = validated_data.get('time_to_read', instance.time_to_read)
instance.time_to_read = validated_data.get(
'time_to_read', instance.time_to_read)
instance.save()
return instance

Expand All @@ -73,3 +85,60 @@ def get_favorited(self, instance):

def get_favorites_count(self, instance):
return instance.favorited_by.count()


class RecursiveSerializer(serializers.Serializer):
"""
This class deals with a comment within a comment
"""

def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data


class CommentSerializer(serializers.ModelSerializer):
"""
This class creates the comments serializers
"""
author = serializers.SerializerMethodField()
article = serializers.ReadOnlyField(source='article.title')
thread = RecursiveSerializer(many=True, read_only=True)

class Meta:
model = Comment

fields = (
'id',
'body',
'article',
'author',
'thread',
'created_at',
'updated_at'
)

def update(self, instance, valid_input, **kwargs):
"""
Update and return a comment instance, given valid_input
"""
instance.body = valid_input.get('body', instance.body)
instance.save()
return instance

def get_author(self, obj):
try:
author = obj.author
profile = Profile.objects.get(user_id=author.id)
serializer = ProfileSerializer(profile)
return serializer.data
except Exception as e:
return {}

def create(self, valid_input):
"""
Create and return a new comment instance, given a valid_input
"""
parent = self.context.get('parent', None)
instance = Comment.objects.create(parent=parent, **valid_input)
return instance
38 changes: 31 additions & 7 deletions authors/apps/articles/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import json
from django.test import TestCase
from rest_framework.test import APIClient

class BaseTest(TestCase):
"""
Test user views
Expand All @@ -14,9 +13,17 @@ def setUp(self):
self.SIGN_IN_URL = '/api/users/login/'
self.SIGN_UP_URL = '/api/users/'
self.ARTICLES = '/api/articles/'
self.ARTICLE = '/api/articles/{}/'
self.ARTICLE = '/api/articles/{}/'
self.TESTARTICLE = '/api/articles/test-title/'

self.CREATE_A_COMMENT = '/api/articles/{}/comment/'
self.FETCH_ALL_COMMENTS = '/api/articles/{}/comment/'

self.CREATE_A_REPLY = '/api/articles/{}/comment/{}/'
self.FETCH_A_COMMENT = '/api/articles/{}/comment/{}/'
self.UPDATE_A_COMMENT = '/api/articles/{}/comment/{}/'
self.DELETE_A_COMMENT = '/api/articles/{}/comment/{}/'

self.client = APIClient()

test_user = {
Expand All @@ -37,18 +44,34 @@ def setUp(self):
}

self.test_article_data = {
"title": "test title",
"body": "This is me testing",
"description": "testing",
"time_to_read": 1,
"tags": ["TDD"]

"title": "test title",
"body": "This is me testing",
"description": "testing",
"time_to_read": 1,
"tags": ["TDD"]
}

self.sample_comment = {"body": "this is a sample comment"}
self.sample_update = {"body": "this is a sample comment five"}

self.client.post(self.SIGN_UP_URL, test_user, format="json")
response = self.client.post(self.SIGN_IN_URL, test_user, format="json")
self.token = "bearer " + json.loads(response.content)["user"]["token"]

self.client.post(self.SIGN_UP_URL, test_non_author_user, format="json")

response = self.client.post(
self.SIGN_IN_URL, test_non_author_user, format="json")
self.non_user_token = "bearer " + \
json.loads(response.content)["user"]["token"]

self.client.post(self.ARTICLES, self.test_article_data,
HTTP_AUTHORIZATION=self.token, format="json")
self.client.post(self.ARTICLES, self.test_article_data,
HTTP_AUTHORIZATION=self.token, format="json")


response = self.client.post(self.SIGN_IN_URL, test_non_author_user, format="json")
self.non_user_token = "bearer " + json.loads(response.content)["user"]["token"]

Expand Down Expand Up @@ -76,3 +99,4 @@ def create_article(self, article, token):
HTTP_AUTHORIZATION = 'Bearer ' + token,
format='json'
)

Loading

0 comments on commit 391be4e

Please sign in to comment.