from django.core.paginator import EmptyPage from django.db import transaction from django.http import Http404 from django.shortcuts import render, redirect from django.urls import reverse 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, \ SETTING_ONLY_FAVORITES from boards.forms import ThreadForm, PlainErrorList from boards.models import Post, Thread, Ban from boards.views.banned import BannedView from boards.views.base import BaseBoardView, CONTEXT_FORM from boards.views.mixins import FileUploadMixin, PaginatedMixin, \ DispatcherMixin, PARAMETER_METHOD from boards.views.posting_mixin import PostMixin 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_ADDITIONAL = 'additional_params' PARAMETER_MAX_FILE_SIZE = 'max_file_size' PARAMETER_RSS_URL = 'rss_url' PARAMETER_MAX_FILES = 'max_files' TEMPLATE = 'boards/all_threads.html' DEFAULT_PAGE = 1 FORM_TAGS = 'tags' class AllThreadsView(PostMixin, FileUploadMixin, BaseBoardView, PaginatedMixin, DispatcherMixin): tag_name = '' 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, initial={FORM_TAGS: self.tag_name}) 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(replies__opening=True)\ .order_by('-replies__pub_time') filter = request.GET.get('filter') 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_MAX_FILE_SIZE] = self.get_max_upload_size() params[PARAMETER_RSS_URL] = self.get_rss_url() params[PARAMETER_MAX_FILES] = settings.get_int('Forms', 'MaxFileCount') paginator.set_url(self.get_reverse_url(), request.GET.dict()) params.update(self.get_page_context(paginator, page)) return render(request, TEMPLATE, params) @method_decorator(csrf_protect) def post(self, request): if PARAMETER_METHOD in request.POST: self.dispatch_method(request) return redirect('index') # FIXME Different for different modes 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_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] files = form.get_files() file_urls = form.get_file_urls() images = form.get_images() text = self._remove_invalid_links(text) tags = data[FORM_TAGS] monochrome = form.is_monochrome() stickerpack = form.is_stickerpack() post = Post.objects.create_post(title=title, text=text, files=files, ip=ip, tags=tags, tripcode=form.get_tripcode(), monochrome=monochrome, images=images, file_urls=file_urls, stickerpack=stickerpack) if form.is_subscribe(): settings_manager = get_settings_manager(request) settings_manager.add_or_read_fav_thread(post) if html_response: return redirect(post.get_absolute_url()) def get_threads(self): """ Gets list of threads that will be shown on a page. """ threads = Thread.objects\ .exclude(tags__in=self.settings_manager.get_hidden_tags()) if self.settings_manager.get_setting(SETTING_ONLY_FAVORITES): fav_tags = self.settings_manager.get_fav_tags() if len(fav_tags) > 0: threads = threads.filter(tags__in=fav_tags) return threads def get_rss_url(self): return self.get_reverse_url() + 'rss/' def toggle_fav(self, request): settings_manager = get_settings_manager(request) settings_manager.set_setting(SETTING_ONLY_FAVORITES, not settings_manager.get_setting(SETTING_ONLY_FAVORITES, False))