/django/contrib/comments/views/comments.py
Python | 136 lines | 112 code | 7 blank | 17 comment | 7 complexity | a832bc53a061c08897d46a94fc8f2d2f MD5 | raw file
1from django import http 2from django.conf import settings 3from utils import next_redirect, confirmation_view 4from django.core.exceptions import ObjectDoesNotExist, ValidationError 5from django.db import models 6from django.shortcuts import render_to_response 7from django.template import RequestContext 8from django.template.loader import render_to_string 9from django.utils.html import escape 10from django.views.decorators.http import require_POST 11from django.contrib import comments 12from django.contrib.comments import signals 13from django.views.decorators.csrf import csrf_protect 14 15class CommentPostBadRequest(http.HttpResponseBadRequest): 16 """ 17 Response returned when a comment post is invalid. If ``DEBUG`` is on a 18 nice-ish error message will be displayed (for debugging purposes), but in 19 production mode a simple opaque 400 page will be displayed. 20 """ 21 def __init__(self, why): 22 super(CommentPostBadRequest, self).__init__() 23 if settings.DEBUG: 24 self.content = render_to_string("comments/400-debug.html", {"why": why}) 25 26@csrf_protect 27@require_POST 28def post_comment(request, next=None, using=None): 29 """ 30 Post a comment. 31 32 HTTP POST is required. If ``POST['submit'] == "preview"`` or if there are 33 errors a preview template, ``comments/preview.html``, will be rendered. 34 """ 35 # Fill out some initial data fields from an authenticated user, if present 36 data = request.POST.copy() 37 if request.user.is_authenticated(): 38 if not data.get('name', ''): 39 data["name"] = request.user.get_full_name() or request.user.username 40 if not data.get('email', ''): 41 data["email"] = request.user.email 42 43 # Check to see if the POST data overrides the view's next argument. 44 next = data.get("next", next) 45 46 # Look up the object we're trying to comment about 47 ctype = data.get("content_type") 48 object_pk = data.get("object_pk") 49 if ctype is None or object_pk is None: 50 return CommentPostBadRequest("Missing content_type or object_pk field.") 51 try: 52 model = models.get_model(*ctype.split(".", 1)) 53 target = model._default_manager.using(using).get(pk=object_pk) 54 except TypeError: 55 return CommentPostBadRequest( 56 "Invalid content_type value: %r" % escape(ctype)) 57 except AttributeError: 58 return CommentPostBadRequest( 59 "The given content-type %r does not resolve to a valid model." % \ 60 escape(ctype)) 61 except ObjectDoesNotExist: 62 return CommentPostBadRequest( 63 "No object matching content-type %r and object PK %r exists." % \ 64 (escape(ctype), escape(object_pk))) 65 except (ValueError, ValidationError), e: 66 return CommentPostBadRequest( 67 "Attempting go get content-type %r and object PK %r exists raised %s" % \ 68 (escape(ctype), escape(object_pk), e.__class__.__name__)) 69 70 # Do we want to preview the comment? 71 preview = "preview" in data 72 73 # Construct the comment form 74 form = comments.get_form()(target, data=data) 75 76 # Check security information 77 if form.security_errors(): 78 return CommentPostBadRequest( 79 "The comment form failed security verification: %s" % \ 80 escape(str(form.security_errors()))) 81 82 # If there are errors or if we requested a preview show the comment 83 if form.errors or preview: 84 template_list = [ 85 # These first two exist for purely historical reasons. 86 # Django v1.0 and v1.1 allowed the underscore format for 87 # preview templates, so we have to preserve that format. 88 "comments/%s_%s_preview.html" % (model._meta.app_label, model._meta.module_name), 89 "comments/%s_preview.html" % model._meta.app_label, 90 # Now the usual directory based template heirarchy. 91 "comments/%s/%s/preview.html" % (model._meta.app_label, model._meta.module_name), 92 "comments/%s/preview.html" % model._meta.app_label, 93 "comments/preview.html", 94 ] 95 return render_to_response( 96 template_list, { 97 "comment" : form.data.get("comment", ""), 98 "form" : form, 99 "next": next, 100 }, 101 RequestContext(request, {}) 102 ) 103 104 # Otherwise create the comment 105 comment = form.get_comment_object() 106 comment.ip_address = request.META.get("REMOTE_ADDR", None) 107 if request.user.is_authenticated(): 108 comment.user = request.user 109 110 # Signal that the comment is about to be saved 111 responses = signals.comment_will_be_posted.send( 112 sender = comment.__class__, 113 comment = comment, 114 request = request 115 ) 116 117 for (receiver, response) in responses: 118 if response == False: 119 return CommentPostBadRequest( 120 "comment_will_be_posted receiver %r killed the comment" % receiver.__name__) 121 122 # Save the comment and signal that it was saved 123 comment.save() 124 signals.comment_was_posted.send( 125 sender = comment.__class__, 126 comment = comment, 127 request = request 128 ) 129 130 return next_redirect(data, next, comment_done, c=comment._get_pk_val()) 131 132comment_done = confirmation_view( 133 template = "comments/posted.html", 134 doc = """Display a "comment was posted" success page.""" 135) 136