posting.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from django.contrib import messages
  2. from django.db.transaction import atomic
  3. from django.http import JsonResponse
  4. from django.shortcuts import redirect, render
  5. from django.utils import html
  6. from django.utils.translation import ugettext as _
  7. from django.views.generic import View
  8. from misago.core.exceptions import AjaxError
  9. from misago.forums.lists import get_forum_path
  10. from misago.threads import goto
  11. from misago.threads.posting import (PostingInterrupt, EditorFormset,
  12. START, REPLY, EDIT)
  13. from misago.threads.models import Thread, Post, Label
  14. from misago.threads.permissions import (allow_start_thread, allow_reply_thread,
  15. allow_edit_post)
  16. from misago.threads.views.generic.base import ViewBase
  17. __all__ = ['PostingView']
  18. class PostingView(ViewBase):
  19. """
  20. Basic view for starting/replying/editing
  21. """
  22. template = 'misago/posting/formset.html'
  23. def find_mode(self, request, *args, **kwargs):
  24. """
  25. First step: guess from request what kind of view we are
  26. """
  27. is_submit = request.method == 'POST' and 'submit' in request.POST
  28. if is_submit:
  29. request.user.lock()
  30. forum = None
  31. thread = None
  32. post = None
  33. if 'post_id' in kwargs:
  34. post = self.get_post(request, lock=is_submit, **kwargs)
  35. forum = post.forum
  36. thread = post.thread
  37. elif 'thread_id' in kwargs:
  38. thread = self.get_thread(request, lock=is_submit, **kwargs)
  39. forum = thread.forum
  40. else:
  41. forum = self.get_forum(request, lock=is_submit, **kwargs)
  42. if thread:
  43. if post:
  44. mode = EDIT
  45. else:
  46. mode = REPLY
  47. else:
  48. mode = START
  49. thread = Thread(forum=forum)
  50. if not post:
  51. post = Post(forum=forum, thread=thread)
  52. return mode, forum, thread, post
  53. def allow_mode(self, user, mode, forum, thread, post):
  54. """
  55. Second step: check start/reply/edit permissions
  56. """
  57. if mode == START:
  58. self.allow_start(user, forum)
  59. if mode == REPLY:
  60. self.allow_reply(user, thread)
  61. if mode == EDIT:
  62. self.allow_edit(user, post)
  63. def allow_start(self, user, forum):
  64. allow_start_thread(user, forum)
  65. def allow_reply(self, user, thread):
  66. allow_reply_thread(user, thread)
  67. def allow_edit(self, user, post):
  68. allow_edit_post(user, post)
  69. def dispatch(self, request, *args, **kwargs):
  70. if request.method == 'POST':
  71. with atomic():
  72. return self.real_dispatch(request, *args, **kwargs)
  73. else:
  74. return self.real_dispatch(request, *args, **kwargs)
  75. def real_dispatch(self, request, *args, **kwargs):
  76. mode_context = self.find_mode(request, *args, **kwargs)
  77. self.allow_mode(request.user, *mode_context)
  78. mode, forum, thread, post = mode_context
  79. if not request.is_ajax():
  80. response = render(request, 'misago/errorpages/wrong_way.html')
  81. response.status_code = 405
  82. return response
  83. forum.labels = Label.objects.get_forum_labels(forum)
  84. formset = EditorFormset(request=request,
  85. mode=mode,
  86. user=request.user,
  87. forum=forum,
  88. thread=thread,
  89. post=post)
  90. if request.method == 'POST':
  91. if 'submit' in request.POST:
  92. if formset.is_valid():
  93. try:
  94. formset.save()
  95. except PostingInterrupt as e:
  96. return JsonResponse({'interrupt': e.message})
  97. if mode == EDIT:
  98. message = _("Changes saved.")
  99. else:
  100. if mode == START:
  101. message = _("New thread was posted.")
  102. if mode == REPLY:
  103. message = _("Your reply was posted.")
  104. messages.success(request, message)
  105. posts_qs = self.exclude_invisible_posts(
  106. thread.post_set, request.user, forum, thread)
  107. post_url = goto.post(thread, posts_qs, post)
  108. return JsonResponse({
  109. 'message': message,
  110. 'post_url': post_url,
  111. 'parsed': post.parsed,
  112. 'original': post.original,
  113. 'title': thread.title,
  114. 'title_escaped': html.escape(thread.title),
  115. })
  116. else:
  117. return JsonResponse({'errors': formset.errors})
  118. if 'preview' in request.POST:
  119. formset.update()
  120. return JsonResponse({'preview': formset.post.parsed})
  121. return self.render(request, {
  122. 'mode': mode,
  123. 'formset': formset,
  124. 'forms': formset.get_forms_list(),
  125. 'main_forms': formset.get_main_forms(),
  126. 'supporting_forms': formset.get_supporting_forms(),
  127. 'forum': forum,
  128. 'path': get_forum_path(forum),
  129. 'thread': thread,
  130. 'post': post,
  131. 'api_url': request.path
  132. })