Skip to content

Commit

Permalink
Add review views for all content types.
Browse files Browse the repository at this point in the history
Review view provides additional information when entering content
review, displaying explicit message e.g. if the content is already
approved, or the user doesn't have the rights to approve it.

Fixes #13.
Fixes #12.
  • Loading branch information
przem8k committed May 3, 2015
1 parent c7dd738 commit 8ad6f83
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 66 deletions.
21 changes: 12 additions & 9 deletions articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,23 @@ def save(self, *args, **kwargs):
self.cover_credits_html = ""
super().save(*args, **kwargs)

def get_url_params(self):
return {
'slug': self.slug,
}

@models.permalink
def get_absolute_url(self):
return('article', (), {
'slug': self.slug,
})
return('article', (), self.get_url_params())

@models.permalink
def get_edit_url(self):
return('edit_article', (), {
'slug': self.slug,
})
return('edit_article', (), self.get_url_params())

@models.permalink
def get_review_url(self):
return ('review_article', (), self.get_url_params())

@models.permalink
def get_approve_url(self):
return ('approve_article', (), {
'slug': self.slug
})
return ('approve_article', (), self.get_url_params())
2 changes: 2 additions & 0 deletions articles/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
url(r'^(?P<slug>[-\w]+)/', include([
url(r'^$', views.ArticleView.as_view(), name='article'),
url(r'^edytuj/$', views.EditArticle.as_view(), name='edit_article'),
url(r'^korekta/$', views.ReviewArticle.as_view(),
name='review_article'),
url(r'^zatwierdz/$', views.ApproveArticle.as_view(),
name='approve_article'),
])),
Expand Down
20 changes: 13 additions & 7 deletions articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from content.mixins import ContentItemEditMixin, ContentItemAddMixin
from content.mixins import ContentItemViewMixin
from content.mixins import ContentItemApproveMixin
from content.views import ReviewContentView


class IndexView(TemplateView):
Expand Down Expand Up @@ -47,18 +48,23 @@ def get_success_url(self):
return self.object.get_absolute_url()


class EditArticle(ContentItemEditMixin, UpdateView):
class GetArticleMixin(object):
def get_object(self):
return get_object_or_404(Article, slug=self.kwargs['slug'])


class EditArticle(GetArticleMixin, ContentItemEditMixin, UpdateView):
model = Article
form_class = ArticleForm
template_name = "articles/add_edit_article.html"

def get_object(self):
return get_object_or_404(Article, slug=self.kwargs['slug'])

def get_success_url(self):
return self.object.get_absolute_url()


class ApproveArticle(ContentItemApproveMixin, RedirectView):
def get_object(self):
return get_object_or_404(Article, slug=self.kwargs['slug'])
class ReviewArticle(GetArticleMixin, ReviewContentView):
pass


class ApproveArticle(GetArticleMixin, ContentItemApproveMixin, RedirectView):
pass
29 changes: 13 additions & 16 deletions blog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,26 @@ def save(self, *args, **kwargs):
self.more_html = ""
super().save(*args, **kwargs)

@models.permalink
def get_absolute_url(self):
return ('post_detail', (), {
def get_url_params(self):
return {
'year': self.pub_date.strftime("%Y"),
'month': self.pub_date.strftime("%m"),
'day': self.pub_date.strftime("%d"),
'slug': self.slug
})
}

@models.permalink
def get_absolute_url(self):
return ('post_detail', (), self.get_url_params())

@models.permalink
def get_edit_url(self):
return ('edit_post', (), {
'year': self.pub_date.strftime("%Y"),
'month': self.pub_date.strftime("%m"),
'day': self.pub_date.strftime("%d"),
'slug': self.slug
})
return ('edit_post', (), self.get_url_params())

@models.permalink
def get_review_url(self):
return ('review_post', (), self.get_url_params())

@models.permalink
def get_approve_url(self):
return ('approve_post', (), {
'year': self.pub_date.strftime("%Y"),
'month': self.pub_date.strftime("%m"),
'day': self.pub_date.strftime("%d"),
'slug': self.slug
})
return ('approve_post', (), self.get_url_params())
44 changes: 43 additions & 1 deletion blog/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ def test_blog_index(self):

def test_approve_post(self):
post = self.new_post(self.user_alice)
self.assertFalse(post.is_live())

# Verify that the general public can't access the post.
self.assertFalse(post.is_live())
response = self.get(post.get_absolute_url())
self.assertEqual(404, response.status_code)

Expand All @@ -60,3 +60,45 @@ def test_approve_post(self):
self.assertEqual(200, response.status_code)
self.assertFalse(response.context['can_edit'])
self.assertFalse(response.context['can_approve'])

def test_review_post(self):
""" Tests the review helper view. """
# Add a new post.
post = self.new_post(self.user_alice)
self.assertFalse(post.is_live())

# Verify that anonymous user is redirected to login.
response = self.get(post.get_review_url())
self.assertEqual(302, response.status_code)
self.assertTrue(reverse('hello') in response.url)

# Alice should be redirected to the actual post with some informative
# message.
response = self.get_client(self.user_alice).get(post.get_review_url(),
follow=True)
self.assertRedirects(response, post.get_absolute_url(), status_code=301)
self.assertTrue('messages' in response.context)
self.assertEqual(1, len(response.context['messages']))

# Bob should be redirected too.
response = self.get_client(self.user_bob).get(post.get_review_url(),
follow=True)
self.assertRedirects(response, post.get_absolute_url(), status_code=301)
self.assertTrue('messages' in response.context)
self.assertEqual(1, len(response.context['messages']))

# And the valid approver too.
response = self.get_client(self.user_approver_zoe).get(
post.get_review_url(), follow=True)
self.assertRedirects(response, post.get_absolute_url(), status_code=301)
self.assertTrue('messages' in response.context)
self.assertEqual(1, len(response.context['messages']))

# And the valid approver after the post is live too.
post.reviewed = True
post.save()
response = self.get_client(self.user_approver_zoe).get(
post.get_review_url(), follow=True)
self.assertRedirects(response, post.get_absolute_url(), status_code=301)
self.assertTrue('messages' in response.context)
self.assertEqual(1, len(response.context['messages']))
2 changes: 2 additions & 0 deletions blog/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
include([
url(r'^$', views.PostDetail.as_view(), name='post_detail'),
url(r'^edytuj/$', views.EditPost.as_view(), name='edit_post'),
url(r'^korekta/$', views.ReviewPost.as_view(),
name='review_post'),
url(r'^zatwierdz/$', views.ApprovePost.as_view(),
name='approve_post'),
])),
Expand Down
11 changes: 8 additions & 3 deletions blog/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from content.mixins import ContentItemEditMixin, ContentItemAddMixin
from content.mixins import ContentItemViewMixin
from content.mixins import ContentItemApproveMixin
from content.views import ReviewContentView


def obsolete_post(request, post_id):
Expand Down Expand Up @@ -40,7 +41,7 @@ def get_context_data(self, **kwargs):
return context


class PostGetObjectMixin(object):
class GetPostMixin(object):
def get_object(self):
import time
year = self.kwargs['year']
Expand Down Expand Up @@ -68,7 +69,7 @@ def get_success_url(self):
return self.object.get_absolute_url()


class EditPost(PostGetObjectMixin, ContentItemEditMixin, UpdateView):
class EditPost(GetPostMixin, ContentItemEditMixin, UpdateView):
model = Post
form_class = PostForm
template_name = "blog/add_edit_post.html"
Expand All @@ -77,5 +78,9 @@ def get_success_url(self):
return self.object.get_absolute_url()


class ApprovePost(PostGetObjectMixin, ContentItemApproveMixin, RedirectView):
class ReviewPost(GetPostMixin, ReviewContentView):
pass


class ApprovePost(GetPostMixin, ContentItemApproveMixin, RedirectView):
pass
36 changes: 36 additions & 0 deletions content/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic import RedirectView


class ReviewContentView(RedirectView):
""" Redirects to content to be reviewed and puts up a helper message
depending on whether the item has already been reviewed and whether the user
has the rights to approve it.
Requirements for impl:
- self.get_object() has to return the content item
"""

@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)

def get_redirect_url(self, *args, **kwargs):
item = self.get_object()
if item.is_live():
messages.add_message(self.request, messages.INFO,
"Materiał został już wcześniej zatwierdzony.")
return item.get_absolute_url()

if not item.can_be_approved_by(self.request.user):
messages.add_message(self.request, messages.INFO,
"Ten materiał nie może być zatwierdzony przez "
"Ciebie.")
return item.get_absolute_url()

messages.add_message(self.request, messages.INFO,
"Edytuj lub zatwierdź materiał przy pomocy linków "
"na dole strony.")
return item.get_absolute_url()
29 changes: 13 additions & 16 deletions events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,32 +103,29 @@ def save(self, *args, **kwargs):
self.description_html = render_trevor(self.description_trevor)
super().save(*args, **kwargs)

@models.permalink
def get_absolute_url(self):
return ('event_detail', (), {
def get_url_params(self):
return {
'year': self.datetime.strftime("%Y"),
'month': self.datetime.strftime("%m"),
'day': self.datetime.strftime("%d"),
'slug': self.slug
})
}

@models.permalink
def get_absolute_url(self):
return ('event_detail', (), self.get_url_params())

@models.permalink
def get_edit_url(self):
return ('edit_event', (), {
'year': self.datetime.strftime("%Y"),
'month': self.datetime.strftime("%m"),
'day': self.datetime.strftime("%d"),
'slug': self.slug
})
return ('edit_event', (), self.get_url_params())

@models.permalink
def get_review_url(self):
return ('review_event', (), self.get_url_params())

@models.permalink
def get_approve_url(self):
return ('approve_event', (), {
'year': self.datetime.strftime("%Y"),
'month': self.datetime.strftime("%m"),
'day': self.datetime.strftime("%d"),
'slug': self.slug
})
return ('approve_event', (), self.get_url_params())

# SlugMixin:
def get_slug_elements(self):
Expand Down
2 changes: 2 additions & 0 deletions events/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
url(r'^(?P<day>\d{2})/(?P<slug>[-\w]+)/', include([
url(r'^$', views.EventDetail.as_view(), name="event_detail"),
url(r'^edytuj/$', views.EditEvent.as_view(), name="edit_event"),
url(r'^korekta/$', views.ReviewEvent.as_view(),
name="review_event"),
url(r'^zatwierdz/$', views.ApproveEvent.as_view(),
name="approve_event")
])),
Expand Down
11 changes: 8 additions & 3 deletions events/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from content.mixins import ContentItemEditMixin, ContentItemAddMixin
from content.mixins import ContentItemViewMixin, ManageInlineFormsetMixin
from content.mixins import ContentItemApproveMixin
from content.views import ReviewContentView


class EventIndex(EventMenuMixin, TemplateView):
Expand Down Expand Up @@ -121,7 +122,7 @@ def get_success_url(self):
return self.object.get_absolute_url()


class EventGetObjectMixin(object):
class GetEventMixin(object):
def get_object(self):
import time
year = self.kwargs['year']
Expand All @@ -136,7 +137,7 @@ def get_object(self):
datetime__day=event_date.day)


class EditEvent(EventGetObjectMixin, ContentItemEditMixin,
class EditEvent(GetEventMixin, ContentItemEditMixin,
ManageInlineFormsetMixin, UpdateView):
model = Event
form_class = EventForm
Expand Down Expand Up @@ -171,5 +172,9 @@ def get_success_url(self):
return self.object.get_absolute_url()


class ApproveEvent(EventGetObjectMixin, ContentItemApproveMixin, RedirectView):
class ReviewEvent(GetEventMixin, ReviewContentView):
pass


class ApproveEvent(GetEventMixin, ContentItemApproveMixin, RedirectView):
pass
15 changes: 12 additions & 3 deletions songs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,26 @@ def __str__(self):
else:
return self.title

def get_url_params(self):
return {
'slug': self.slug
}

@models.permalink
def get_absolute_url(self):
return ('song', (), {'slug': self.slug})
return ('song', (), self.get_url_params())

@models.permalink
def get_edit_url(self):
return ('edit_song', (), {'slug': self.slug})
return ('edit_song', (), self.get_url_params())

@models.permalink
def get_review_url(self):
return ('review_song', (), self.get_url_params())

@models.permalink
def get_approve_url(self):
return ('approve_song', (), {'slug': self.slug})
return ('approve_song', (), self.get_url_params())

def clean(self):
try:
Expand Down
1 change: 1 addition & 0 deletions songs/song_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
url(r'^transpose/(?P<transposition>\d+)/$', views.SongView.as_view(),
name="song-transposition"),
url(r'^edytuj/$', views.EditSong.as_view(), name="edit_song"),
url(r'^korekta/$', views.ReviewSong.as_view(), name="review_song"),
url(r'^zatwierdz/$', views.ApproveSong.as_view(), name="approve_song"),
])),
]
Loading

0 comments on commit 8ad6f83

Please sign in to comment.