|
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 |
|
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 |
|
14 class CommentPostBadRequest(http.HttpResponseBadRequest): |
|
15 """ |
|
16 Response returned when a comment post is invalid. If ``DEBUG`` is on a |
|
17 nice-ish error message will be displayed (for debugging purposes), but in |
|
18 production mode a simple opaque 400 page will be displayed. |
|
19 """ |
|
20 def __init__(self, why): |
|
21 super(CommentPostBadRequest, self).__init__() |
|
22 if settings.DEBUG: |
|
23 self.content = render_to_string("comments/400-debug.html", {"why": why}) |
|
24 |
|
25 def post_comment(request, next=None): |
|
26 """ |
|
27 Post a comment. |
|
28 |
|
29 HTTP POST is required. If ``POST['submit'] == "preview"`` or if there are |
|
30 errors a preview template, ``comments/preview.html``, will be rendered. |
|
31 """ |
|
32 # Fill out some initial data fields from an authenticated user, if present |
|
33 data = request.POST.copy() |
|
34 if request.user.is_authenticated(): |
|
35 if not data.get('name', ''): |
|
36 data["name"] = request.user.get_full_name() or request.user.username |
|
37 if not data.get('email', ''): |
|
38 data["email"] = request.user.email |
|
39 |
|
40 # Check to see if the POST data overrides the view's next argument. |
|
41 next = data.get("next", next) |
|
42 |
|
43 # Look up the object we're trying to comment about |
|
44 ctype = data.get("content_type") |
|
45 object_pk = data.get("object_pk") |
|
46 if ctype is None or object_pk is None: |
|
47 return CommentPostBadRequest("Missing content_type or object_pk field.") |
|
48 try: |
|
49 model = models.get_model(*ctype.split(".", 1)) |
|
50 target = model._default_manager.get(pk=object_pk) |
|
51 except TypeError: |
|
52 return CommentPostBadRequest( |
|
53 "Invalid content_type value: %r" % escape(ctype)) |
|
54 except AttributeError: |
|
55 return CommentPostBadRequest( |
|
56 "The given content-type %r does not resolve to a valid model." % \ |
|
57 escape(ctype)) |
|
58 except ObjectDoesNotExist: |
|
59 return CommentPostBadRequest( |
|
60 "No object matching content-type %r and object PK %r exists." % \ |
|
61 (escape(ctype), escape(object_pk))) |
|
62 |
|
63 # Do we want to preview the comment? |
|
64 preview = "preview" in data |
|
65 |
|
66 # Construct the comment form |
|
67 form = comments.get_form()(target, data=data) |
|
68 |
|
69 # Check security information |
|
70 if form.security_errors(): |
|
71 return CommentPostBadRequest( |
|
72 "The comment form failed security verification: %s" % \ |
|
73 escape(str(form.security_errors()))) |
|
74 |
|
75 # If there are errors or if we requested a preview show the comment |
|
76 if form.errors or preview: |
|
77 template_list = [ |
|
78 "comments/%s_%s_preview.html" % tuple(str(model._meta).split(".")), |
|
79 "comments/%s_preview.html" % model._meta.app_label, |
|
80 "comments/preview.html", |
|
81 ] |
|
82 return render_to_response( |
|
83 template_list, { |
|
84 "comment" : form.data.get("comment", ""), |
|
85 "form" : form, |
|
86 "next": next, |
|
87 }, |
|
88 RequestContext(request, {}) |
|
89 ) |
|
90 |
|
91 # Otherwise create the comment |
|
92 comment = form.get_comment_object() |
|
93 comment.ip_address = request.META.get("REMOTE_ADDR", None) |
|
94 if request.user.is_authenticated(): |
|
95 comment.user = request.user |
|
96 |
|
97 # Signal that the comment is about to be saved |
|
98 responses = signals.comment_will_be_posted.send( |
|
99 sender = comment.__class__, |
|
100 comment = comment, |
|
101 request = request |
|
102 ) |
|
103 |
|
104 for (receiver, response) in responses: |
|
105 if response == False: |
|
106 return CommentPostBadRequest( |
|
107 "comment_will_be_posted receiver %r killed the comment" % receiver.__name__) |
|
108 |
|
109 # Save the comment and signal that it was saved |
|
110 comment.save() |
|
111 signals.comment_was_posted.send( |
|
112 sender = comment.__class__, |
|
113 comment = comment, |
|
114 request = request |
|
115 ) |
|
116 |
|
117 return next_redirect(data, next, comment_done, c=comment._get_pk_val()) |
|
118 |
|
119 post_comment = require_POST(post_comment) |
|
120 |
|
121 comment_done = confirmation_view( |
|
122 template = "comments/posted.html", |
|
123 doc = """Display a "comment was posted" success page.""" |
|
124 ) |
|
125 |