from django.core.urlresolvers import reverse from django.core.files import File from django.core.files.temp import NamedTemporaryFile from django.core.paginator import EmptyPage from django.db import transaction from django.http import Http404 from django.shortcuts import render, redirect from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_protect from boards import utils, settings from boards.abstracts.paginator import get_paginator from boards.abstracts.settingsmanager import get_settings_manager from boards.forms import ThreadForm, PlainErrorList from boards.models import Post, Thread, Ban, Banner from boards.views.banned import BannedView from boards.views.base import BaseBoardView, CONTEXT_FORM from boards.views.posting_mixin import PostMixin from boards.views.mixins import FileUploadMixin, PaginatedMixin FORM_TAGS = 'tags' FORM_TEXT = 'text' FORM_TITLE = 'title' FORM_IMAGE = 'image' FORM_THREADS = 'threads' TAG_DELIMITER = ' ' PARAMETER_CURRENT_PAGE = 'current_page' PARAMETER_PAGINATOR = 'paginator' PARAMETER_THREADS = 'threads' PARAMETER_BANNERS = 'banners' PARAMETER_ADDITIONAL = 'additional_params' PARAMETER_MAX_FILE_SIZE = 'max_file_size' PARAMETER_RSS_URL = 'rss_url' TEMPLATE = 'boards/all_threads.html' DEFAULT_PAGE = 1 class AllThreadsView(PostMixin, FileUploadMixin, BaseBoardView, PaginatedMixin): def __init__(self): self.settings_manager = None super(AllThreadsView, self).__init__() @method_decorator(csrf_protect) def get(self, request, form: ThreadForm=None): page = request.GET.get('page', DEFAULT_PAGE) params = self.get_context_data(request=request) if not form: form = ThreadForm(error_class=PlainErrorList) self.settings_manager = get_settings_manager(request) threads = self.get_threads() order = request.GET.get('order', 'bump') if order == 'bump': threads = threads.order_by('-bump_time') else: threads = threads.filter(multi_replies__opening=True).order_by('-multi_replies__pub_time') filter = request.GET.get('filter') if filter == 'fav_tags': fav_tags = self.settings_manager.get_fav_tags() if len(fav_tags) > 0: threads = threads.filter(tags__in=fav_tags) threads = threads.distinct() paginator = get_paginator(threads, settings.get_int('View', 'ThreadsPerPage')) paginator.current_page = int(page) try: threads = paginator.page(page).object_list except EmptyPage: raise Http404() params[PARAMETER_THREADS] = threads params[CONTEXT_FORM] = form params[PARAMETER_BANNERS] = Banner.objects.order_by('-id').all() params[PARAMETER_MAX_FILE_SIZE] = self.get_max_upload_size() params[PARAMETER_RSS_URL] = self.get_rss_url() paginator.set_url(self.get_reverse_url(), request.GET.dict()) self.get_page_context(paginator, params, page) return render(request, TEMPLATE, params) @method_decorator(csrf_protect) def post(self, request): form = ThreadForm(request.POST, request.FILES, error_class=PlainErrorList) form.session = request.session if form.is_valid(): return self.create_thread(request, form) if form.need_to_ban: # Ban user because he is suspected to be a bot self._ban_current_user(request) return self.get(request, form) def get_page_context(self, paginator, params, page): """ Get pagination context variables """ params[PARAMETER_PAGINATOR] = paginator current_page = paginator.page(int(page)) params[PARAMETER_CURRENT_PAGE] = current_page self.set_page_urls(paginator, params) def get_reverse_url(self): return reverse('index') @transaction.atomic def create_thread(self, request, form: ThreadForm, html_response=True): """ Creates a new thread with an opening post. """ ip = utils.get_client_ip(request) is_banned = Ban.objects.filter(ip=ip).exists() if is_banned: if html_response: return redirect(BannedView().as_view()) else: return data = form.cleaned_data title = form.get_title() text = data[FORM_TEXT] file = form.get_file() threads = data[FORM_THREADS] images = form.get_images() text = self._remove_invalid_links(text) tags = data[FORM_TAGS] monochrome = form.is_monochrome() post = Post.objects.create_post(title=title, text=text, file=file, ip=ip, tags=tags, opening_posts=threads, tripcode=form.get_tripcode(), monochrome=monochrome, images=images) # This is required to update the threads to which posts we have replied # when creating this one post.notify_clients() if html_response: return redirect(post.get_absolute_url()) def get_threads(self): """ Gets list of threads that will be shown on a page. """ return Thread.objects\ .exclude(tags__in=self.settings_manager.get_hidden_tags()) def get_rss_url(self): return self.get_reverse_url() + 'rss/'