gremmie@1: """ gremmie@1: Views for the comments application. bgneal@693: gremmie@1: """ gremmie@1: from django.contrib.auth.decorators import login_required gremmie@1: from django.core.exceptions import ObjectDoesNotExist gremmie@1: from django.http import HttpResponse gremmie@1: from django.http import HttpResponseBadRequest gremmie@1: from django.http import HttpResponseForbidden gremmie@1: from django.db.models import get_model gremmie@1: from django.shortcuts import render_to_response gremmie@1: from django.template import RequestContext gremmie@1: from django.utils.html import escape gremmie@1: from django.views.decorators.http import require_POST gremmie@1: gremmie@1: from core.functions import email_admins bgneal@974: from core.html import image_check, ImageCheckError bgneal@136: from core.markup import site_markup gremmie@1: from comments.forms import CommentForm gremmie@1: from comments.models import Comment gremmie@1: from comments.models import CommentFlag bgneal@215: import antispam bgneal@215: import antispam.utils bgneal@215: gremmie@1: bgneal@974: PREVIEW_UNAVAILABLE = """ bgneal@974:
Error: {}
bgneal@974:Sorry, preview is unavailable.
bgneal@974:There is an image in your post which failed our image check. We can only bgneal@974: accept images from a small number of sources for security reasons. You may use bgneal@974: the forms below this box to safely hot-link to images hosted elsewhere on the bgneal@974: Internet or upload from your computer or device.
bgneal@974: """ bgneal@974: bgneal@974: gremmie@1: @login_required gremmie@1: @require_POST gremmie@1: def post_comment(request): gremmie@1: """ gremmie@1: This function handles the posting of comments. If successful, returns bgneal@215: the comment text as the response. This function is meant to be the target gremmie@1: of an AJAX post. gremmie@1: """ gremmie@1: # Look up the object we're trying to comment about gremmie@1: ctype = request.POST.get('content_type', None) gremmie@1: object_pk = request.POST.get('object_pk', None) gremmie@1: if ctype is None or object_pk is None: gremmie@1: return HttpResponseBadRequest('Missing content_type or object_pk field.') gremmie@1: gremmie@1: try: gremmie@1: model = get_model(*ctype.split('.', 1)) gremmie@1: target = model.objects.get(pk=object_pk) gremmie@1: except TypeError: gremmie@1: return HttpResponseBadRequest( gremmie@1: "Invalid content_type value: %r" % escape(ctype)) gremmie@1: except AttributeError: gremmie@1: return HttpResponseBadRequest( gremmie@1: "The given content-type %r does not resolve to a valid model." % \ gremmie@1: escape(ctype)) gremmie@1: except ObjectDoesNotExist: gremmie@1: return HttpResponseBadRequest( gremmie@1: "No object matching content-type %r and object PK %r exists." % \ gremmie@1: (escape(ctype), escape(object_pk))) gremmie@1: gremmie@1: # Can we comment on the target object? gremmie@1: if hasattr(target, 'can_comment_on'): gremmie@1: if callable(target.can_comment_on): gremmie@1: can_comment_on = target.can_comment_on() gremmie@1: else: gremmie@1: can_comment_on = target.can_comment_on gremmie@1: else: gremmie@1: can_comment_on = True gremmie@1: gremmie@1: if not can_comment_on: gremmie@1: return HttpResponseForbidden('Cannot comment on this item.') gremmie@1: gremmie@1: # Check form validity gremmie@1: gremmie@1: form = CommentForm(target, request.POST) gremmie@1: if not form.is_valid(): bgneal@963: # The client side javascript is pretty simplistic right now and we don't bgneal@963: # want to change it yet. It is expecting a single error string. Just grab bgneal@963: # the first error message and use that. bgneal@963: errors = form.errors.as_data() bgneal@963: msg = errors.values()[0][0].message if errors else 'Unknown error' bgneal@963: return HttpResponseBadRequest(msg) gremmie@1: bgneal@215: comment = form.get_comment_object(request.user, request.META.get("REMOTE_ADDR", None)) gremmie@1: bgneal@693: # Check for spam bgneal@215: bgneal@215: if antispam.utils.spam_check(request, comment.comment): bgneal@215: return HttpResponseForbidden(antispam.BUSTED_MESSAGE) bgneal@215: bgneal@963: comment.save(html=form.comment_html) gremmie@1: gremmie@1: # return the rendered comment gremmie@1: return render_to_response('comments/comment.html', { gremmie@1: 'comment': comment, gremmie@1: }, gremmie@1: context_instance = RequestContext(request)) bgneal@693: gremmie@1: gremmie@1: @require_POST gremmie@1: def flag_comment(request): gremmie@1: """ gremmie@1: This function handles the flagging of comments by users. This function should gremmie@1: be the target of an AJAX post. gremmie@1: """ gremmie@1: if not request.user.is_authenticated(): gremmie@1: return HttpResponse('Please login or register to flag a comment.') gremmie@1: gremmie@1: id = request.POST.get('id', None) gremmie@1: if id is None: gremmie@1: return HttpResponseBadRequest('No id') gremmie@1: gremmie@1: try: gremmie@1: comment = Comment.objects.get(pk=id) gremmie@1: except Comment.DoesNotExist: gremmie@1: return HttpResponseBadRequest('No comment with id %s' % id) gremmie@1: gremmie@1: flag = CommentFlag(user=request.user, comment=comment) gremmie@1: flag.save() gremmie@1: email_admins('A Comment Has Been Flagged', """Hello, gremmie@1: gremmie@1: A user has flagged a comment for review. gremmie@1: """) gremmie@1: return HttpResponse('The comment was flagged. A moderator will review the comment shortly. ' \ gremmie@1: 'Thanks for helping to improve the discussions on this site.') gremmie@1: gremmie@1: gremmie@1: @require_POST gremmie@1: def markdown_preview(request): gremmie@1: """ gremmie@1: This function should be the target of an AJAX POST. It takes the 'data' parameter gremmie@1: from the POST parameters and returns a rendered HTML page from the data, which bgneal@693: is assumed to be in markdown format. The HTML page is suitable for the preview gremmie@1: function for a javascript editor such as markItUp. gremmie@1: """ gremmie@1: if not request.user.is_authenticated(): gremmie@1: return HttpResponseForbidden('This service is only available to logged in users.') gremmie@1: gremmie@1: data = request.POST.get('data', None) gremmie@1: if data is None: gremmie@1: return HttpResponseBadRequest('No data') gremmie@1: bgneal@974: html = site_markup(data) bgneal@974: try: bgneal@974: image_check(html) bgneal@974: except ImageCheckError as ex: bgneal@974: html = PREVIEW_UNAVAILABLE.format(ex) bgneal@974: gremmie@1: return render_to_response('comments/markdown_preview.html', { bgneal@974: 'data': html, gremmie@1: }, gremmie@1: context_instance = RequestContext(request))