annotate gpp/messages/views.py @ 407:42a4e66972d5

Trying to fix #200; found a bug in the get_forum_unread_status() function. Added some db indexes.
author Brian Neal <bgneal@gmail.com>
date Fri, 01 Apr 2011 01:18:44 +0000
parents c8c0fa817a05
children
rev   line source
gremmie@1 1 """Views for the messages application"""
gremmie@1 2
bgneal@371 3 import collections
gremmie@1 4 import datetime
bgneal@371 5
gremmie@1 6 from django.shortcuts import render_to_response
gremmie@1 7 from django.template import RequestContext
gremmie@1 8 from django.http import HttpResponseRedirect
gremmie@1 9 from django.contrib.auth.decorators import login_required
bgneal@178 10 from django.contrib import messages
gremmie@1 11 from django.shortcuts import get_object_or_404
gremmie@1 12 from django.core.urlresolvers import reverse
gremmie@1 13 from django.http import Http404
bgneal@156 14 from django.views.decorators.http import require_POST
gremmie@1 15
gremmie@1 16 from messages.models import Message
gremmie@1 17 from messages.models import Options
gremmie@1 18 from messages.forms import ComposeForm
gremmie@1 19 from messages.forms import OptionsForm
gremmie@1 20 from messages.utils import reply_subject
gremmie@1 21 from messages.utils import quote_message
gremmie@1 22
gremmie@1 23
gremmie@1 24 BOX_MAP = {
gremmie@1 25 'inbox': 'messages-inbox',
gremmie@1 26 'outbox': 'messages-outbox',
gremmie@1 27 'trash': 'messages-trash',
gremmie@1 28 }
gremmie@1 29
bgneal@371 30 MSG_DELETED, MSG_TRASHED, MSG_ERROR = range(3)
bgneal@371 31
gremmie@1 32
gremmie@1 33 def box_redirect(request):
gremmie@1 34 """
gremmie@1 35 Determines which box to redirect to by looking for a GET or
gremmie@1 36 POST parameter.
gremmie@1 37 """
gremmie@1 38 if request.method == 'GET':
gremmie@1 39 box = request.GET.get('box', 'inbox')
gremmie@1 40 else:
gremmie@1 41 box = request.POST.get('box', 'inbox')
gremmie@1 42 if BOX_MAP.has_key(box):
gremmie@1 43 url = reverse(BOX_MAP[box])
gremmie@1 44 else:
gremmie@1 45 url = reverse(BOX_MAP['inbox'])
gremmie@1 46 return HttpResponseRedirect(url)
gremmie@1 47
gremmie@1 48
gremmie@1 49 @login_required
gremmie@1 50 def inbox(request):
gremmie@1 51 """Displays the inbox for the user making the request."""
gremmie@1 52 msgs = Message.objects.inbox(request.user)
gremmie@1 53 return render_to_response('messages/inbox.html', {
gremmie@1 54 'msgs': msgs,
bgneal@371 55 },
gremmie@1 56 context_instance = RequestContext(request))
gremmie@1 57
gremmie@1 58
gremmie@1 59 @login_required
gremmie@1 60 def outbox(request):
gremmie@1 61 """Displays the outbox for the user making the request."""
gremmie@1 62 msgs = Message.objects.outbox(request.user)
gremmie@1 63 return render_to_response('messages/outbox.html', {
gremmie@1 64 'msgs': msgs,
bgneal@371 65 },
gremmie@1 66 context_instance = RequestContext(request))
gremmie@1 67
gremmie@1 68
gremmie@1 69 @login_required
gremmie@1 70 def trash(request):
gremmie@1 71 """Displays the trash for the user making the request."""
gremmie@1 72 msgs = Message.objects.trash(request.user)
gremmie@1 73 return render_to_response('messages/trash.html', {
gremmie@1 74 'msgs': msgs,
bgneal@371 75 },
gremmie@1 76 context_instance = RequestContext(request))
gremmie@1 77
gremmie@1 78
gremmie@1 79 @login_required
gremmie@1 80 def view(request, msg_id):
gremmie@1 81 """
gremmie@1 82 View a given message. Only the sender or receiver can see
gremmie@1 83 the message.
gremmie@1 84 """
gremmie@1 85 msg = get_object_or_404(Message, pk=msg_id)
gremmie@1 86 if msg.sender != request.user and msg.receiver != request.user:
gremmie@1 87 raise Http404
gremmie@1 88
gremmie@1 89 if msg.receiver == request.user and msg.read_date is None:
gremmie@1 90 msg.read_date = datetime.datetime.now()
gremmie@1 91 msg.save()
gremmie@1 92
gremmie@1 93 box = request.GET.get('box', None)
gremmie@1 94
gremmie@1 95 return render_to_response('messages/view.html', {
gremmie@1 96 'box': box,
gremmie@1 97 'msg': msg,
gremmie@1 98 'is_deleted': msg.is_deleted(request.user),
bgneal@371 99 },
gremmie@1 100 context_instance = RequestContext(request))
gremmie@1 101
gremmie@1 102
gremmie@1 103 @login_required
gremmie@1 104 def reply(request, msg_id):
gremmie@1 105 """
gremmie@1 106 Process or prepare the compose form in order to reply
gremmie@1 107 to a given message.
gremmie@1 108 """
gremmie@1 109 msg = get_object_or_404(Message, pk=msg_id)
gremmie@1 110
gremmie@1 111 if request.method == "POST":
gremmie@1 112 if request.POST.get('submit_button', 'Cancel') == 'Cancel':
gremmie@1 113 return box_redirect(request)
gremmie@1 114 compose_form = ComposeForm(request.user, request.POST)
gremmie@1 115 if compose_form.is_valid():
gremmie@1 116 compose_form.save(sender=request.user, parent_msg=msg)
bgneal@178 117 messages.success(request, 'Reply sent.')
gremmie@1 118 return box_redirect(request)
gremmie@1 119 else:
gremmie@1 120 if msg.receiver == request.user:
gremmie@1 121 receiver_name = msg.sender.username
gremmie@1 122 else:
gremmie@1 123 # replying to message in outbox
gremmie@1 124 receiver_name = msg.receiver.username
gremmie@1 125
gremmie@1 126 form_data = {
gremmie@1 127 'receiver': receiver_name,
gremmie@1 128 'subject': reply_subject(msg.subject),
gremmie@1 129 'message': quote_message(msg.sender, msg.send_date, msg.message),
gremmie@1 130 'box': request.GET.get('box', 'inbox'),
gremmie@1 131 }
gremmie@1 132
gremmie@1 133 compose_form = ComposeForm(request.user, initial=form_data)
gremmie@1 134
gremmie@1 135 return render_to_response('messages/compose.html', {
gremmie@1 136 'compose_form': compose_form,
bgneal@371 137 },
gremmie@1 138 context_instance = RequestContext(request))
gremmie@1 139
gremmie@1 140
gremmie@1 141 @login_required
gremmie@1 142 def compose(request, receiver=None):
gremmie@1 143 """
gremmie@1 144 Process or prepare the compose form in order to create
gremmie@1 145 a new message.
gremmie@1 146 """
gremmie@1 147 if request.method == "POST":
gremmie@1 148 if request.POST.get('submit_button', 'Cancel') == 'Cancel':
gremmie@1 149 return HttpResponseRedirect(reverse('messages-inbox'))
gremmie@1 150 compose_form = ComposeForm(request.user, request.POST)
gremmie@1 151 if compose_form.is_valid():
gremmie@1 152 compose_form.save(sender=request.user)
bgneal@178 153 messages.success(request, 'Message sent.')
gremmie@1 154 return HttpResponseRedirect(reverse('messages-inbox'))
gremmie@1 155 else:
gremmie@1 156 if receiver is not None:
gremmie@1 157 form_data = {
gremmie@1 158 'receiver': receiver,
gremmie@1 159 }
gremmie@1 160 compose_form = ComposeForm(request.user, initial=form_data)
gremmie@1 161 else:
gremmie@1 162 compose_form = ComposeForm(request.user)
gremmie@1 163
gremmie@1 164 return render_to_response('messages/compose.html', {
gremmie@1 165 'compose_form': compose_form,
bgneal@371 166 },
gremmie@1 167 context_instance = RequestContext(request))
gremmie@1 168
gremmie@1 169
bgneal@371 170 def _delete_message(user, msg):
bgneal@371 171 """
bgneal@371 172 Deletes a given message. The user must be either the sender or
bgneal@371 173 receiver for this to succeed.
bgneal@371 174 If both parties have deleted the message, it is deleted from the
bgneal@371 175 database. If only one party has deleted the message, the message
bgneal@371 176 is just sent to the trash.
bgneal@371 177
bgneal@371 178 Returns MSG_DELETED, MSG_TRASHED, or MSG_ERROR to indicate what
bgneal@371 179 action was performed.
bgneal@371 180
bgneal@371 181 """
bgneal@371 182 if msg.sender == user:
bgneal@371 183 if (msg.receiver_delete_date is not None or
bgneal@371 184 msg.read_date is None):
bgneal@371 185 # Both parties deleted the message or receiver hasn't read it yet,
bgneal@371 186 # we can delete it now
bgneal@371 187 msg.delete()
bgneal@371 188 return MSG_DELETED
bgneal@371 189 else:
bgneal@371 190 # receiver still has it in inbox
bgneal@371 191 msg.sender_delete_date = datetime.datetime.now()
bgneal@371 192 msg.save()
bgneal@371 193 return MSG_TRASHED
bgneal@371 194
bgneal@371 195 elif msg.receiver == user:
bgneal@371 196 if msg.sender_delete_date is not None:
bgneal@371 197 # both parties deleted the message, we can delete it now
bgneal@371 198 msg.delete()
bgneal@371 199 return MSG_DELETED
bgneal@371 200 else:
bgneal@371 201 # sender still has it in the outbox
bgneal@371 202 msg.receiver_delete_date = datetime.datetime.now()
bgneal@371 203 msg.save()
bgneal@371 204 return MSG_TRASHED
bgneal@371 205
bgneal@371 206 return MSG_ERROR
bgneal@371 207
bgneal@371 208
gremmie@1 209 @login_required
bgneal@156 210 @require_POST
gremmie@1 211 def delete(request, msg_id):
gremmie@1 212 """
gremmie@1 213 Deletes a given message. The user must be either the sender or
gremmie@1 214 receiver for this to succeed.
gremmie@1 215 """
gremmie@1 216 msg = get_object_or_404(Message, pk=msg_id)
bgneal@371 217 result = _delete_message(request.user, msg)
bgneal@371 218 if result == MSG_DELETED:
bgneal@371 219 messages.success(request, 'Message deleted.')
bgneal@371 220 elif result == MSG_TRASHED:
bgneal@371 221 messages.success(request, 'Message sent to trash.')
gremmie@1 222 else:
bgneal@371 223 messages.error(request, 'Error deleting message.')
gremmie@1 224
gremmie@1 225 return box_redirect(request)
gremmie@1 226
gremmie@1 227
gremmie@1 228 @login_required
gremmie@1 229 def delete_bulk(request):
gremmie@1 230 """
gremmie@1 231 Deletes messages in bulk. The message ID's to be deleted are expected
gremmie@1 232 to be in the delete POST array. The user must be either the sender
gremmie@1 233 or receiver for this to succeed.
gremmie@1 234 """
gremmie@1 235 if request.method == "POST":
gremmie@1 236 delete_ids = request.POST.getlist('delete_ids')
gremmie@1 237 try:
gremmie@1 238 delete_ids = [int(id) for id in delete_ids]
gremmie@1 239 except ValueError:
gremmie@1 240 raise Http404
bgneal@371 241
bgneal@371 242 msgs = Message.objects.filter(id__in=delete_ids)
bgneal@371 243
bgneal@371 244 counts = collections.defaultdict(int)
gremmie@1 245 for msg in msgs:
bgneal@371 246 result = _delete_message(request.user, msg)
bgneal@371 247 counts[result] += 1
bgneal@371 248
bgneal@371 249 if counts[MSG_DELETED]:
bgneal@371 250 messages.success(request, 'Messages deleted: %d' % counts[MSG_DELETED])
bgneal@371 251 if counts[MSG_TRASHED]:
bgneal@371 252 messages.success(request, 'Messages sent to trash: %d' % counts[MSG_TRASHED])
bgneal@371 253 if counts[MSG_ERROR]:
bgneal@371 254 messages.error(request, 'Message errors: %d' % counts[MSG_ERROR])
gremmie@1 255
gremmie@1 256 return box_redirect(request)
gremmie@1 257
gremmie@1 258
gremmie@1 259 @login_required
bgneal@156 260 @require_POST
gremmie@1 261 def undelete(request, msg_id):
gremmie@1 262 """
gremmie@1 263 Undeletes a given message. The user must be either the sender or
gremmie@1 264 receiver for this to succeed.
gremmie@1 265 """
gremmie@1 266 msg = get_object_or_404(Message, pk=msg_id)
gremmie@1 267 if msg.sender == request.user:
gremmie@1 268 msg.sender_delete_date = None
gremmie@1 269 elif msg.receiver == request.user:
gremmie@1 270 msg.receiver_delete_date = None
gremmie@1 271 else:
gremmie@1 272 raise Http404
gremmie@1 273 msg.save()
bgneal@178 274 messages.success(request, 'Message retrieved from the trash.')
gremmie@1 275
gremmie@1 276 return box_redirect(request)
gremmie@1 277
gremmie@1 278
gremmie@1 279 @login_required
gremmie@1 280 def undelete_bulk(request):
gremmie@1 281 """
gremmie@1 282 Undeletes messages in bulk. The message ID's to be deleted are expected
gremmie@1 283 to be in the delete POST array. The user must be either the sender
gremmie@1 284 or receiver for this to succeed.
gremmie@1 285 """
gremmie@1 286 if request.method == "POST":
gremmie@1 287 undelete_ids = request.POST.getlist('undelete_ids')
gremmie@1 288 try:
gremmie@1 289 undelete_ids = [int(id) for id in undelete_ids]
gremmie@1 290 except ValueError:
gremmie@1 291 raise Http404
gremmie@1 292 msgs = Message.objects.filter(id__in = undelete_ids)
gremmie@1 293 for msg in msgs:
gremmie@1 294 if msg.sender == request.user:
gremmie@1 295 msg.sender_delete_date = None
gremmie@1 296 msg.save()
gremmie@1 297 elif msg.receiver == request.user:
gremmie@1 298 msg.receiver_delete_date = None
gremmie@1 299 msg.save()
bgneal@178 300 messages.success(request, 'Messages retrieved from the trash.')
gremmie@1 301
gremmie@1 302 return box_redirect(request)
gremmie@1 303
gremmie@1 304
gremmie@1 305 @login_required
gremmie@1 306 def options(request):
gremmie@1 307 """
gremmie@1 308 View to display/change user options.
gremmie@1 309 """
gremmie@1 310 if request.method == "POST":
gremmie@1 311 if request.POST.get('submit_button', 'Cancel') == 'Cancel':
gremmie@1 312 return HttpResponseRedirect(reverse('messages-inbox'))
gremmie@1 313 options = Options.objects.for_user(request.user)
gremmie@1 314 form = OptionsForm(request.POST, instance=options)
gremmie@1 315 if form.is_valid():
gremmie@1 316 form.save()
bgneal@178 317 messages.success(request, 'Options saved.')
gremmie@1 318 return HttpResponseRedirect(reverse('messages-inbox'))
gremmie@1 319 else:
gremmie@1 320 try:
gremmie@1 321 options = Options.objects.for_user(request.user)
gremmie@1 322 except:
gremmie@1 323 options = Options()
gremmie@1 324 options.user = request.user
gremmie@1 325 options.save()
gremmie@1 326
gremmie@1 327 form = OptionsForm(instance=options)
gremmie@1 328
gremmie@1 329 return render_to_response('messages/options.html', {
gremmie@1 330 'form': form,
bgneal@371 331 },
gremmie@1 332 context_instance = RequestContext(request))
gremmie@1 333