diff --git a/portal/settings.py b/portal/settings.py index a45e5ac..a01bec9 100644 --- a/portal/settings.py +++ b/portal/settings.py @@ -1,34 +1,11 @@ -""" -Django settings for portal project. - -For more information on this file, see -https://docs.djangoproject.com/en/1.6/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.6/ref/settings/ -""" - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os -BASE_DIR = os.path.dirname(os.path.dirname(__file__)) - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ['REVUO_KEY'] -# SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.environ.get('REVUO_DEBUG', False) TEMPLATE_DEBUG = True -ALLOWED_HOSTS = [] - - -# Application definition - INSTALLED_APPS = ( 'revuo', 'django_summernote', @@ -53,9 +30,6 @@ WSGI_APPLICATION = 'portal.wsgi.application' - - - # Internationalization # https://docs.djangoproject.com/en/1.6/topics/i18n/ @@ -73,7 +47,6 @@ ALLOWED_HOSTS = ['*'] -import os BASE_DIR = os.path.dirname(os.path.abspath(__file__)) STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.AppDirectoriesFinder', @@ -90,9 +63,7 @@ LOGIN_URL = '/login/' - # Database -# https://docs.djangoproject.com/en/1.6/ref/settings/#databases if DEBUG: debug_db = os.path.join(BASE_DIR, 'db.sqlite3') diff --git a/revuo/admin.py b/revuo/admin.py index 3a479cf..f0cab5b 100644 --- a/revuo/admin.py +++ b/revuo/admin.py @@ -1,5 +1,6 @@ from django.contrib import admin -from revuo.models import Author, NewsItem, BlogItem, Publication +from revuo.models.author import Author +from revuo.models.publications import NewsItem, BlogItem, Publication admin.site.register(Author) admin.site.register(NewsItem) diff --git a/revuo/forms.py b/revuo/forms.py index 4588b45..57d5807 100644 --- a/revuo/forms.py +++ b/revuo/forms.py @@ -1,6 +1,7 @@ from django import forms -from django_summernote.widgets import SummernoteWidget, SummernoteInplaceWidget -from revuo.models import NewsItem, BlogItem, Author, Publication +from django_summernote.widgets import SummernoteWidget +from revuo.models.author import Author +from revuo.models.publications import NewsItem, BlogItem class FormNewsItem(forms.ModelForm): diff --git a/revuo/migrations/0001_initial.py b/revuo/migrations/0001_initial.py index 63e3aa4..4d00a98 100644 --- a/revuo/migrations/0001_initial.py +++ b/revuo/migrations/0001_initial.py @@ -76,7 +76,7 @@ class Migration(migrations.Migration): ('authorized', models.BooleanField(default=False)), ('title', models.TextField(max_length=140)), ('description', models.TextField(max_length=280)), - ('attachment', models.FileField(upload_to=revuo.models.publication_destination)), + ('attachment', models.FileField(upload_to=revuo.models.publications.publication_destination)), ('author', models.ForeignKey(to='revuo.Author')), ], options={ diff --git a/revuo/migrations/0002_auto_20141116_0103.py b/revuo/migrations/0002_auto_20141116_0103.py new file mode 100644 index 0000000..603caea --- /dev/null +++ b/revuo/migrations/0002_auto_20141116_0103.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('revuo', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='admin', + name='user', + ), + migrations.DeleteModel( + name='Admin', + ), + ] diff --git a/revuo/models/__init__.py b/revuo/models/__init__.py new file mode 100644 index 0000000..0aa1cbc --- /dev/null +++ b/revuo/models/__init__.py @@ -0,0 +1,3 @@ +import publications +from publications import BlogItem, NewsItem, Publication +from author import Author \ No newline at end of file diff --git a/revuo/models/author.py b/revuo/models/author.py new file mode 100644 index 0000000..218c205 --- /dev/null +++ b/revuo/models/author.py @@ -0,0 +1,13 @@ +from django.db import models +from django.contrib.auth.models import User + +class Author(models.Model): + user = models.OneToOneField(User) + editor = models.BooleanField(default=False) + about = models.TextField(max_length=1024) + + def __unicode__(self): + return ' '.join([self.user.first_name, self.user.last_name]) + + def get_url(self): + return '/staff/{}'.format(self.id) diff --git a/revuo/models.py b/revuo/models/publications.py similarity index 74% rename from revuo/models.py rename to revuo/models/publications.py index 05f9bde..d757caa 100644 --- a/revuo/models.py +++ b/revuo/models/publications.py @@ -1,29 +1,4 @@ from django.db import models -from django.contrib.auth.models import User -import datetime - - -class Author(models.Model): - user = models.OneToOneField(User) - editor = models.BooleanField(default=False) - about = models.TextField(max_length=1024) - - - def __unicode__(self): - return ' '.join([self.user.first_name, self.user.last_name]) - - - def get_url(self): - return '/staff/{}'.format(self.id) - - -class Admin(models.Model): - user = models.OneToOneField(User) - - - def __unicode__(self): - return ' '.join([self.user.first_name, self.user.last_name]) - class NewsItem(models.Model): created_at = models.DateTimeField(auto_now_add=True) @@ -34,15 +9,12 @@ class NewsItem(models.Model): description = models.TextField(max_length=280) text = models.TextField() - def authorize(self): self.authorized = True - def __unicode__(self): return self.title - def get_url(self): return '/N/{}'.format(self.id) @@ -56,19 +28,15 @@ class BlogItem(models.Model): description = models.TextField(max_length=280) text = models.TextField() - def authorize(self): self.authorized = True - def __unicode__(self): return self.title - def get_url(self): return '/B/{}'.format(self.id) - def publication_destination(instance, filename): return '_'.join([str(instance.author.id),filename]) @@ -82,14 +50,11 @@ class Publication(models.Model): description = models.TextField(max_length=280) attachment = models.FileField(upload_to=publication_destination) - def authorize(self): self.authorized = True - def get_url(self): return '/P/{}'.format(self.id) - def __unicode__(self): - return self.title + return self.title \ No newline at end of file diff --git a/revuo/templates/revuo/base.html b/revuo/templates/revuo/base.html index 2d4abdf..920df9b 100644 --- a/revuo/templates/revuo/base.html +++ b/revuo/templates/revuo/base.html @@ -1,9 +1,8 @@ -{% load staticfiles %} - +{% load staticfiles %} - + {% block title %}{% endblock %} @@ -45,6 +44,12 @@
  • Pending Items
  • {% endif %} + {% if user.is_superuser %} +
  • + +
  • Settings
  • +
  • Preferences
  • + {% endif %}
  • Logout
  • {% else %} diff --git a/revuo/tests.py b/revuo/tests.py index cf470e0..399a2ed 100644 --- a/revuo/tests.py +++ b/revuo/tests.py @@ -1,7 +1,8 @@ from django.test import LiveServerTestCase, TestCase from selenium import webdriver from model_mommy import mommy -from revuo.models import Author, Admin, NewsItem, BlogItem, Publication +from revuo.models.author import Author +from revuo.models.publications import NewsItem, BlogItem, Publication from django.contrib.auth.models import User from django.contrib.auth import authenticate from time import sleep @@ -303,19 +304,6 @@ def test_author_model(self): ' '.join([author.user.first_name, author.user.last_name]) ) - - def test_admin_model(self): - """ - admin model test - """ - admin = mommy.make(Admin) - self.assertTrue(isinstance(admin, Admin)) - self.assertEqual( - admin.__unicode__(), - ' '.join([admin.user.first_name, admin.user.last_name]) - ) - - def test_items_model(self): """ item model test diff --git a/revuo/urls.py b/revuo/urls.py index 6be6a09..9c6374e 100644 --- a/revuo/urls.py +++ b/revuo/urls.py @@ -1,8 +1,10 @@ from django.conf.urls import patterns, include, url -from revuo.views import Home, Staff, StaffView -from revuo.views import ItemList, ItemView, NewItem -from revuo.views import EditProfile, Publisher, PublishItem, TrashItem +from revuo.views.home import Home +from revuo.views.create import NewItem, EditProfile +from revuo.views.list import ItemList, StaffList +from revuo.views.view import ItemView, StaffView +from revuo.views.moderation import Publisher, PublishItem, TrashItem urlpatterns = patterns('', url(r'^$', Home.as_view(), name='home'), @@ -11,7 +13,7 @@ url(r'^publications$', ItemList.as_view(category='publications'), name='publications'), url(r'^(?P[NBP])/(?P\d+)$', ItemView.as_view()), - url(r'^staff$', Staff.as_view(), name='staff'), + url(r'^staff$', StaffList.as_view(), name='staff'), url(r'^staff/(?P\d+)$', StaffView.as_view()), url(r'^restricted/N/add$', NewItem.as_view(category='N'), name='add_news'), diff --git a/revuo/views.py b/revuo/views.py deleted file mode 100644 index 1b87ae8..0000000 --- a/revuo/views.py +++ /dev/null @@ -1,171 +0,0 @@ -from django.shortcuts import render, redirect, get_object_or_404 -from django.utils.decorators import method_decorator -from django.template import RequestContext -from django.http import HttpResponse, HttpResponseForbidden -from django.contrib.auth.decorators import login_required, user_passes_test -from django.views.generic.base import View -from revuo.models import NewsItem, BlogItem, Author, Publication -from revuo.forms import FormNewsItem, FormBlogItem, FormEditProfile, FormPublication -import json - - -class Home(View): - template_name = 'revuo/home.html' - - def get(self, request): - return render(request, self.template_name, {}) - - -class ItemList(View): - categories = {'news': NewsItem, 'blog': BlogItem, 'publications': Publication} - category = None - - def get(self, request): - Item = self.categories[self.category] - item_list = Item.objects.filter(authorized=True) - ordered = item_list.order_by('-created_at')[:10] - template = 'revuo/{}.html'.format(self.category) - return render(request, template, {'items_list':ordered}) - - -class ItemView(View): - categories = {'N': NewsItem, 'B': BlogItem, 'P': Publication} - - def get(self, request, category, item_id): - Item = self.categories[category] - if request.user.is_authenticated(): - item = get_object_or_404(Item, id=item_id) - else: - item = get_object_or_404(Item, id=item_id, authorized=True) - template = 'revuo/{}_item.html'.format(category) - return render(request, template, {'item':item, 'category':category}) - - -class Staff(View): - template_name = 'revuo/staff.html' - - def get(self, request): - authors_list = Author.objects.all() - return render(request, self.template_name, {'authors_list':authors_list}) - - -class StaffView(View): - template_name = 'revuo/staff_view.html' - - def get(self, request, staff_id): - author = get_object_or_404(Author, id=staff_id) - return render(request, self.template_name, {'author':author}) - - -# =========================== -# logged actions -# =========================== - - -class NewItem(View): - template_name = 'revuo/new_item.html' - categories = {'N': FormNewsItem, 'B': FormBlogItem, 'P': FormPublication} - category = None - - @method_decorator(login_required) - def get(self, request): - FormItem = self.categories[self.category] - form = FormItem() - return render(request, self.template_name, {'form': form}, - context_instance=RequestContext(request)) - - - @method_decorator(login_required) - def post(self, request): - FormItem = self.categories[self.category] - form = FormItem(request.POST, request.FILES) - if form.is_valid(): - author = Author.objects.get(user=request.user) - if self.category == 'P': # need to find out why it didn't work for ModelForm - item = Publication(author=author,attachment=request.FILES['attachment']) - item.title = form.cleaned_data['title'] - item.description = form.cleaned_data['description'] - else: - item = form.instance - item.author = author - item.authorized = False - item.save() - return redirect(item.get_url()) - return render(request, self.template_name, {'form': form}, - context_instance=RequestContext(request)) - - -def editor_test(user): - return Author.objects.get(user=user).editor - - -class Publisher(View): - template_name = 'revuo/publisher.html' - - """ - gets a list of items pending authorization - """ - @method_decorator(login_required) - @method_decorator(user_passes_test(editor_test)) - def get(self, request): - news = NewsItem.objects.filter(authorized=False) - posts = BlogItem.objects.filter(authorized=False) - pubs = Publication.objects.filter(authorized=False) - items_list = list(news) + list(posts) + list(pubs) - return render(request, self.template_name, {'items_list':items_list}, - context_instance=RequestContext(request)) - - -class PublishItem(View): - categories = {'N': NewsItem, 'B': BlogItem, 'P': Publication} - - @method_decorator(login_required) - @method_decorator(user_passes_test(editor_test)) - def get(self, request, category, item_id): - if request.is_ajax(): - Item = self.categories[category] - item = get_object_or_404(Item, id=int(item_id)) - item.authorize() - item.save() - result = {'msg': 'Item Published'} - else: - return HttpResponseForbidden("FORBIDDEN") - return HttpResponse(json.dumps(result), content_type='application/json') - - -class TrashItem(View): - categories = {'N': NewsItem, 'B': BlogItem, 'P': Publication} - - @method_decorator(login_required) - @method_decorator(user_passes_test(editor_test)) - def get(self, request, category, item_id): - if request.is_ajax(): - Item = self.categories[category] - item = get_object_or_404(Item, id=int(item_id)) - item.delete() - result = {'msg': 'Item Deleted'} - else: - return HttpResponseForbidden("FORBIDDEN") - return HttpResponse(json.dumps(result), content_type='application/json') - - -class EditProfile(View): - template_name = 'revuo/edit_item.html' - - @method_decorator(login_required) - def get(self, request): - author_info = Author.objects.get(user=request.user) - form = FormEditProfile(instance=author_info) - return render(request, self.template_name, {'form': form}, - context_instance=RequestContext(request)) - - - @method_decorator(login_required) - def post(self, request): - author_info = Author.objects.get(user=request.user) - form = FormEditProfile(request.POST, request.FILES, instance=author_info) - if form.is_valid(): - form.instance.save() - return redirect('/') - return render(request, self.template_name, {'form': form}, - context_instance=RequestContext(request)) diff --git a/revuo/views/__init__.py b/revuo/views/__init__.py new file mode 100644 index 0000000..db000e1 --- /dev/null +++ b/revuo/views/__init__.py @@ -0,0 +1 @@ +__author__ = 'gabriel' diff --git a/revuo/views/create.py b/revuo/views/create.py new file mode 100644 index 0000000..6e679dd --- /dev/null +++ b/revuo/views/create.py @@ -0,0 +1,63 @@ +from django.shortcuts import render, redirect +from django.template import RequestContext +from django.contrib.auth.decorators import login_required, user_passes_test +from django.utils.decorators import method_decorator +from django.views.generic.base import View + +from revuo.forms import FormNewsItem, FormBlogItem, FormPublication, FormEditProfile +from revuo.models.author import Author +from revuo.models.publications import Publication + +class NewItem(View): + template_name = 'revuo/new_item.html' + categories = {'N': FormNewsItem, 'B': FormBlogItem, 'P': FormPublication} + category = None + + @method_decorator(login_required) + def get(self, request): + FormItem = self.categories[self.category] + form = FormItem() + return render(request, self.template_name, {'form': form}, + context_instance=RequestContext(request)) + + + @method_decorator(login_required) + def post(self, request): + FormItem = self.categories[self.category] + form = FormItem(request.POST, request.FILES) + if form.is_valid(): + author = Author.objects.get(user=request.user) + if self.category == 'P': # need to find out why it didn't work for ModelForm + item = Publication(author=author,attachment=request.FILES['attachment']) + item.title = form.cleaned_data['title'] + item.description = form.cleaned_data['description'] + else: + item = form.instance + item.author = author + item.authorized = False + item.save() + return redirect(item.get_url()) + return render(request, self.template_name, {'form': form}, + context_instance=RequestContext(request)) + + +class EditProfile(View): + template_name = 'revuo/edit_item.html' + + @method_decorator(login_required) + def get(self, request): + author_info = Author.objects.get(user=request.user) + form = FormEditProfile(instance=author_info) + return render(request, self.template_name, {'form': form}, + context_instance=RequestContext(request)) + + + @method_decorator(login_required) + def post(self, request): + author_info = Author.objects.get(user=request.user) + form = FormEditProfile(request.POST, request.FILES, instance=author_info) + if form.is_valid(): + form.instance.save() + return redirect('/') + return render(request, self.template_name, {'form': form}, + context_instance=RequestContext(request)) diff --git a/revuo/views/home.py b/revuo/views/home.py new file mode 100644 index 0000000..b51c619 --- /dev/null +++ b/revuo/views/home.py @@ -0,0 +1,8 @@ +from django.views.generic.base import View +from django.shortcuts import render + +class Home(View): + template_name = 'revuo/home.html' + + def get(self, request): + return render(request, self.template_name, {}) diff --git a/revuo/views/list.py b/revuo/views/list.py new file mode 100644 index 0000000..2bbdb32 --- /dev/null +++ b/revuo/views/list.py @@ -0,0 +1,24 @@ +from django.shortcuts import render +from django.views.generic.base import View + +from revuo.models.publications import NewsItem, BlogItem, Publication +from revuo.models.author import Author + +class ItemList(View): + categories = {'news': NewsItem, 'blog': BlogItem, 'publications': Publication} + category = None + + def get(self, request): + Item = self.categories[self.category] + item_list = Item.objects.filter(authorized=True) + ordered = item_list.order_by('-created_at')[:10] + template = 'revuo/{}.html'.format(self.category) + return render(request, template, {'items_list':ordered}) + + +class StaffList(View): + template_name = 'revuo/staff.html' + + def get(self, request): + authors_list = Author.objects.all() + return render(request, self.template_name, {'authors_list':authors_list}) diff --git a/revuo/views/moderation.py b/revuo/views/moderation.py new file mode 100644 index 0000000..6f2e8ee --- /dev/null +++ b/revuo/views/moderation.py @@ -0,0 +1,67 @@ +from django.shortcuts import render, get_object_or_404 +from django.utils.decorators import method_decorator +from django.template import RequestContext +from django.http import HttpResponse, HttpResponseForbidden +from django.contrib.auth.decorators import login_required, user_passes_test +from django.views.generic.base import View + +from revuo.models.author import Author +from revuo.models.publications import NewsItem, BlogItem, Publication + +import json + +def editor_test(user): + return Author.objects.get(user=user).editor + + +class Publisher(View): + template_name = 'revuo/publisher.html' + + """ + gets a list of items pending authorization + """ + @method_decorator(login_required) + @method_decorator(user_passes_test(editor_test)) + def get(self, request): + news = NewsItem.objects.filter(authorized=False) + posts = BlogItem.objects.filter(authorized=False) + pubs = Publication.objects.filter(authorized=False) + items_list = list(news) + list(posts) + list(pubs) + return render(request, self.template_name, {'items_list':items_list}, + context_instance=RequestContext(request)) + + +class PublishItem(View): + categories = {'N': NewsItem, 'B': BlogItem, 'P': Publication} + + @method_decorator(login_required) + @method_decorator(user_passes_test(editor_test)) + def get(self, request, category, item_id): + if request.is_ajax(): + Item = self.categories[category] + item = get_object_or_404(Item, id=int(item_id)) + item.authorize() + item.save() + result = {'msg': 'Item Published'} + else: + return HttpResponseForbidden("FORBIDDEN") + return HttpResponse(json.dumps(result), content_type='application/json') + + +class TrashItem(View): + categories = {'N': NewsItem, 'B': BlogItem, 'P': Publication} + + @method_decorator(login_required) + @method_decorator(user_passes_test(editor_test)) + def get(self, request, category, item_id): + if request.is_ajax(): + Item = self.categories[category] + item = get_object_or_404(Item, id=int(item_id)) + item.delete() + result = {'msg': 'Item Deleted'} + else: + return HttpResponseForbidden("FORBIDDEN") + return HttpResponse(json.dumps(result), content_type='application/json') + + + diff --git a/revuo/views/view.py b/revuo/views/view.py new file mode 100644 index 0000000..fe81373 --- /dev/null +++ b/revuo/views/view.py @@ -0,0 +1,26 @@ +from django.shortcuts import render, get_object_or_404 +from django.views.generic.base import View + +from revuo.models.publications import NewsItem, BlogItem, Publication +from revuo.models.author import Author + +class ItemView(View): + categories = {'N': NewsItem, 'B': BlogItem, 'P': Publication} + + def get(self, request, category, item_id): + Item = self.categories[category] + if request.user.is_authenticated(): + item = get_object_or_404(Item, id=item_id) + else: + item = get_object_or_404(Item, id=item_id, authorized=True) + template = 'revuo/{}_item.html'.format(category) + return render(request, template, {'item':item, 'category':category}) + + +class StaffView(View): + template_name = 'revuo/staff_view.html' + + def get(self, request, staff_id): + author = get_object_or_404(Author, id=staff_id) + return render(request, self.template_name, {'author':author}) +