annotate comments/views.py @ 989:2908859c2fe4

Smilies now use relative links. This is for upcoming switch to SSL. Currently we do not need absolute URLs for smilies. If this changes we can add it later.
author Brian Neal <bgneal@gmail.com>
date Thu, 29 Oct 2015 20:54:34 -0500
parents a828e80223d2
children 68c3343f3318
rev   line source
gremmie@1 1 """
gremmie@1 2 Views for the comments application.
bgneal@693 3
gremmie@1 4 """
gremmie@1 5 from django.contrib.auth.decorators import login_required
gremmie@1 6 from django.core.exceptions import ObjectDoesNotExist
gremmie@1 7 from django.http import HttpResponse
gremmie@1 8 from django.http import HttpResponseBadRequest
gremmie@1 9 from django.http import HttpResponseForbidden
gremmie@1 10 from django.db.models import get_model
gremmie@1 11 from django.shortcuts import render_to_response
gremmie@1 12 from django.template import RequestContext
gremmie@1 13 from django.utils.html import escape
gremmie@1 14 from django.views.decorators.http import require_POST
gremmie@1 15
gremmie@1 16 from core.functions import email_admins
bgneal@974 17 from core.html import image_check, ImageCheckError
bgneal@136 18 from core.markup import site_markup
gremmie@1 19 from comments.forms import CommentForm
gremmie@1 20 from comments.models import Comment
gremmie@1 21 from comments.models import CommentFlag
bgneal@215 22 import antispam
bgneal@215 23 import antispam.utils
bgneal@215 24
gremmie@1 25
bgneal@974 26 PREVIEW_UNAVAILABLE = """
bgneal@974 27 <p><strong>Error</strong>: {}</p>
bgneal@974 28 <p>Sorry, preview is unavailable.</p>
bgneal@974 29 <p>There is an image in your post which failed our image check. We can only
bgneal@974 30 accept images from a small number of sources for security reasons. You may use
bgneal@974 31 the forms below this box to safely hot-link to images hosted elsewhere on the
bgneal@974 32 Internet or upload from your computer or device.</p>
bgneal@974 33 """
bgneal@974 34
bgneal@974 35
gremmie@1 36 @login_required
gremmie@1 37 @require_POST
gremmie@1 38 def post_comment(request):
gremmie@1 39 """
gremmie@1 40 This function handles the posting of comments. If successful, returns
bgneal@215 41 the comment text as the response. This function is meant to be the target
gremmie@1 42 of an AJAX post.
gremmie@1 43 """
gremmie@1 44 # Look up the object we're trying to comment about
gremmie@1 45 ctype = request.POST.get('content_type', None)
gremmie@1 46 object_pk = request.POST.get('object_pk', None)
gremmie@1 47 if ctype is None or object_pk is None:
gremmie@1 48 return HttpResponseBadRequest('Missing content_type or object_pk field.')
gremmie@1 49
gremmie@1 50 try:
gremmie@1 51 model = get_model(*ctype.split('.', 1))
gremmie@1 52 target = model.objects.get(pk=object_pk)
gremmie@1 53 except TypeError:
gremmie@1 54 return HttpResponseBadRequest(
gremmie@1 55 "Invalid content_type value: %r" % escape(ctype))
gremmie@1 56 except AttributeError:
gremmie@1 57 return HttpResponseBadRequest(
gremmie@1 58 "The given content-type %r does not resolve to a valid model." % \
gremmie@1 59 escape(ctype))
gremmie@1 60 except ObjectDoesNotExist:
gremmie@1 61 return HttpResponseBadRequest(
gremmie@1 62 "No object matching content-type %r and object PK %r exists." % \
gremmie@1 63 (escape(ctype), escape(object_pk)))
gremmie@1 64
gremmie@1 65 # Can we comment on the target object?
gremmie@1 66 if hasattr(target, 'can_comment_on'):
gremmie@1 67 if callable(target.can_comment_on):
gremmie@1 68 can_comment_on = target.can_comment_on()
gremmie@1 69 else:
gremmie@1 70 can_comment_on = target.can_comment_on
gremmie@1 71 else:
gremmie@1 72 can_comment_on = True
gremmie@1 73
gremmie@1 74 if not can_comment_on:
gremmie@1 75 return HttpResponseForbidden('Cannot comment on this item.')
gremmie@1 76
gremmie@1 77 # Check form validity
gremmie@1 78
gremmie@1 79 form = CommentForm(target, request.POST)
gremmie@1 80 if not form.is_valid():
bgneal@963 81 # The client side javascript is pretty simplistic right now and we don't
bgneal@963 82 # want to change it yet. It is expecting a single error string. Just grab
bgneal@963 83 # the first error message and use that.
bgneal@963 84 errors = form.errors.as_data()
bgneal@963 85 msg = errors.values()[0][0].message if errors else 'Unknown error'
bgneal@963 86 return HttpResponseBadRequest(msg)
gremmie@1 87
bgneal@215 88 comment = form.get_comment_object(request.user, request.META.get("REMOTE_ADDR", None))
gremmie@1 89
bgneal@693 90 # Check for spam
bgneal@215 91
bgneal@215 92 if antispam.utils.spam_check(request, comment.comment):
bgneal@215 93 return HttpResponseForbidden(antispam.BUSTED_MESSAGE)
bgneal@215 94
bgneal@963 95 comment.save(html=form.comment_html)
gremmie@1 96
gremmie@1 97 # return the rendered comment
gremmie@1 98 return render_to_response('comments/comment.html', {
gremmie@1 99 'comment': comment,
gremmie@1 100 },
gremmie@1 101 context_instance = RequestContext(request))
bgneal@693 102
gremmie@1 103
gremmie@1 104 @require_POST
gremmie@1 105 def flag_comment(request):
gremmie@1 106 """
gremmie@1 107 This function handles the flagging of comments by users. This function should
gremmie@1 108 be the target of an AJAX post.
gremmie@1 109 """
gremmie@1 110 if not request.user.is_authenticated():
gremmie@1 111 return HttpResponse('Please login or register to flag a comment.')
gremmie@1 112
gremmie@1 113 id = request.POST.get('id', None)
gremmie@1 114 if id is None:
gremmie@1 115 return HttpResponseBadRequest('No id')
gremmie@1 116
gremmie@1 117 try:
gremmie@1 118 comment = Comment.objects.get(pk=id)
gremmie@1 119 except Comment.DoesNotExist:
gremmie@1 120 return HttpResponseBadRequest('No comment with id %s' % id)
gremmie@1 121
gremmie@1 122 flag = CommentFlag(user=request.user, comment=comment)
gremmie@1 123 flag.save()
gremmie@1 124 email_admins('A Comment Has Been Flagged', """Hello,
gremmie@1 125
gremmie@1 126 A user has flagged a comment for review.
gremmie@1 127 """)
gremmie@1 128 return HttpResponse('The comment was flagged. A moderator will review the comment shortly. ' \
gremmie@1 129 'Thanks for helping to improve the discussions on this site.')
gremmie@1 130
gremmie@1 131
gremmie@1 132 @require_POST
gremmie@1 133 def markdown_preview(request):
gremmie@1 134 """
gremmie@1 135 This function should be the target of an AJAX POST. It takes the 'data' parameter
gremmie@1 136 from the POST parameters and returns a rendered HTML page from the data, which
bgneal@693 137 is assumed to be in markdown format. The HTML page is suitable for the preview
gremmie@1 138 function for a javascript editor such as markItUp.
gremmie@1 139 """
gremmie@1 140 if not request.user.is_authenticated():
gremmie@1 141 return HttpResponseForbidden('This service is only available to logged in users.')
gremmie@1 142
gremmie@1 143 data = request.POST.get('data', None)
gremmie@1 144 if data is None:
gremmie@1 145 return HttpResponseBadRequest('No data')
gremmie@1 146
bgneal@974 147 html = site_markup(data)
bgneal@978 148 if html:
bgneal@978 149 try:
bgneal@978 150 image_check(html)
bgneal@978 151 except ImageCheckError as ex:
bgneal@978 152 html = PREVIEW_UNAVAILABLE.format(ex)
bgneal@974 153
gremmie@1 154 return render_to_response('comments/markdown_preview.html', {
bgneal@974 155 'data': html,
gremmie@1 156 },
gremmie@1 157 context_instance = RequestContext(request))