def post(self, request): reference = request.POST.get("reference") == "yes" target_topic = request.POST.get("target_topic", "").strip() from_date = parse_date_or_none(request.POST.get("from_date")) to_date = parse_date_or_none(request.POST.get("to_date")) try: target_topic = Topic.objects.get(title=target_topic) generic_superuser = get_generic_superuser() topic_list_raw = list(self.get_object_list()) entries_list = Entry.objects_published.filter( topic__in=topic_list_raw) if from_date: entries_list = entries_list.filter(date_created__gte=from_date) if to_date: entries_list = entries_list.filter(date_created__lte=to_date) entries_count = entries_list.count() entries_list.update( topic=target_topic) # Bulk update, does not call save() target_topic.register_wishes() # Include an informative entry on old topic to indicate the new topic if reference: bulk_list = [ Entry( topic=obj, content= f"({pgettext('editor', 'see')}: {target_topic.title})", author=generic_superuser, ) for obj in topic_list_raw ] Entry.objects.bulk_create(bulk_list) # Admin log log_admin( f"TopicMove action, count: {entries_count}. sources->{topic_list_raw}," f"from->{from_date} to->{to_date}", request.user, Topic, target_topic, ) notifications.success( request, ngettext("%(count)d entry was transferred", "%(count)d entries were transferred", entries_count) % {"count": entries_count}, ) except Topic.DoesNotExist: notifications.error(request, gettext("Couldn't find the target topic.")) except Author.DoesNotExist: notifications.error(request, gettext("GENERIC_SUPERUSER is missing?")) return redirect(self.get_changelist_url())
def search(self, user, search_keys): """ The logic of advanced search feature. Notice: Entry counts given in accordance with search filters, it may not be the count of ALL entries. """ keywords = search_keys.get("keywords") author_nick = search_keys.get("author_nick") favorites_only = search_keys.get("is_in_favorites") == "true" nice_only = search_keys.get("is_nice_ones") == "true" from_date = search_keys.get("from_date") to_date = search_keys.get("to_date") ordering = search_keys.get("ordering") # Input validation from_date = parse_date_or_none(from_date, dayfirst=False) to_date = parse_date_or_none(to_date, dayfirst=False) if ordering not in ("alpha", "newer", "popular"): ordering = "newer" # Provide a default search term if none present if not keywords and not author_nick and not (favorites_only and user.is_authenticated): # Translators: This is the default keyword to search when users search with no input. keywords = _("common sense") filters = {} # Filtering if favorites_only and user.is_authenticated: filters["entries__favorited_by"] = user if nice_only: filters["entries__vote_rate__gte"] = Decimal("100") if author_nick: filters["entries__author__username"] = author_nick if keywords: filters["title__search" if connection.vendor == "postgresql" else "title__icontains"] = keywords if from_date: filters["entries__date_created__gte"] = from_date if to_date: filters["entries__date_created__lte"] = to_date ordering_map = {"alpha": ["title"], "newer": ["-date_created"], "popular": ["-count", "-date_created"]} qs = ( Topic.objects.values(*self.values) .filter(**self.base_filter, **filters) .annotate(count=Count("entries", distinct=True)) ) return qs.order_by(*ordering_map.get(ordering))[: settings.TOPICS_PER_PAGE_DEFAULT]
def generation(self): if settings.DISABLE_GENERATIONS: return None gen_start_date = parse_date_or_none(settings.FIRST_GENERATION_DATE) if gen_start_date is None: raise ValueError("Invalid configuration for 'FIRST_GENERATION_DATE'. Please provide a valid date.") delta = self.date_joined - gen_start_date return math.ceil((delta.days / settings.GENERATION_GAP_DAYS) or 1)
def post(self, request): time_choices = { "D1": timedelta(days=1), "W1": timedelta(days=7), "W2": timedelta(days=14), "M1": timedelta(days=30), "M3": timedelta(days=90), "PM": None, } choice = request.POST.get("suspension_time") if choice in time_choices.keys(): if choice == "PM": suspended_until = parse_date_or_none("01.01.2038") else: suspended_until = timezone.now() + time_choices[choice] # Evaluate it immediately because it needs to be iterated and we need to call len() user_list_raw = list(self.get_object_list()) # Get and parse information for suspension action_information = request.POST.get("information", gettext("No information was given.")) message_for_user = gettext( "your account has been suspended. administration message: %(message)s\n\n" "in your profile page, you can see the remaining time until your account gets reactivated." ) % {"message": action_information} message_for_log = f"Suspended until {suspended_until}, information: {action_information}" log_list = [] # Reserve list that hold instances for bulk creation generic_superuser = get_generic_superuser() # Set new suspended_until and append instances to reserved lists for user in user_list_raw: user.suspended_until = suspended_until log_list.append(logentry_instance(message_for_log, request.user, Author, user)) Message.objects.compose(generic_superuser, user, message_for_user) # Bulk creation/updates Author.objects.bulk_update(user_list_raw, ["suspended_until"]) # Update Author, does not call save() logentry_bulk_create(log_list) # Log user suspension for admin history count = len(user_list_raw) notifications.success( request, ngettext("%(count)d author was suspended.", "%(count)d authors were suspended.", count) % {"count": count}, ) else: notifications.error(request, gettext("The selected duration was invalid.")) return redirect(self.get_changelist_url())