diff --git a/.gitignore b/.gitignore
index 6f8f59b..e271278 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+# created by virtualenv automatically
*.pyc
*.db
-*.sqlite3
+*.sqlite3
\ No newline at end of file
diff --git a/blogging/admin.py b/blogging/admin.py
index 1175916..5a6258a 100644
--- a/blogging/admin.py
+++ b/blogging/admin.py
@@ -1,6 +1,20 @@
from django.contrib import admin
+
from blogging.models import Post, Category
+class CategoryAdmin(admin.ModelAdmin):
+ list_display = ('name', 'description')
+
+ exclude = ('posts',)
+
+class CategoryInLine(admin.TabularInline):
+ model = Category.posts.through
+
+class PostAdmin(admin.ModelAdmin):
+ inlines = [CategoryInLine,]
+
+ list_display = ('title', 'created_date',)
+
-admin.site.register(Post)
-admin.site.register(Category)
+admin.site.register(Post, PostAdmin)
+admin.site.register(Category, CategoryAdmin)
\ No newline at end of file
diff --git a/blogging/feeds.py b/blogging/feeds.py
new file mode 100644
index 0000000..d88b5b8
--- /dev/null
+++ b/blogging/feeds.py
@@ -0,0 +1,20 @@
+from django.contrib.syndication.views import Feed
+from django.urls import reverse
+from blogging.models import Post
+
+class LatestEntriesFeed(Feed):
+ title = 'Most Recent Posts'
+ link = '/sitenews/'
+ description = '5 Most Recent Posts to Site'
+
+ def items(self):
+ return Post.objects.order_by('-published_date')[:5]
+
+ def item_title(self, item):
+ return item.title
+
+ def item_author(self, item):
+ return item.author
+
+ def item_link(self, item):
+ return reverse('post', args=[item.pk])
diff --git a/blogging/migrations/0001_initial.py b/blogging/migrations/0001_initial.py
index 5d406bf..90f963a 100644
--- a/blogging/migrations/0001_initial.py
+++ b/blogging/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.1 on 2019-10-29 01:39
+# Generated by Django 2.1.1 on 2021-06-26 19:07
from django.conf import settings
from django.db import migrations, models
diff --git a/blogging/migrations/0002_category.py b/blogging/migrations/0002_category.py
index 0ccbe19..435d3ab 100644
--- a/blogging/migrations/0002_category.py
+++ b/blogging/migrations/0002_category.py
@@ -1,4 +1,4 @@
-# Generated by Django 2.1.1 on 2019-11-05 03:35
+# Generated by Django 2.1.1 on 2021-07-01 03:23
from django.db import migrations, models
@@ -16,7 +16,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=128)),
('description', models.TextField(blank=True)),
- ('posts', models.ManyToManyField(blank=True, related_name='categories', to='blogging.Post')),
+ ('posts', models.ManyToManyField(blank=True, related_name='Categories', to='blogging.Post')),
],
),
]
diff --git a/blogging/models.py b/blogging/models.py
index 10d6cc3..4d9a2ce 100644
--- a/blogging/models.py
+++ b/blogging/models.py
@@ -1,24 +1,35 @@
+from typing import Set
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
+ #title - CharField max_length = 60
title = models.CharField(max_length=128)
+ #text - TextField
text = models.TextField(blank=True)
+ #author - CharField max_length = 30
author = models.ForeignKey(User, on_delete=models.CASCADE)
+ #created_date - DateField auto_now_add=False
created_date = models.DateTimeField(auto_now_add=True)
+ #modified_date - DateField auto_now=True
modified_date = models.DateTimeField(auto_now=True)
+ #published_date - - DateField auto_now_add=True
published_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.title
+
class Category(models.Model):
+ #name
name = models.CharField(max_length=128)
+ #description
description = models.TextField(blank=True)
- posts = models.ManyToManyField(Post, blank=True, related_name='categories')
-
- class Meta:
- verbose_name_plural = 'Categories'
-
+ #posts
+ posts = models.ManyToManyField(Post, blank=True, related_name='Categories')
+
def __str__(self):
return self.name
+
+ class Meta:
+ verbose_name_plural = 'Categories'
\ No newline at end of file
diff --git a/blogging/serializers.py b/blogging/serializers.py
new file mode 100644
index 0000000..ab235d7
--- /dev/null
+++ b/blogging/serializers.py
@@ -0,0 +1,27 @@
+from django.contrib.auth.models import User, Group
+from rest_framework import serializers
+from blogging.models import Post, Category
+
+class UserSerializer(serializers.HyperlinkedModelSerializer):
+ class Meta:
+ model = User
+ fields = ['url', 'username', 'email', 'groups']
+
+
+class GroupSerializer(serializers.HyperlinkedModelSerializer):
+ class Meta:
+ model = Group
+ fields = ['url', 'name']
+
+class PostSerializer(serializers.HyperlinkedModelSerializer):
+ class Meta:
+ model = Post
+ fields = [
+ 'url', 'title', 'text', 'author', 'created_date',
+ 'modified_date','published_date',
+ ]
+
+class CategorySerializer(serializers.HyperlinkedModelSerializer):
+ class Meta:
+ model = Category
+ fields = ['url', 'name', 'description', 'posts']
diff --git a/blogging/templates/blogging/detail.html b/blogging/templates/blogging/detail.html
index ea5b9c8..cfa7b96 100644
--- a/blogging/templates/blogging/detail.html
+++ b/blogging/templates/blogging/detail.html
@@ -14,4 +14,4 @@
{{ post }}
{{ category }}
{% endfor %}
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/blogging/templates/blogging/list.html b/blogging/templates/blogging/list.html
index d8aa919..1cd6a3b 100644
--- a/blogging/templates/blogging/list.html
+++ b/blogging/templates/blogging/list.html
@@ -4,7 +4,7 @@ Recent Posts
{% for post in posts %}
Posted by {{ post.author.username }} — {{ post.published_date }}
@@ -19,4 +19,4 @@
{% endfor %}
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/blogging/tests.py b/blogging/tests.py
index 4250226..7fee97d 100644
--- a/blogging/tests.py
+++ b/blogging/tests.py
@@ -1,15 +1,12 @@
import datetime
-
from django.test import TestCase
from django.contrib.auth.models import User
from django.utils.timezone import utc
-
from blogging.models import Post
from blogging.models import Category
-
class PostTestCase(TestCase):
- fixtures = ['blogging_test_fixture.json', ]
+ fixtures = ['blogging_test_fixture.json',]
def setUp(self):
self.user = User.objects.get(pk=1)
@@ -20,16 +17,13 @@ def test_string_representation(self):
actual = str(p1)
self.assertEqual(expected, actual)
-
class CategoryTestCase(TestCase):
-
def test_string_representation(self):
expected = "A Category"
c1 = Category(name=expected)
actual = str(c1)
self.assertEqual(expected, actual)
-
class FrontEndTestCase(TestCase):
"""test views provided in the front-end"""
fixtures = ['blogging_test_fixture.json', ]
@@ -69,4 +63,4 @@ def test_details_only_published(self):
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, title)
else:
- self.assertEqual(resp.status_code, 404)
+ self.assertEqual(resp.status_code, 404)
\ No newline at end of file
diff --git a/blogging/urls.py b/blogging/urls.py
index 172a39c..95a2eb7 100644
--- a/blogging/urls.py
+++ b/blogging/urls.py
@@ -1,7 +1,9 @@
from django.urls import path
-from blogging.views import list_view, detail_view
+from blogging.views import stub_view
+from blogging.views import list_view
+from blogging.views import detail_view
urlpatterns = [
path('', list_view, name="blog_index"),
path('posts//', detail_view, name="blog_detail"),
-]
+]
\ No newline at end of file
diff --git a/blogging/views.py b/blogging/views.py
index b4bab4f..e405ca0 100644
--- a/blogging/views.py
+++ b/blogging/views.py
@@ -1,9 +1,30 @@
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import loader
+from django.contrib.auth.models import User, Group
+from blogging import serializers
+from rest_framework import viewsets
+from rest_framework import permissions
+from blogging.models import Category, Post
+from blogging.serializers import CategorySerializer, PostSerializer, UserSerializer, GroupSerializer
+from django.contrib.syndication.views import Feed
+from django.urls import reverse
-from blogging.models import Post
+def stub_view(request, *args, **kwargs):
+ body = "Stub View\n\n"
+ if args:
+ body += "Args:\n"
+ body += "\n".join(["\t%s" % a for a in args])
+ if kwargs:
+ body += "Kwargs:\n"
+ body += "\n".join(["\t%s: %s" % i for i in kwargs.items()])
+ return HttpResponse(body, content_type="text/plain")
+def list_view(request):
+ published = Post.objects.exclude(published_date__exact=None)
+ posts = published.order_by('-published_date')
+ context = {'posts': posts}
+ return render(request, 'blogging/list.html', context)
def detail_view(request, post_id):
published = Post.objects.exclude(published_date__exact=None)
@@ -14,9 +35,55 @@ def detail_view(request, post_id):
context = {'post': post}
return render(request, 'blogging/detail.html', context)
+class UserViewSet(viewsets.ModelViewSet):
+ """
+ API endpoint that allows users to be viewed or edited.
+ """
+ queryset = User.objects.all().order_by('-date_joined')
+ serializer_class = UserSerializer
+ permission_classes = [permissions.IsAuthenticated]
-def list_view(request):
- published = Post.objects.exclude(published_date__exact=None)
- posts = published.order_by('-published_date')
- context = {'posts': posts}
- return render(request, 'blogging/list.html', context)
+
+class GroupViewSet(viewsets.ModelViewSet):
+ """
+ API endpoint that allows groups to be viewed or edited.
+ """
+ queryset = Group.objects.all()
+ serializer_class = GroupSerializer
+ permission_classes = [permissions.IsAuthenticated]
+
+class PostViewSet(viewsets.ModelViewSet):
+ """
+ API endpoint that allows Post to be viewed or edited.
+ """
+ queryset = Post.objects.all()
+ serializer_class = PostSerializer
+ permission_classes = [permissions.IsAuthenticated]
+
+class CategoryViewSet(viewsets.ModelViewSet):
+ """
+ API endpoint that allows Categories to be viewed or edited.
+ """
+ queryset = Category.objects.all()
+ serializer_class = CategorySerializer
+ permission_classes = [permissions.IsAuthenticated]
+
+class LatestEntriesFeed(Feed):
+ title = 'Most Recent Posts'
+ link = '/sitenews/'
+ description = '5 Most Recent Posts to Site'
+
+ def items(self):
+ return Post.objects.order_by('-published_date')[:5]
+
+ def item_title(self, item):
+ return item.title
+
+ def item_author(self, item):
+ return item.author
+
+ def item_id(self, item):
+ return item.pk
+
+ def item_link(self, item):
+ return reverse('latest-feed', kwargs= {"id" : self.item_id})
\ No newline at end of file
diff --git a/mysite/production.py b/mysite/production.py
new file mode 100644
index 0000000..ef4250c
--- /dev/null
+++ b/mysite/production.py
@@ -0,0 +1,16 @@
+import os
+
+import dj_database_url
+
+from .settings import *
+
+
+DATABASES = {
+ 'default': dj_database_url.config(default='sqlite:///' + os.path.join(BASE_DIR, 'db.sqlite3'))
+ }
+
+DEBUG = False
+TEMPLATE_DEBUG = False
+ALLOWED_HOSTS = [os.environ.get('ALLOWED_HOSTS'), 'localhost']
+STATIC_ROOT = os.path.join(BASE_DIR, 'static')
+SECRET_KEY = os.environ.get('SECRET_KEY')
\ No newline at end of file
diff --git a/mysite/settings.py b/mysite/settings.py
index 14e4a11..3ec4c8c 100644
--- a/mysite/settings.py
+++ b/mysite/settings.py
@@ -37,8 +37,14 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'django.contrib.sites',
+ 'allauth',
+ 'allauth.account',
+ 'allauth.socialaccount',
+ 'allauth.socialaccount.providers.facebook',
'polling',
'blogging',
+ 'rest_framework',
]
MIDDLEWARE = [
@@ -123,3 +129,15 @@
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/'
+
+REST_FRAMEWORK = {
+ 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
+ 'PAGE_SIZE': 10
+}
+
+AUTHENTICATION_BACKENDS = [
+ 'django.contrib.auth.backends.ModelBackend',
+ 'allauth.account.auth_backends.AuthenticationBackend',
+]
+
+SITE_ID = 1
diff --git a/mysite/templates/base.html b/mysite/templates/base.html
index 4bb0230..8e6acaf 100644
--- a/mysite/templates/base.html
+++ b/mysite/templates/base.html
@@ -1,4 +1,4 @@
-{% load staticfiles %}
+{% load static %}
@@ -6,16 +6,16 @@
-
{% block content %}
@@ -24,4 +24,4 @@
-
+