From b725a6ae1b843e8a6225e60a8061989c519734d8 Mon Sep 17 00:00:00 2001 From: Colleen Kaku Date: Mon, 8 Mar 2021 12:00:26 -0800 Subject: [PATCH 1/4] Completed Lesson 07 assignment. --- blogging/admin.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/blogging/admin.py b/blogging/admin.py index 1175916..252e3ee 100644 --- a/blogging/admin.py +++ b/blogging/admin.py @@ -2,5 +2,17 @@ from blogging.models import Post, Category -admin.site.register(Post) -admin.site.register(Category) +class CategoryInline(admin.StackedInline): + model = Category.posts.through + + +class PostAdmin(admin.ModelAdmin): + inlines = [CategoryInline, ] + + +class CategoryAdmin(admin.ModelAdmin): + exclude = ('posts', ) + + +admin.site.register(Post, PostAdmin) +admin.site.register(Category, CategoryAdmin) From d92ca7ed41054b1a338e2a85cd96f259a26950d1 Mon Sep 17 00:00:00 2001 From: Colleen Kaku Date: Tue, 9 Mar 2021 14:33:18 -0800 Subject: [PATCH 2/4] Added Django Rest Framework for User, Group, Post, Category endpoints. --- mysite/quickstart/__init__.py | 0 mysite/quickstart/admin.py | 3 +++ mysite/quickstart/apps.py | 5 ++++ mysite/quickstart/migrations/__init__.py | 0 mysite/quickstart/models.py | 3 +++ mysite/quickstart/serializers.py | 27 +++++++++++++++++++++ mysite/quickstart/tests.py | 3 +++ mysite/quickstart/views.py | 30 ++++++++++++++++++++++++ mysite/settings.py | 6 +++++ mysite/templates/base.html | 2 +- mysite/urls.py | 13 +++++++++- 11 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 mysite/quickstart/__init__.py create mode 100644 mysite/quickstart/admin.py create mode 100644 mysite/quickstart/apps.py create mode 100644 mysite/quickstart/migrations/__init__.py create mode 100644 mysite/quickstart/models.py create mode 100644 mysite/quickstart/serializers.py create mode 100644 mysite/quickstart/tests.py create mode 100644 mysite/quickstart/views.py diff --git a/mysite/quickstart/__init__.py b/mysite/quickstart/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mysite/quickstart/admin.py b/mysite/quickstart/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/mysite/quickstart/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/mysite/quickstart/apps.py b/mysite/quickstart/apps.py new file mode 100644 index 0000000..3308061 --- /dev/null +++ b/mysite/quickstart/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class QuickstartConfig(AppConfig): + name = 'quickstart' diff --git a/mysite/quickstart/migrations/__init__.py b/mysite/quickstart/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mysite/quickstart/models.py b/mysite/quickstart/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/mysite/quickstart/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/mysite/quickstart/serializers.py b/mysite/quickstart/serializers.py new file mode 100644 index 0000000..942dfd4 --- /dev/null +++ b/mysite/quickstart/serializers.py @@ -0,0 +1,27 @@ +from django.contrib.auth.models import User, Group +from blogging.models import Post, Category +from rest_framework import serializers + + +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 = ['title', 'text', 'author', 'created_date', 'modified_date', 'published_date'] + + +class CategorySerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Category + fields = ['name', 'description', 'posts'] \ No newline at end of file diff --git a/mysite/quickstart/tests.py b/mysite/quickstart/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/mysite/quickstart/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/mysite/quickstart/views.py b/mysite/quickstart/views.py new file mode 100644 index 0000000..fac9561 --- /dev/null +++ b/mysite/quickstart/views.py @@ -0,0 +1,30 @@ +from django.shortcuts import render +from django.contrib.auth.models import User, Group +from blogging.models import Post, Category +from rest_framework import viewsets +from rest_framework import permissions +from mysite.quickstart.serializers import UserSerializer, GroupSerializer, PostSerializer, CategorySerializer + + +class UserViewSet(viewsets.ModelViewSet): + queryset = User.objects.all().order_by('-date_joined') + serializer_class = UserSerializer + permission_classes = [permissions.IsAuthenticated] + + +class GroupViewSet(viewsets.ModelViewSet): + queryset = Group.objects.all() + serializer_class = GroupSerializer + permission_classes = [permissions.IsAuthenticated] + + +class PostViewSet(viewsets.ModelViewSet): + queryset = Post.objects.all().order_by('-created_date') + serializer_class = PostSerializer + permission_classes = [permissions.IsAuthenticated] + + +class CategoryViewSet(viewsets.ModelViewSet): + queryset = Category.objects.all() + serializer_class = CategorySerializer + permission_classes = [permissions.IsAuthenticated] \ No newline at end of file diff --git a/mysite/settings.py b/mysite/settings.py index 14e4a11..663aaa4 100644 --- a/mysite/settings.py +++ b/mysite/settings.py @@ -39,6 +39,7 @@ 'django.contrib.staticfiles', 'polling', 'blogging', + 'rest_framework', ] MIDDLEWARE = [ @@ -123,3 +124,8 @@ LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/' + +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 10, +} diff --git a/mysite/templates/base.html b/mysite/templates/base.html index 4bb0230..9835a36 100644 --- a/mysite/templates/base.html +++ b/mysite/templates/base.html @@ -1,4 +1,4 @@ -{% load staticfiles %} +{% load static %} diff --git a/mysite/urls.py b/mysite/urls.py index 446cd8f..fcb5f88 100644 --- a/mysite/urls.py +++ b/mysite/urls.py @@ -16,12 +16,23 @@ from django.contrib import admin from django.urls import path, include from django.contrib.auth.views import LoginView, LogoutView +from rest_framework import routers +from mysite.quickstart import views + + +router = routers.DefaultRouter() +router.register(r'users', views.UserViewSet) +router.register(r'groups', views.GroupViewSet) +router.register(r'posts', views.PostViewSet) +router.register(r'categories', views.CategoryViewSet) urlpatterns = [ - path('', include('blogging.urls')), + path('', include(router.urls)), + path('blogging/', include('blogging.urls')), path('polling/', include('polling.urls')), path('admin/', admin.site.urls), path('login/', LoginView.as_view(template_name='login.html'), name="login"), path('logout/', LogoutView.as_view(next_page='/'), name="logout"), + path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] From a6e2ac0dcdf751e2f349a7aa3bf48d1781d66d32 Mon Sep 17 00:00:00 2001 From: Colleen Kaku Date: Tue, 9 Mar 2021 16:23:00 -0800 Subject: [PATCH 3/4] Added RSS Feed View for viewing posts. --- mysite/feeds.py | 22 ++++++++++++++++++++++ mysite/urls.py | 4 +++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 mysite/feeds.py diff --git a/mysite/feeds.py b/mysite/feeds.py new file mode 100644 index 0000000..5faaac1 --- /dev/null +++ b/mysite/feeds.py @@ -0,0 +1,22 @@ +from django.contrib.syndication.views import Feed +from django.urls import reverse +from blogging.models import Post + + +class LatestEntriesFeed(Feed): + title = "Blog entries" + link = "/posts/" + description = "Most recent blog entries" + + def items(self): + published = Post.objects.exclude(published_date__exact=None) + return published.order_by('-published_date')[:5] + + def item_title(self, item): + return item.title + + def item_description(self, item): + return item.text + + def item_link(self, item): + return reverse('blog_detail', args=[item.pk]) \ No newline at end of file diff --git a/mysite/urls.py b/mysite/urls.py index fcb5f88..4645143 100644 --- a/mysite/urls.py +++ b/mysite/urls.py @@ -18,6 +18,7 @@ from django.contrib.auth.views import LoginView, LogoutView from rest_framework import routers from mysite.quickstart import views +from mysite.feeds import LatestEntriesFeed router = routers.DefaultRouter() @@ -34,5 +35,6 @@ path('admin/', admin.site.urls), path('login/', LoginView.as_view(template_name='login.html'), name="login"), path('logout/', LogoutView.as_view(next_page='/'), name="logout"), - path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) + path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), + path('latest/feed/', LatestEntriesFeed()), ] From ab6e3104babd029bb347fe11af74e2028542df5c Mon Sep 17 00:00:00 2001 From: Colleen Kaku Date: Thu, 11 Mar 2021 14:15:03 -0800 Subject: [PATCH 4/4] Production settings added. --- mysite/production.py | 14 ++++++++++++++ requirements.txt | 8 +++++++- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 mysite/production.py diff --git a/mysite/production.py b/mysite/production.py new file mode 100644 index 0000000..025698f --- /dev/null +++ b/mysite/production.py @@ -0,0 +1,14 @@ +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/requirements.txt b/requirements.txt index 81580ab..4cfe887 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,8 @@ -Django==2.1.1 +asgiref==3.3.1 +dj-database-url==0.5.0 +Django==3.1.7 +djangorestframework==3.12.2 +psycopg2==2.7.7 +psycopg2-binary==2.8.6 pytz==2019.3 +sqlparse==0.4.1