1
from django.http import HttpResponseRedirect, Http404
2
from django.contrib.auth.decorators import login_required
3
from django.contrib.contenttypes.models import ContentType
4
from django.shortcuts import get_object_or_404, render_to_response
5
from django.template import RequestContext, Context, Template
6
from django.utils.http import urlquote
7
from django.conf import settings
8
from threadedcomments.forms import FreeThreadedCommentForm, ThreadedCommentForm
9
from threadedcomments.models import ThreadedComment, FreeThreadedComment, DEFAULT_MAX_COMMENT_LENGTH
10
from threadedcomments.utils import JSONResponse, XMLResponse
12
def _adjust_max_comment_length(form, field_name='comment'):
14
Sets the maximum comment length to that default specified in the settings.
16
form.base_fields['comment'].max_length = DEFAULT_MAX_COMMENT_LENGTH
18
def _get_next(request):
20
The part that's the least straightforward about views in this module is how they
21
determine their redirects after they have finished computation.
23
In short, they will try and determine the next place to go in the following order:
25
1. If there is a variable named ``next`` in the *POST* parameters, the view will
26
redirect to that variable's value.
27
2. If there is a variable named ``next`` in the *GET* parameters, the view will
28
redirect to that variable's value.
29
3. If Django can determine the previous page from the HTTP headers, the view will
30
redirect to that previous page.
31
4. Otherwise, the view raise a 404 Not Found.
33
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None)))
34
if not next or next == request.path:
35
raise Http404 # No next url was supplied in GET or POST.
38
def _preview(request, context_processors, extra_context, form_class=ThreadedCommentForm):
40
Returns a preview of the comment so that the user may decide if he or she wants to
41
edit it before submitting it permanently.
43
_adjust_max_comment_length(form_class)
44
form = form_class(request.POST or None)
46
'next' : _get_next(request),
50
new_comment = form.save(commit=False)
51
context['comment'] = new_comment
53
context['comment'] = None
54
return render_to_response(
55
'threadedcomments/preview_comment.html',
57
context_instance = RequestContext(request, context, context_processors)
60
def free_comment(request, content_type=None, object_id=None, edit_id=None, parent_id=None, add_messages=False, ajax=False, model=FreeThreadedComment, form_class=FreeThreadedCommentForm, context_processors=[], extra_context={}):
62
Receives POST data and either creates a new ``ThreadedComment`` or
63
``FreeThreadedComment``, or edits an old one based upon the specified parameters.
65
If there is a 'preview' key in the POST request, a preview will be forced and the
66
comment will not be saved until a 'preview' key is no longer in the POST request.
68
If it is an *AJAX* request (either XML or JSON), it will return a serialized
69
version of the last created ``ThreadedComment`` and there will be no redirect.
71
If invalid POST data is submitted, this will go to the comment preview page
72
where the comment may be edited until it does not contain errors.
74
if not edit_id and not (content_type and object_id):
75
raise Http404 # Must specify either content_type and object_id or edit_id
76
if "preview" in request.POST:
77
return _preview(request, context_processors, extra_context, form_class=form_class)
79
instance = get_object_or_404(model, id=edit_id)
82
_adjust_max_comment_length(form_class)
83
form = form_class(request.POST, instance=instance)
85
new_comment = form.save(commit=False)
87
new_comment.ip_address = request.META.get('REMOTE_ADDR', None)
88
new_comment.content_type = get_object_or_404(ContentType, id = int(content_type))
89
new_comment.object_id = int(object_id)
90
if model == ThreadedComment:
91
new_comment.user = request.user
93
new_comment.parent = get_object_or_404(model, id = int(parent_id))
95
if model == ThreadedComment:
97
request.user.message_set.create(message="Your message has been posted successfully.")
99
request.session['successful_data'] = {
100
'name' : form.cleaned_data['name'],
101
'website' : form.cleaned_data['website'],
102
'email' : form.cleaned_data['email'],
105
return JSONResponse([new_comment,])
107
return XMLResponse([new_comment,])
109
return HttpResponseRedirect(_get_next(request))
111
return JSONResponse({'errors' : form.errors}, is_iterable=False)
115
{% for error,name in errors %}
116
<field name="{{ name }}">
117
{% for suberror in error %}<error>{{ suberror }}</error>{% endfor %}
122
response_str = Template(template_str).render(Context({'errors' : zip(form.errors.values(), form.errors.keys())}))
123
return XMLResponse(response_str, is_iterable=False)
125
return _preview(request, context_processors, extra_context, form_class=form_class)
127
def comment(*args, **kwargs):
129
Thin wrapper around free_comment which adds login_required status and also assigns
130
the ``model`` to be ``ThreadedComment``.
132
kwargs['model'] = ThreadedComment
133
kwargs['form_class'] = ThreadedCommentForm
134
return free_comment(*args, **kwargs)
135
# Require login to be required, as request.user must exist and be valid.
136
comment = login_required(comment)
138
def can_delete_comment(comment, user):
140
Default callback function to determine wether the given user has the
141
ability to delete the given comment.
143
if user.is_staff or user.is_superuser:
145
if hasattr(comment, 'user') and comment.user == user:
149
def comment_delete(request, object_id, model=ThreadedComment, extra_context = {}, context_processors = [], permission_callback=can_delete_comment):
151
Deletes the specified comment, which can be either a ``FreeThreadedComment`` or a
152
``ThreadedComment``. If it is a POST request, then the comment will be deleted
153
outright, however, if it is a GET request, a confirmation page will be shown.
155
tc = get_object_or_404(model, id=int(object_id))
156
if not permission_callback(tc, request.user):
157
login_url = settings.LOGIN_URL
158
current_url = urlquote(request.get_full_path())
159
return HttpResponseRedirect("%s?next=%s" % (login_url, current_url))
160
if request.method == "POST":
162
return HttpResponseRedirect(_get_next(request))
164
if model == ThreadedComment:
165
is_free_threaded_comment = False
166
is_threaded_comment = True
168
is_free_threaded_comment = True
169
is_threaded_comment = False
170
return render_to_response(
171
'threadedcomments/confirm_delete.html',
173
context_instance = RequestContext(
177
'is_free_threaded_comment' : is_free_threaded_comment,
178
'is_threaded_comment' : is_threaded_comment,
179
'next' : _get_next(request),
b'\\ No newline at end of file'