From 3bd4ef57717387b30db5b89a7f8d0a56bed20b26 Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Fri, 15 Nov 2024 16:35:32 +0100 Subject: [PATCH] =?UTF-8?q?On=20s=C3=A9pare=20le=20code=20pour=20plus=20de?= =?UTF-8?q?=20lisibilit=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agenda_culturel/filters.py | 478 +++++++++++++++++++++++++++++++++ src/agenda_culturel/forms.py | 18 ++ src/agenda_culturel/views.py | 433 +---------------------------- 3 files changed, 505 insertions(+), 424 deletions(-) create mode 100644 src/agenda_culturel/filters.py diff --git a/src/agenda_culturel/filters.py b/src/agenda_culturel/filters.py new file mode 100644 index 0000000..00650df --- /dev/null +++ b/src/agenda_culturel/filters.py @@ -0,0 +1,478 @@ +import django_filters +from django.utils.translation import gettext_lazy as _ +from django import forms +from django.http import QueryDict + + +from django.forms import ( + ModelForm, + ValidationError, + TextInput, + Form, + URLField, + MultipleHiddenInput, + Textarea, + CharField, + ChoiceField, + RadioSelect, + MultipleChoiceField, + BooleanField, + HiddenInput, + ModelChoiceField, +) + +from .forms import ( + URLSubmissionForm, + EventForm, + BatchImportationForm, + FixDuplicates, + SelectEventInList, + MergeDuplicates, + RecurrentImportForm, + CategorisationRuleImportForm, + CategorisationForm, + EventAddPlaceForm, + PlaceForm, +) + +from .models import ( + ReferenceLocation, + RecurrentImport, + Tag, + Event, + Category, + ContactMessage, + DuplicatedEvents +) + + +class EventFilter(django_filters.FilterSet): + RECURRENT_CHOICES = [ + ("remove_recurrent", "Masquer les événements récurrents"), + ("only_recurrent", "Montrer uniquement les événements récurrents"), + ] + + DISTANCE_CHOICES = [5, 10, 15, 30] + + position = django_filters.ModelChoiceFilter( + label="À proximité de", + method="no_filter", + empty_label=_("Select a location"), + queryset=ReferenceLocation.objects.all().order_by("-main", "name__unaccent") + ) + + radius = django_filters.ChoiceFilter( + label="Dans un rayon de", + method="no_filter", + choices=[(x, str(x) + " km") for x in DISTANCE_CHOICES], + null_label=None, + empty_label=None + ) + + exclude_tags = django_filters.MultipleChoiceFilter( + label="Exclure les étiquettes", + choices=[], + lookup_expr="icontains", + field_name="tags", + exclude=True, + widget=forms.SelectMultiple, + ) + + tags = django_filters.MultipleChoiceFilter( + label="Inclure les étiquettes", + choices=[], + lookup_expr="icontains", + conjoined=True, + field_name="tags", + widget=forms.SelectMultiple, + ) + + recurrences = django_filters.ChoiceFilter( + label="Inclure la récurrence", + choices=RECURRENT_CHOICES, + method="filter_recurrences", + ) + + category = django_filters.ModelMultipleChoiceFilter( + label="Filtrer par catégories", + field_name="category__id", + to_field_name="id", + queryset=Category.objects.all(), + widget=MultipleHiddenInput, + ) + + + status = django_filters.MultipleChoiceFilter( + label="Filtrer par status", + choices=Event.STATUS.choices, + field_name="status", + widget=forms.CheckboxSelectMultiple, + ) + + class Meta: + model = Event + fields = ["category", "tags", "exclude_tags", "status", "recurrences"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not kwargs["request"].user.is_authenticated: + self.form.fields.pop("status") + self.form.fields["exclude_tags"].choices = Tag.get_tag_groups(exclude=True, nb_suggestions=0) + self.form.fields["tags"].choices = Tag.get_tag_groups(include=True) + + def filter_recurrences(self, queryset, name, value): + # construct the full lookup expression + lookup = "__".join([name, "isnull"]) + return queryset.filter(**{lookup: value == "remove_recurrent"}) + + def no_filter(self, queryset, name, value): + return queryset + + @property + def qs(self): + parent = super().qs + if self.get_cleaned_data("position") is None or self.get_cleaned_data("radius") is None: + return parent + d = self.get_cleaned_data("radius") + p = self.get_cleaned_data("position").location + return parent.exclude(exact_location=False).filter(exact_location__location__distance_lt=(p, D(km=d))) + + def get_url(self): + if isinstance(self.form.data, QueryDict): + return self.form.data.urlencode() + else: + return "" + + def get_full_url(self): + return self.request.get_full_path() + + def get_url_remove_categories(self, catpks, full_path = None): + if full_path is None: + full_path = self.request.get_full_path() + + result = full_path + for catpk in catpks: + result = result.replace('category=' + str(catpk), '') + result = result.replace('?&', '?') + result = result.replace('&&', '&') + return result + + def get_url_add_categories(self, catpks, full_path = None): + if full_path is None: + full_path = self.request.get_full_path() + + result = full_path + for catpk in catpks: + result = result + ('&' if '?' in full_path else '?') + 'category=' + str(catpk) + return result + + def get_url_without_filters_only_cats(self): + return self.get_url_without_filters(True) + + + def get_url_without_filters(self, only_categories=False): + + if only_categories: + # on repart d'une url sans option + result = self.request.get_full_path().split("?")[0] + # on ajoute toutes les catégories + result = self.get_url_add_categories([c.pk for c in self.get_categories()], result) + else: + # on supprime toutes les catégories + result = self.get_url_remove_categories([c.pk for c in self.get_categories()]) + + return result + + + def get_cleaned_data(self, name): + try: + return self.form.cleaned_data[name] + except AttributeError: + return {} + except KeyError: + return {} + + def get_categories(self): + return self.get_cleaned_data("category") + + def has_category(self): + return "category" in self.form.cleaned_data and len(self.get_cleaned_data("category")) > 0 + + def get_tags(self): + return self.get_cleaned_data("tags") + + def get_exclude_tags(self): + return self.get_cleaned_data("exclude_tags") + + def get_status(self): + return self.get_cleaned_data("status") + + def get_position(self): + return self.get_cleaned_data("position") + + def get_radius(self): + return self.get_cleaned_data("radius") + + def to_str(self, prefix=''): + self.form.full_clean() + result = ' '.join([c.name for c in self.get_categories()] + [t for t in self.get_tags()] + ["~" + t for t in self.get_exclude_tags()] + [str(self.get_position()), str(self.get_radius())]) + if len(result) > 0: + result = prefix + result + return result + + def get_status_names(self): + if "status" in self.form.cleaned_data: + return [ + dict(Event.STATUS.choices)[s] for s in self.get_cleaned_data("status") + ] + else: + return [] + + def get_recurrence_filtering(self): + if "recurrences" in self.form.cleaned_data: + d = dict(self.RECURRENT_CHOICES) + v = self.form.cleaned_data["recurrences"] + if v in d: + return d[v] + else: + return "" + else: + return "" + + + def is_resetable(self, only_categories=False): + if only_categories: + return len(self.get_cleaned_data("category")) != 0 + else: + if self.request.user.is_authenticated: + if ( + len(self.get_cleaned_data("status")) != 1 + or + self.get_cleaned_data("status")[0] != Event.STATUS.PUBLISHED + ): + return True + else: + if ( + len(self.get_cleaned_data("status")) != 0 + ): + return True + return ( + len(self.get_cleaned_data("tags")) != 0 + or len(self.get_cleaned_data("exclude_tags")) != 0 + or len(self.get_cleaned_data("recurrences")) != 0 + or ((not self.get_cleaned_data("position") is None) and (not self.get_cleaned_data("radius") is None)) + ) + + def is_active(self, only_categories=False): + if only_categories: + return len(self.get_cleaned_data("category")) != 0 + else: + return ( + len(self.get_cleaned_data("status")) != 0 + or len(self.get_cleaned_data("tags")) != 0 + or len(self.get_cleaned_data("exclude_tags")) != 0 + or len(self.get_cleaned_data("recurrences")) != 0 + or ((not self.get_cleaned_data("position") is None) and (not self.get_cleaned_data("radius") is None)) + ) + + def is_selected(self, cat): + return "category" in self.form.cleaned_data and cat in self.form.cleaned_data["category"] + + def is_selected_tag(self, tag): + return "tags" in self.form.cleaned_data and tag in self.form.cleaned_data["tags"] + + def get_url_add_tag(self, tag, category=None): + full_path = self.request.get_full_path() + + result = full_path + ('&' if '?' in full_path else '?') + 'tags=' + str(tag) + + if not category is None: + result = self.get_url_add_categories([category.pk], result) + return result + + def tag_exists(self, tag): + return tag in [t[0] for g in self.form.fields["tags"].choices for t in g[1]] + + def set_default_values(request): + if request.user.is_authenticated: + if request.GET.get('status', None) == None: + tempdict = request.GET.copy() + tempdict['status'] = 'published' + request.GET = tempdict + return request + return request + + def get_position_radius(self): + if self.get_cleaned_data("position") is None or self.get_cleaned_data("radius") is None: + return "" + else: + return str(self.get_cleaned_data("position")) + ' (' + str(self.get_cleaned_data("radius")) + ' km)' + + +class EventFilterAdmin(django_filters.FilterSet): + status = django_filters.MultipleChoiceFilter( + choices=Event.STATUS.choices, widget=forms.CheckboxSelectMultiple + ) + + representative = django_filters.MultipleChoiceFilter( + label=_("Representative version"), + choices=[(True, _("Yes")), (False, _("Non"))], + method="filter_by_representative", + widget=forms.CheckboxSelectMultiple) + + import_sources = django_filters.ModelChoiceFilter( + label=_("Imported from"), + method="filter_by_source", + queryset=RecurrentImport.objects.all().order_by("name__unaccent") + ) + + def filter_by_source(self, queryset, name, value): + src = RecurrentImport.objects.get(pk=value.pk).source + return queryset.filter(import_sources__contains=[src]) + + def filter_by_representative(self, queryset, name, value): + if value is None or len(value) != 1: + return queryset + else: + q = (Q(other_versions__isnull=True) | + Q(other_versions__representative=F('pk')) | + Q(other_versions__representative__isnull=True)) + if value[0] == True: + return queryset.filter(q) + else: + return queryset.exclude(q) + + + class Meta: + model = Event + fields = ["status"] + + +class ContactMessagesFilterAdmin(django_filters.FilterSet): + closed = django_filters.MultipleChoiceFilter( + label="Status", + choices=((True, _("Closed")), (False, _("Open"))), + widget=forms.CheckboxSelectMultiple, + ) + spam = django_filters.MultipleChoiceFilter( + label="Spam", + choices=((True, _("Spam")), (False, _("Non spam"))), + widget=forms.CheckboxSelectMultiple, + ) + + class Meta: + model = ContactMessage + fields = ["closed", "spam"] + + +class SimpleSearchEventFilter(django_filters.FilterSet): + q = django_filters.CharFilter(method="custom_filter", + label=_("Search"), + widget=forms.TextInput(attrs={"type": "search"}) + ) + + status = django_filters.MultipleChoiceFilter( + label="Filtrer par status", + choices=Event.STATUS.choices, + field_name="status", + widget=forms.CheckboxSelectMultiple, + ) + + def custom_filter(self, queryset, name, value): + search_query = SearchQuery(value, config="french") + qs = queryset.filter( + Q(title__icontains=value) + | Q(category__name__icontains=value) + | Q(tags__icontains=[value]) + | Q(exact_location__name__icontains=value) + | Q(description__icontains=value) + ) + for f in ["title", "category__name", "exact_location__name", "description"]: + params = { + f + + "_hl": SearchHeadline( + f, + search_query, + start_sel='', + stop_sel="", + config="french", + ) + } + qs = qs.annotate(**params) + return qs + + class Meta: + model = Event + fields = ["q"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not kwargs["request"].user.is_authenticated: + self.form.fields.pop("status") + + +class SearchEventFilter(django_filters.FilterSet): + tags = django_filters.CharFilter(lookup_expr="icontains") + title = django_filters.CharFilter(method="hl_filter_contains") + location = django_filters.CharFilter(method="hl_filter_contains") + description = django_filters.CharFilter(method="hl_filter_contains") + start_day = django_filters.DateFromToRangeFilter( + widget=django_filters.widgets.RangeWidget(attrs={"type": "date"}) + ) + status = django_filters.MultipleChoiceFilter( + label="Filtrer par status", + choices=Event.STATUS.choices, + field_name="status", + widget=forms.CheckboxSelectMultiple, + ) + + o = django_filters.OrderingFilter( + # tuple-mapping retains order + fields=( + ("title", "title"), + ("description", "description"), + ("start_day", "start_day"), + ), + ) + + def hl_filter_contains(self, queryset, name, value): + # first check if it contains + filter_contains = {name + "__contains": value} + queryset = queryset.filter(**filter_contains) + + # then hightlight the result + search_query = SearchQuery(value, config="french") + params = { + name + + "_hl": SearchHeadline( + name, + search_query, + start_sel='', + stop_sel="", + config="french", + ) + } + return queryset.annotate(**params) + + class Meta: + model = Event + fields = ["title", "location", "description", "category", "tags", "start_day"] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not kwargs["request"].user.is_authenticated: + self.form.fields.pop("status") + + +class DuplicatedEventsFilter(django_filters.FilterSet): + fixed = django_filters.BooleanFilter( + label="Résolu", + field_name='representative', method="fixed_qs") + + class Meta: + model = DuplicatedEvents + fields = [] + + + def fixed_qs(self, queryset, name, value): + return DuplicatedEvents.not_fixed_qs(queryset, value) diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py index 7efe4c8..6a624a6 100644 --- a/src/agenda_culturel/forms.py +++ b/src/agenda_culturel/forms.py @@ -14,6 +14,24 @@ from django.forms import ( HiddenInput, ModelChoiceField, ) + +from django.forms import ( + ModelForm, + ValidationError, + TextInput, + Form, + URLField, + MultipleHiddenInput, + Textarea, + CharField, + ChoiceField, + RadioSelect, + MultipleChoiceField, + BooleanField, + HiddenInput, + ModelChoiceField, +) + from django_better_admin_arrayfield.forms.widgets import DynamicArrayWidget from .models import ( diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index dcc3709..5691183 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -6,7 +6,6 @@ from django.contrib.auth.mixins import ( UserPassesTestMixin, PermissionRequiredMixin, ) -from django.http import QueryDict from django import forms from django.contrib.postgres.search import SearchQuery, SearchHeadline from django.utils.safestring import mark_safe @@ -35,6 +34,15 @@ from .forms import ( MultipleHiddenInput ) +from .filters import ( + EventFilter, + EventFilterAdmin, + ContactMessagesFilterAdmin, + SimpleSearchEventFilter, + SearchEventFilter, + DuplicatedEventsFilter, +) + from .models import ( Event, Category, @@ -57,7 +65,6 @@ from django.db.models import Q, Subquery, OuterRef, Count, F from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ -import django_filters from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.contrib.auth.decorators import login_required, permission_required @@ -153,267 +160,6 @@ def internal_server_error(request): def thank_you(request): return render(request, "agenda_culturel/thank_you.html") -class EventFilter(django_filters.FilterSet): - RECURRENT_CHOICES = [ - ("remove_recurrent", "Masquer les événements récurrents"), - ("only_recurrent", "Montrer uniquement les événements récurrents"), - ] - - DISTANCE_CHOICES = [5, 10, 15, 30] - - position = django_filters.ModelChoiceFilter( - label="À proximité de", - method="no_filter", - empty_label=_("Select a location"), - queryset=ReferenceLocation.objects.all().order_by("-main", "name__unaccent") - ) - - radius = django_filters.ChoiceFilter( - label="Dans un rayon de", - method="no_filter", - choices=[(x, str(x) + " km") for x in DISTANCE_CHOICES], - null_label=None, - empty_label=None - ) - - exclude_tags = django_filters.MultipleChoiceFilter( - label="Exclure les étiquettes", - choices=[], - lookup_expr="icontains", - field_name="tags", - exclude=True, - widget=forms.SelectMultiple, - ) - - tags = django_filters.MultipleChoiceFilter( - label="Inclure les étiquettes", - choices=[], - lookup_expr="icontains", - conjoined=True, - field_name="tags", - widget=forms.SelectMultiple, - ) - - recurrences = django_filters.ChoiceFilter( - label="Inclure la récurrence", - choices=RECURRENT_CHOICES, - method="filter_recurrences", - ) - - category = django_filters.ModelMultipleChoiceFilter( - label="Filtrer par catégories", - field_name="category__id", - to_field_name="id", - queryset=Category.objects.all(), - widget=MultipleHiddenInput, - ) - - - status = django_filters.MultipleChoiceFilter( - label="Filtrer par status", - choices=Event.STATUS.choices, - field_name="status", - widget=forms.CheckboxSelectMultiple, - ) - - class Meta: - model = Event - fields = ["category", "tags", "exclude_tags", "status", "recurrences"] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - if not kwargs["request"].user.is_authenticated: - self.form.fields.pop("status") - self.form.fields["exclude_tags"].choices = Tag.get_tag_groups(exclude=True, nb_suggestions=0) - self.form.fields["tags"].choices = Tag.get_tag_groups(include=True) - - def filter_recurrences(self, queryset, name, value): - # construct the full lookup expression - lookup = "__".join([name, "isnull"]) - return queryset.filter(**{lookup: value == "remove_recurrent"}) - - def no_filter(self, queryset, name, value): - return queryset - - @property - def qs(self): - parent = super().qs - if self.get_cleaned_data("position") is None or self.get_cleaned_data("radius") is None: - return parent - d = self.get_cleaned_data("radius") - p = self.get_cleaned_data("position").location - return parent.exclude(exact_location=False).filter(exact_location__location__distance_lt=(p, D(km=d))) - - def get_url(self): - if isinstance(self.form.data, QueryDict): - return self.form.data.urlencode() - else: - return "" - - def get_full_url(self): - return self.request.get_full_path() - - def get_url_remove_categories(self, catpks, full_path = None): - if full_path is None: - full_path = self.request.get_full_path() - - result = full_path - for catpk in catpks: - result = result.replace('category=' + str(catpk), '') - result = result.replace('?&', '?') - result = result.replace('&&', '&') - return result - - def get_url_add_categories(self, catpks, full_path = None): - if full_path is None: - full_path = self.request.get_full_path() - - result = full_path - for catpk in catpks: - result = result + ('&' if '?' in full_path else '?') + 'category=' + str(catpk) - return result - - def get_url_without_filters_only_cats(self): - return self.get_url_without_filters(True) - - - def get_url_without_filters(self, only_categories=False): - - if only_categories: - # on repart d'une url sans option - result = self.request.get_full_path().split("?")[0] - # on ajoute toutes les catégories - result = self.get_url_add_categories([c.pk for c in self.get_categories()], result) - else: - # on supprime toutes les catégories - result = self.get_url_remove_categories([c.pk for c in self.get_categories()]) - - return result - - - def get_cleaned_data(self, name): - try: - return self.form.cleaned_data[name] - except AttributeError: - return {} - except KeyError: - return {} - - def get_categories(self): - return self.get_cleaned_data("category") - - def has_category(self): - return "category" in self.form.cleaned_data and len(self.get_cleaned_data("category")) > 0 - - def get_tags(self): - return self.get_cleaned_data("tags") - - def get_exclude_tags(self): - return self.get_cleaned_data("exclude_tags") - - def get_status(self): - return self.get_cleaned_data("status") - - def get_position(self): - return self.get_cleaned_data("position") - - def get_radius(self): - return self.get_cleaned_data("radius") - - def to_str(self, prefix=''): - self.form.full_clean() - result = ' '.join([c.name for c in self.get_categories()] + [t for t in self.get_tags()] + ["~" + t for t in self.get_exclude_tags()] + [str(self.get_position()), str(self.get_radius())]) - if len(result) > 0: - result = prefix + result - return result - - def get_status_names(self): - if "status" in self.form.cleaned_data: - return [ - dict(Event.STATUS.choices)[s] for s in self.get_cleaned_data("status") - ] - else: - return [] - - def get_recurrence_filtering(self): - if "recurrences" in self.form.cleaned_data: - d = dict(self.RECURRENT_CHOICES) - v = self.form.cleaned_data["recurrences"] - if v in d: - return d[v] - else: - return "" - else: - return "" - - - def is_resetable(self, only_categories=False): - if only_categories: - return len(self.get_cleaned_data("category")) != 0 - else: - if self.request.user.is_authenticated: - if ( - len(self.get_cleaned_data("status")) != 1 - or - self.get_cleaned_data("status")[0] != Event.STATUS.PUBLISHED - ): - return True - else: - if ( - len(self.get_cleaned_data("status")) != 0 - ): - return True - return ( - len(self.get_cleaned_data("tags")) != 0 - or len(self.get_cleaned_data("exclude_tags")) != 0 - or len(self.get_cleaned_data("recurrences")) != 0 - or ((not self.get_cleaned_data("position") is None) and (not self.get_cleaned_data("radius") is None)) - ) - - def is_active(self, only_categories=False): - if only_categories: - return len(self.get_cleaned_data("category")) != 0 - else: - return ( - len(self.get_cleaned_data("status")) != 0 - or len(self.get_cleaned_data("tags")) != 0 - or len(self.get_cleaned_data("exclude_tags")) != 0 - or len(self.get_cleaned_data("recurrences")) != 0 - or ((not self.get_cleaned_data("position") is None) and (not self.get_cleaned_data("radius") is None)) - ) - - def is_selected(self, cat): - return "category" in self.form.cleaned_data and cat in self.form.cleaned_data["category"] - - def is_selected_tag(self, tag): - return "tags" in self.form.cleaned_data and tag in self.form.cleaned_data["tags"] - - def get_url_add_tag(self, tag, category=None): - full_path = self.request.get_full_path() - - result = full_path + ('&' if '?' in full_path else '?') + 'tags=' + str(tag) - - if not category is None: - result = self.get_url_add_categories([category.pk], result) - return result - - def tag_exists(self, tag): - return tag in [t[0] for g in self.form.fields["tags"].choices for t in g[1]] - - def set_default_values(request): - if request.user.is_authenticated: - if request.GET.get('status', None) == None: - tempdict = request.GET.copy() - tempdict['status'] = 'published' - request.GET = tempdict - return request - return request - - def get_position_radius(self): - if self.get_cleaned_data("position") is None or self.get_cleaned_data("radius") is None: - return "" - else: - return str(self.get_cleaned_data("position")) + ' (' + str(self.get_cleaned_data("radius")) + ' km)' @@ -877,43 +623,6 @@ def export_ical(request): return response -class EventFilterAdmin(django_filters.FilterSet): - status = django_filters.MultipleChoiceFilter( - choices=Event.STATUS.choices, widget=forms.CheckboxSelectMultiple - ) - - representative = django_filters.MultipleChoiceFilter( - label=_("Representative version"), - choices=[(True, _("Yes")), (False, _("Non"))], - method="filter_by_representative", - widget=forms.CheckboxSelectMultiple) - - import_sources = django_filters.ModelChoiceFilter( - label=_("Imported from"), - method="filter_by_source", - queryset=RecurrentImport.objects.all().order_by("name__unaccent") - ) - - def filter_by_source(self, queryset, name, value): - src = RecurrentImport.objects.get(pk=value.pk).source - return queryset.filter(import_sources__contains=[src]) - - def filter_by_representative(self, queryset, name, value): - if value is None or len(value) != 1: - return queryset - else: - q = (Q(other_versions__isnull=True) | - Q(other_versions__representative=F('pk')) | - Q(other_versions__representative__isnull=True)) - if value[0] == True: - return queryset.filter(q) - else: - return queryset.exclude(q) - - - class Meta: - model = Event - fields = ["status"] class ContactMessageCreateView(SuccessMessageMixin, CreateView): @@ -959,21 +668,6 @@ class ContactMessageUpdateView( return kwargs -class ContactMessagesFilterAdmin(django_filters.FilterSet): - closed = django_filters.MultipleChoiceFilter( - label="Status", - choices=((True, _("Closed")), (False, _("Open"))), - widget=forms.CheckboxSelectMultiple, - ) - spam = django_filters.MultipleChoiceFilter( - label="Spam", - choices=((True, _("Spam")), (False, _("Non spam"))), - widget=forms.CheckboxSelectMultiple, - ) - - class Meta: - model = ContactMessage - fields = ["closed", "spam"] @login_required(login_url="/accounts/login/") @@ -1113,103 +807,6 @@ def delete_cm_spam(request): -class SimpleSearchEventFilter(django_filters.FilterSet): - q = django_filters.CharFilter(method="custom_filter", - label=_("Search"), - widget=forms.TextInput(attrs={"type": "search"}) - ) - - status = django_filters.MultipleChoiceFilter( - label="Filtrer par status", - choices=Event.STATUS.choices, - field_name="status", - widget=forms.CheckboxSelectMultiple, - ) - - def custom_filter(self, queryset, name, value): - search_query = SearchQuery(value, config="french") - qs = queryset.filter( - Q(title__icontains=value) - | Q(category__name__icontains=value) - | Q(tags__icontains=[value]) - | Q(exact_location__name__icontains=value) - | Q(description__icontains=value) - ) - for f in ["title", "category__name", "exact_location__name", "description"]: - params = { - f - + "_hl": SearchHeadline( - f, - search_query, - start_sel='', - stop_sel="", - config="french", - ) - } - qs = qs.annotate(**params) - return qs - - class Meta: - model = Event - fields = ["q"] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - if not kwargs["request"].user.is_authenticated: - self.form.fields.pop("status") - - -class SearchEventFilter(django_filters.FilterSet): - tags = django_filters.CharFilter(lookup_expr="icontains") - title = django_filters.CharFilter(method="hl_filter_contains") - location = django_filters.CharFilter(method="hl_filter_contains") - description = django_filters.CharFilter(method="hl_filter_contains") - start_day = django_filters.DateFromToRangeFilter( - widget=django_filters.widgets.RangeWidget(attrs={"type": "date"}) - ) - status = django_filters.MultipleChoiceFilter( - label="Filtrer par status", - choices=Event.STATUS.choices, - field_name="status", - widget=forms.CheckboxSelectMultiple, - ) - - o = django_filters.OrderingFilter( - # tuple-mapping retains order - fields=( - ("title", "title"), - ("description", "description"), - ("start_day", "start_day"), - ), - ) - - def hl_filter_contains(self, queryset, name, value): - # first check if it contains - filter_contains = {name + "__contains": value} - queryset = queryset.filter(**filter_contains) - - # then hightlight the result - search_query = SearchQuery(value, config="french") - params = { - name - + "_hl": SearchHeadline( - name, - search_query, - start_sel='', - stop_sel="", - config="french", - ) - } - return queryset.annotate(**params) - - class Meta: - model = Event - fields = ["title", "location", "description", "category", "tags", "start_day"] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - if not kwargs["request"].user.is_authenticated: - self.form.fields.pop("status") def event_search(request, full=False): @@ -1486,18 +1083,6 @@ def run_all_rimports(request, status=None): ## duplicated events ######################### -class DuplicatedEventsFilter(django_filters.FilterSet): - fixed = django_filters.BooleanFilter( - label="Résolu", - field_name='representative', method="fixed_qs") - - class Meta: - model = DuplicatedEvents - fields = [] - - - def fixed_qs(self, queryset, name, value): - return DuplicatedEvents.not_fixed_qs(queryset, value) class DuplicatedEventsDetailView(LoginRequiredMixin, DetailView): model = DuplicatedEvents