from django.contrib import messages from django.db.transaction import atomic from django.http import JsonResponse from django.shortcuts import redirect from django.utils import html from django.utils.translation import ugettext as _ from django.views.generic import View from misago.core.errorpages import not_allowed from misago.core.exceptions import AjaxError from misago.forums.lists import get_forum_path from misago.threads import goto from misago.threads.posting import (PostingInterrupt, EditorFormset, START, REPLY, EDIT) from misago.threads.models import Thread, Post, Label from misago.threads.permissions import (allow_start_thread, allow_reply_thread, allow_edit_post) from misago.threads.views.generic.base import ViewBase __all__ = ['PostingView'] class PostingView(ViewBase): """ Basic view for starting/replying/editing """ template = 'misago/posting/formset.html' def find_mode(self, request, *args, **kwargs): """ First step: guess from request what kind of view we are """ is_submit = request.method == 'POST' and 'submit' in request.POST if is_submit: request.user.lock() forum = None thread = None post = None if 'post_id' in kwargs: post = self.get_post(request, lock=is_submit, **kwargs) forum = post.forum thread = post.thread elif 'thread_id' in kwargs: thread = self.get_thread(request, lock=is_submit, **kwargs) forum = thread.forum else: forum = self.get_forum(request, lock=is_submit, **kwargs) if thread: if post: mode = EDIT else: mode = REPLY else: mode = START thread = Thread(forum=forum) if not post: post = Post(forum=forum, thread=thread) return mode, forum, thread, post def allow_mode(self, user, mode, forum, thread, post): """ Second step: check start/reply/edit permissions """ if mode == START: self.allow_start(user, forum) if mode == REPLY: self.allow_reply(user, thread) if mode == EDIT: self.allow_edit(user, post) def allow_start(self, user, forum): allow_start_thread(user, forum) def allow_reply(self, user, thread): allow_reply_thread(user, thread) def allow_edit(self, user, post): allow_edit_post(user, post) def dispatch(self, request, *args, **kwargs): if not request.is_ajax(): return not_allowed(request) if request.method == 'POST': with atomic(): return self.real_dispatch(request, *args, **kwargs) else: return self.real_dispatch(request, *args, **kwargs) def real_dispatch(self, request, *args, **kwargs): mode_context = self.find_mode(request, *args, **kwargs) self.allow_mode(request.user, *mode_context) mode, forum, thread, post = mode_context forum.labels = Label.objects.get_forum_labels(forum) formset = EditorFormset(request=request, mode=mode, user=request.user, forum=forum, thread=thread, post=post) if request.method == 'POST': if 'submit' in request.POST: if formset.is_valid(): try: formset.save() return self.handle_submit(request, formset) except PostingInterrupt as e: return JsonResponse({'interrupt': e.message}) else: return JsonResponse({'errors': formset.errors}) if 'preview' in request.POST: formset.update() return JsonResponse({'preview': formset.post.parsed}) return self.render(request, { 'mode': mode, 'formset': formset, 'forms': formset.get_forms_list(), 'main_forms': formset.get_main_forms(), 'supporting_forms': formset.get_supporting_forms(), 'forum': forum, 'path': get_forum_path(forum), 'thread': thread, 'post': post, 'api_url': request.path }) def handle_submit(self, request, formset): mode, forum, thread, post = (formset.mode, formset.forum, formset.thread, formset.post) if mode == EDIT: message = _("Changes saved.") else: if mode == START: message = _("New thread was posted.") if mode == REPLY: message = _("Your reply was posted.") messages.success(request, message) posts_qs = self.exclude_invisible_posts(thread.post_set, request.user, forum, thread) post_url = goto.post(thread, posts_qs, post) return JsonResponse({ 'message': message, 'post_url': post_url, 'parsed': post.parsed, 'original': post.original, 'title': thread.title, 'title_escaped': html.escape(thread.title), })