web/lib/django/contrib/comments/views/comments.py
changeset 38 77b6da96e6f1
equal deleted inserted replaced
37:8d941af65caf 38:77b6da96e6f1
       
     1 from django import http
       
     2 from django.conf import settings
       
     3 from utils import next_redirect, confirmation_view
       
     4 from django.core.exceptions import ObjectDoesNotExist, ValidationError
       
     5 from django.db import models
       
     6 from django.shortcuts import render_to_response
       
     7 from django.template import RequestContext
       
     8 from django.template.loader import render_to_string
       
     9 from django.utils.html import escape
       
    10 from django.views.decorators.http import require_POST
       
    11 from django.contrib import comments
       
    12 from django.contrib.comments import signals
       
    13 from django.views.decorators.csrf import csrf_protect
       
    14 
       
    15 class 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
       
    28 def 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 
       
   132 comment_done = confirmation_view(
       
   133     template = "comments/posted.html",
       
   134     doc = """Display a "comment was posted" success page."""
       
   135 )
       
   136