Navigation Menu

Skip to content

Commit

Permalink
Fixed #11625: added comment moderation via admin actions.
Browse files Browse the repository at this point in the history
This is BACKWARDS INCOMPATIBLE if you were using the completely undocumented moderation view from 1.1. That view's been removed in favor of the admin actions.

Thanks, Thejaswi Puthraya.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11639 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jacobian committed Oct 23, 2009
1 parent 162fade commit 8be1bb2
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 211 deletions.
41 changes: 40 additions & 1 deletion django/contrib/comments/admin.py
@@ -1,7 +1,8 @@
from django.contrib import admin
from django.contrib.comments.models import Comment
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _, ungettext
from django.contrib.comments import get_model
from django.contrib.comments.views.moderation import perform_flag, perform_approve, perform_delete

class CommentsAdmin(admin.ModelAdmin):
fieldsets = (
Expand All @@ -22,6 +23,44 @@ class CommentsAdmin(admin.ModelAdmin):
ordering = ('-submit_date',)
raw_id_fields = ('user',)
search_fields = ('comment', 'user__username', 'user_name', 'user_email', 'user_url', 'ip_address')
actions = ["flag_comments", "approve_comments", "remove_comments"]

def get_actions(self, request):
actions = super(CommentsAdmin, self).get_actions(request)
# Only superusers should be able to delete the comments from the DB.
if not request.user.is_superuser:
actions.pop('delete_selected')
if not request.user.has_perm('comments.can_moderate'):
actions.pop('approve_comments')
actions.pop('remove_comments')
return actions

def flag_comments(self, request, queryset):
self._bulk_flag(request, queryset, perform_flag, _("flagged"))
flag_comments.short_description = _("Flag selected comments")

def approve_comments(self, request, queryset):
self._bulk_flag(request, queryset, perform_approve, _('approved'))
approve_comments.short_description = _("Approve selected comments")

def remove_comments(self, request, queryset):
self._bulk_flag(request, queryset, perform_delete, _('removed'))
remove_comments.short_description = _("Remove selected comments")

def _bulk_flag(self, request, queryset, action, description):
"""
Flag, approve, or remove some comments from an admin action. Actually
calls the `action` argument to perform the heavy lifting.
"""
n_comments = 0
for comment in queryset:
action(request, comment)
n_comments += 1

msg = ungettext(u'1 comment was successfully %(action)s.',
u'%(count)s comments were successfully %(action)s.',
n_comments)
self.message_user(request, msg % {'count': n_comments, 'action': description})

# Only register the default admin if the model is the built-in comment model
# (this won't be true if there's a custom comment app).
Expand Down
75 changes: 0 additions & 75 deletions django/contrib/comments/templates/comments/moderation_queue.html

This file was deleted.

1 change: 0 additions & 1 deletion django/contrib/comments/urls.py
Expand Up @@ -7,7 +7,6 @@
url(r'^flagged/$', 'moderation.flag_done', name='comments-flag-done'),
url(r'^delete/(\d+)/$', 'moderation.delete', name='comments-delete'),
url(r'^deleted/$', 'moderation.delete_done', name='comments-delete-done'),
url(r'^moderate/$', 'moderation.moderation_queue', name='comments-moderation-queue'),
url(r'^approve/(\d+)/$', 'moderation.approve', name='comments-approve'),
url(r'^approved/$', 'moderation.approve_done', name='comments-approve-done'),
)
Expand Down
171 changes: 61 additions & 110 deletions django/contrib/comments/views/moderation.py
Expand Up @@ -3,12 +3,10 @@
from django.shortcuts import get_object_or_404, render_to_response
from django.contrib.auth.decorators import login_required, permission_required
from utils import next_redirect, confirmation_view
from django.core.paginator import Paginator, InvalidPage
from django.http import Http404
from django.contrib import comments
from django.contrib.comments import signals

#@login_required
@login_required
def flag(request, comment_id, next=None):
"""
Flags a comment. Confirmation on GET, action on POST.
Expand All @@ -22,18 +20,7 @@ def flag(request, comment_id, next=None):

# Flag on POST
if request.method == 'POST':
flag, created = comments.models.CommentFlag.objects.get_or_create(
comment = comment,
user = request.user,
flag = comments.models.CommentFlag.SUGGEST_REMOVAL
)
signals.comment_was_flagged.send(
sender = comment.__class__,
comment = comment,
flag = flag,
created = created,
request = request,
)
perform_flag(request, comment)
return next_redirect(request.POST.copy(), next, flag_done, c=comment.pk)

# Render a form on GET
Expand All @@ -42,9 +29,8 @@ def flag(request, comment_id, next=None):
{'comment': comment, "next": next},
template.RequestContext(request)
)
flag = login_required(flag)

#@permission_required("comments.delete_comment")
@permission_required("comments.can_moderate")
def delete(request, comment_id, next=None):
"""
Deletes a comment. Confirmation on GET, action on POST. Requires the "can
Expand All @@ -60,20 +46,7 @@ def delete(request, comment_id, next=None):
# Delete on POST
if request.method == 'POST':
# Flag the comment as deleted instead of actually deleting it.
flag, created = comments.models.CommentFlag.objects.get_or_create(
comment = comment,
user = request.user,
flag = comments.models.CommentFlag.MODERATOR_DELETION
)
comment.is_removed = True
comment.save()
signals.comment_was_flagged.send(
sender = comment.__class__,
comment = comment,
flag = flag,
created = created,
request = request,
)
perform_delete(request, comment)
return next_redirect(request.POST.copy(), next, delete_done, c=comment.pk)

# Render a form on GET
Expand All @@ -82,9 +55,8 @@ def delete(request, comment_id, next=None):
{'comment': comment, "next": next},
template.RequestContext(request)
)
delete = permission_required("comments.can_moderate")(delete)

#@permission_required("comments.can_moderate")
@permission_required("comments.can_moderate")
def approve(request, comment_id, next=None):
"""
Approve a comment (that is, mark it as public and non-removed). Confirmation
Expand All @@ -100,23 +72,7 @@ def approve(request, comment_id, next=None):
# Delete on POST
if request.method == 'POST':
# Flag the comment as approved.
flag, created = comments.models.CommentFlag.objects.get_or_create(
comment = comment,
user = request.user,
flag = comments.models.CommentFlag.MODERATOR_APPROVAL,
)

comment.is_removed = False
comment.is_public = True
comment.save()

signals.comment_was_flagged.send(
sender = comment.__class__,
comment = comment,
flag = flag,
created = created,
request = request,
)
perform_approve(request, comment)
return next_redirect(request.POST.copy(), next, approve_done, c=comment.pk)

# Render a form on GET
Expand All @@ -126,69 +82,64 @@ def approve(request, comment_id, next=None):
template.RequestContext(request)
)

approve = permission_required("comments.can_moderate")(approve)

# The following functions actually perform the various flag/aprove/delete
# actions. They've been broken out into seperate functions to that they
# may be called from admin actions.

#@permission_required("comments.can_moderate")
def moderation_queue(request):
def perform_flag(request, comment):
"""
Displays a list of unapproved comments to be approved.
Templates: `comments/moderation_queue.html`
Context:
comments
Comments to be approved (paginated).
empty
Is the comment list empty?
is_paginated
Is there more than one page?
results_per_page
Number of comments per page
has_next
Is there a next page?
has_previous
Is there a previous page?
page
The current page number
next
The next page number
pages
Number of pages
hits
Total number of comments
page_range
Range of page numbers
Actually perform the flagging of a comment from a request.
"""
qs = comments.get_model().objects.filter(is_public=False, is_removed=False)
paginator = Paginator(qs, 100)

try:
page = int(request.GET.get("page", 1))
except ValueError:
raise Http404

try:
comments_per_page = paginator.page(page)
except InvalidPage:
raise Http404

return render_to_response("comments/moderation_queue.html", {
'comments' : comments_per_page.object_list,
'empty' : page == 1 and paginator.count == 0,
'is_paginated': paginator.num_pages > 1,
'results_per_page': 100,
'has_next': comments_per_page.has_next(),
'has_previous': comments_per_page.has_previous(),
'page': page,
'next': page + 1,
'previous': page - 1,
'pages': paginator.num_pages,
'hits' : paginator.count,
'page_range' : paginator.page_range
}, context_instance=template.RequestContext(request))

moderation_queue = permission_required("comments.can_moderate")(moderation_queue)
flag, created = comments.models.CommentFlag.objects.get_or_create(
comment = comment,
user = request.user,
flag = comments.models.CommentFlag.SUGGEST_REMOVAL
)
signals.comment_was_flagged.send(
sender = comment.__class__,
comment = comment,
flag = flag,
created = created,
request = request,
)

def perform_delete(request, comment):
flag, created = comments.models.CommentFlag.objects.get_or_create(
comment = comment,
user = request.user,
flag = comments.models.CommentFlag.MODERATOR_DELETION
)
comment.is_removed = True
comment.save()
signals.comment_was_flagged.send(
sender = comment.__class__,
comment = comment,
flag = flag,
created = created,
request = request,
)


def perform_approve(request, comment):
flag, created = comments.models.CommentFlag.objects.get_or_create(
comment = comment,
user = request.user,
flag = comments.models.CommentFlag.MODERATOR_APPROVAL,
)

comment.is_removed = False
comment.is_public = True
comment.save()

signals.comment_was_flagged.send(
sender = comment.__class__,
comment = comment,
flag = flag,
created = created,
request = request,
)

# Confirmation views.

flag_done = confirmation_view(
template = "comments/flagged.html",
Expand Down

0 comments on commit 8be1bb2

Please sign in to comment.