From a5f0d97d54b6e03eb84eea06c46def1344d2ad18 Mon Sep 17 00:00:00 2001 From: Sam Collins Date: Thu, 16 Feb 2017 00:04:44 +0000 Subject: [PATCH] First Start of blog system --- config/settings/common.py | 1 + config/settings/stage.py | 2 +- config/urls.py | 10 ++- .../migrations/0003_auto_20170215_2146.py | 23 +++++++ mhackspace/blog/__init__.py | 0 mhackspace/blog/admin.py | 19 ++++++ mhackspace/blog/apps.py | 5 ++ mhackspace/blog/feeds.py | 47 +++++++++++++ mhackspace/blog/migrations/0001_initial.py | 44 ++++++++++++ .../migrations/0002_auto_20170215_2323.py | 68 +++++++++++++++++++ .../migrations/0003_auto_20170215_2348.py | 24 +++++++ mhackspace/blog/migrations/__init__.py | 0 mhackspace/blog/models.py | 46 +++++++++++++ mhackspace/blog/tests.py | 3 + mhackspace/blog/views.py | 3 + .../migrations/0002_auto_20170215_2146.py | 19 ++++++ mhackspace/feeds/models.py | 3 + .../users/migrations/0002_user_public.py | 20 ++++++ mhackspace/users/models.py | 1 + 19 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 mhackspace/base/migrations/0003_auto_20170215_2146.py create mode 100644 mhackspace/blog/__init__.py create mode 100644 mhackspace/blog/admin.py create mode 100644 mhackspace/blog/apps.py create mode 100644 mhackspace/blog/feeds.py create mode 100644 mhackspace/blog/migrations/0001_initial.py create mode 100644 mhackspace/blog/migrations/0002_auto_20170215_2323.py create mode 100644 mhackspace/blog/migrations/0003_auto_20170215_2348.py create mode 100644 mhackspace/blog/migrations/__init__.py create mode 100644 mhackspace/blog/models.py create mode 100644 mhackspace/blog/tests.py create mode 100644 mhackspace/blog/views.py create mode 100644 mhackspace/feeds/migrations/0002_auto_20170215_2146.py create mode 100644 mhackspace/users/migrations/0002_user_public.py diff --git a/config/settings/common.py b/config/settings/common.py index 618110b..924821d 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -53,6 +53,7 @@ LOCAL_APPS = ( 'mhackspace.feeds', 'mhackspace.contact', 'mhackspace.members', + 'mhackspace.blog', ) # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps diff --git a/config/settings/stage.py b/config/settings/stage.py index 64e5f1d..9ba0561 100644 --- a/config/settings/stage.py +++ b/config/settings/stage.py @@ -211,7 +211,7 @@ LOGGING = { } # Custom Admin URL, use {% url 'admin:index' %} -ADMIN_URL = env('DJANGO_ADMIN_URL', default='admin') +ADMIN_URL = env('DJANGO_ADMIN_URL', default='admin/') # Your production stuff: Below this line define 3rd party library settings # ------------------------------------------------------------------------------ diff --git a/config/urls.py b/config/urls.py index 3eafd7c..2554f89 100644 --- a/config/urls.py +++ b/config/urls.py @@ -7,11 +7,13 @@ from django.conf.urls.static import static from django.contrib import admin from django.views.generic import TemplateView from django.views import defaults as default_views +from django.contrib.auth import views as auth_views + from mhackspace.contact.views import contact from mhackspace.members.views import MemberListView from mhackspace.subscriptions import views as subscription from mhackspace.base.feeds import LatestEntriesFeed -from django.contrib.auth import views as auth_views +from mhackspace.blog.feeds import BlogFeed, BlogCategoryFeed urlpatterns = [ url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name='home'), @@ -20,6 +22,12 @@ urlpatterns = [ url(r'^mailing-list/$', TemplateView.as_view(template_name='pages/mailing-list.html'), name='group'), url(r'^contact/$', contact, name='contact'), + url(r'^blog/$', contact, name='contact'), + url(r'^blog/rss/$', BlogFeed()), + url(r'^blog/(?P[0-9A-Za-z_\-]+)/$', BlogCategoryFeed(), name='blog-item'), + url(r'^blog/category/(?P[0-9A-Za-z_\-]+)/$', BlogCategoryFeed(), name='blog-category'), + url(r'^blog/category/(?P[0-9A-Za-z_\-]+)/rss/$', BlogCategoryFeed(), name='blog-category_feed'), + # need to be logged in for these urls url(r'^members/$', MemberListView.as_view(), name='members'), diff --git a/mhackspace/base/migrations/0003_auto_20170215_2146.py b/mhackspace/base/migrations/0003_auto_20170215_2146.py new file mode 100644 index 0000000..88e0fc3 --- /dev/null +++ b/mhackspace/base/migrations/0003_auto_20170215_2146.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-15 21:46 +from __future__ import unicode_literals + +from django.db import migrations +import stdimage.models +import stdimage.utils +import stdimage.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('base', '0002_auto_20170214_1911'), + ] + + operations = [ + migrations.AlterField( + model_name='bannerimages', + name='scaled_image', + field=stdimage.models.StdImageField(blank=True, null=True, upload_to=stdimage.utils.UploadToAutoSlugClassNameDir('title'), validators=[stdimage.validators.MinSizeValidator(1200, 300)]), + ), + ] diff --git a/mhackspace/blog/__init__.py b/mhackspace/blog/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mhackspace/blog/admin.py b/mhackspace/blog/admin.py new file mode 100644 index 0000000..9b5d7b9 --- /dev/null +++ b/mhackspace/blog/admin.py @@ -0,0 +1,19 @@ +from django.contrib import admin +from django.contrib.admin import ModelAdmin + +from mhackspace.blog.models import Post, Category + +@admin.register(Post) +class PostAdmin(ModelAdmin): + date_hierarchy = 'published_date' + list_display = ('title', 'slug', 'author','active', 'members_only', 'published_date', 'updated_date') + list_filter = ('author', 'categories', 'members_only') + search_fields = ('title', 'author__name', 'author__id', 'published_date', 'updated_date') + readonly_fields = ('published_date',) + filter_horizontal = ('categories',) + prepopulated_fields = {"slug": ("title",)} + +@admin.register(Category) +class CategoryAdmin(ModelAdmin): + list_display = ('name',) + prepopulated_fields = {"slug": ("name",)} diff --git a/mhackspace/blog/apps.py b/mhackspace/blog/apps.py new file mode 100644 index 0000000..7930587 --- /dev/null +++ b/mhackspace/blog/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class BlogConfig(AppConfig): + name = 'blog' diff --git a/mhackspace/blog/feeds.py b/mhackspace/blog/feeds.py new file mode 100644 index 0000000..77e2fa6 --- /dev/null +++ b/mhackspace/blog/feeds.py @@ -0,0 +1,47 @@ +from django.contrib.syndication.views import Feed +from django.urls import reverse + +from mhackspace.blog.models import Category, Post + +class BlogFeed(Feed): + title = "Maidstone Hackspace Blog" + link = "/blog/" + description = "The latest blog posts and news from the Maidstone Hackspace site" + + def items(self, category): + return Post.objects.select_related('author').filter(active=True, members_only=False)[:20] + + def item_title(self, item): + return item.title + + def item_description(self, item): + return item.description + + def item_author_name(self, item): + return item.author.name + + def item_author_email(self, item): + if item.author.public: + return item.author.email + + def item_categories(self, item): + return item.categories.all() + + def item_pubdate(self, item): + return item.published_date + + def item_updateddate(self, item): + return item.updated_date + +class BlogCategoryFeed(BlogFeed): + def get_object(self, request, category): + return Category.objects.filter(slug=category).first() + + def items(self, category): + return Post.objects.select_related('author').filter(active=True, members_only=False, categories=category)[:20] + + def title(self, category): + return "Maidstone Hackspace Blog: %s" % category.name + + def description(self, category): + return category.description diff --git a/mhackspace/blog/migrations/0001_initial.py b/mhackspace/blog/migrations/0001_initial.py new file mode 100644 index 0000000..ddf2980 --- /dev/null +++ b/mhackspace/blog/migrations/0001_initial.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-15 21:46 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import stdimage.models +import stdimage.utils + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ], + ), + migrations.CreateModel( + name='Post', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=30)), + ('image', stdimage.models.StdImageField(blank=True, null=True, upload_to=stdimage.utils.UploadToAutoSlugClassNameDir('title'))), + ('description', models.TextField()), + ('date', models.DateTimeField(default=django.utils.timezone.now)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('categories', models.ManyToManyField(to='blog.Category')), + ], + options={ + 'ordering': ('date',), + }, + ), + ] diff --git a/mhackspace/blog/migrations/0002_auto_20170215_2323.py b/mhackspace/blog/migrations/0002_auto_20170215_2323.py new file mode 100644 index 0000000..bf8b7c3 --- /dev/null +++ b/mhackspace/blog/migrations/0002_auto_20170215_2323.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-15 23:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='post', + options={'ordering': ('updated_date',)}, + ), + migrations.RenameField( + model_name='post', + old_name='date', + new_name='published_date', + ), + migrations.AddField( + model_name='category', + name='description', + field=models.TextField(default='Maidstone Hackspace Blog'), + preserve_default=False, + ), + migrations.AddField( + model_name='category', + name='members_only', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='category', + name='slug', + field=models.SlugField(default='url', max_length=100), + preserve_default=False, + ), + migrations.AddField( + model_name='post', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='post', + name='slug', + field=models.SlugField(default='url', max_length=100, unique=True), + preserve_default=False, + ), + migrations.AddField( + model_name='post', + name='updated_date', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AlterField( + model_name='category', + name='name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='post', + name='title', + field=models.CharField(max_length=100, unique=True), + ), + ] diff --git a/mhackspace/blog/migrations/0003_auto_20170215_2348.py b/mhackspace/blog/migrations/0003_auto_20170215_2348.py new file mode 100644 index 0000000..e855abd --- /dev/null +++ b/mhackspace/blog/migrations/0003_auto_20170215_2348.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-15 23:48 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('blog', '0002_auto_20170215_2323'), + ] + + operations = [ + migrations.RemoveField( + model_name='category', + name='members_only', + ), + migrations.AddField( + model_name='post', + name='members_only', + field=models.BooleanField(default=False), + ), + ] diff --git a/mhackspace/blog/migrations/__init__.py b/mhackspace/blog/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mhackspace/blog/models.py b/mhackspace/blog/models.py new file mode 100644 index 0000000..dccad7f --- /dev/null +++ b/mhackspace/blog/models.py @@ -0,0 +1,46 @@ +from django.db import models +from django.utils import timezone +from django.urls import reverse + +from mhackspace.users.models import User +from stdimage.models import StdImageField +from stdimage.utils import UploadToAutoSlugClassNameDir + +class Category(models.Model): + name = models.CharField(max_length=100) + slug = models.SlugField(max_length=100) + description = models.TextField() + + def __str__(self): + return self.name + +class Post(models.Model): + title = models.CharField(max_length=100, unique=True) + slug = models.SlugField(max_length=100, unique=True) + categories = models.ManyToManyField(Category) + author = models.ForeignKey(User) + image = StdImageField( + upload_to=UploadToAutoSlugClassNameDir(populate_from='title'), + blank=True, + null=True, + variations={ + 'home': { + "width": 530, + "height": 220, + "crop": True}}) + + description = models.TextField() + published_date = models.DateTimeField(default=timezone.now) + updated_date = models.DateTimeField(default=timezone.now) + active = models.BooleanField(default=True) + members_only = models.BooleanField(default=False) + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse('blog-item', kwargs={'slug': self.slug}) + + class Meta: + ordering = ('updated_date',) + diff --git a/mhackspace/blog/tests.py b/mhackspace/blog/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/mhackspace/blog/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/mhackspace/blog/views.py b/mhackspace/blog/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/mhackspace/blog/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/mhackspace/feeds/migrations/0002_auto_20170215_2146.py b/mhackspace/feeds/migrations/0002_auto_20170215_2146.py new file mode 100644 index 0000000..67e31ab --- /dev/null +++ b/mhackspace/feeds/migrations/0002_auto_20170215_2146.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-15 21:46 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('feeds', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='article', + options={'ordering': ('pk',)}, + ), + ] diff --git a/mhackspace/feeds/models.py b/mhackspace/feeds/models.py index c52f782..680329b 100644 --- a/mhackspace/feeds/models.py +++ b/mhackspace/feeds/models.py @@ -53,3 +53,6 @@ class Article(models.Model): def __str__(self): return self.title + + class Meta: + ordering = ('pk',) diff --git a/mhackspace/users/migrations/0002_user_public.py b/mhackspace/users/migrations/0002_user_public.py new file mode 100644 index 0000000..e458f79 --- /dev/null +++ b/mhackspace/users/migrations/0002_user_public.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-15 23:23 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='public', + field=models.BooleanField(default=False, help_text='If the users email is public on post feeds'), + ), + ] diff --git a/mhackspace/users/models.py b/mhackspace/users/models.py index ccf0afc..8b4d4de 100644 --- a/mhackspace/users/models.py +++ b/mhackspace/users/models.py @@ -11,6 +11,7 @@ from stdimage.models import StdImageField class User(AbstractUser): name = models.CharField(_('Name of User'), blank=True, max_length=255) + public = models.BooleanField(default=False, help_text='If the users email is public on post feeds') image = StdImageField( upload_to='avatars/', blank=True,