On sépare le code pour plus de lisibilité
This commit is contained in:
parent
637b976442
commit
3bd4ef5771
478
src/agenda_culturel/filters.py
Normal file
478
src/agenda_culturel/filters.py
Normal file
@ -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='<span class="highlight">',
|
||||
stop_sel="</span>",
|
||||
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='<span class="highlight">',
|
||||
stop_sel="</span>",
|
||||
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)
|
@ -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 (
|
||||
|
@ -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='<span class="highlight">',
|
||||
stop_sel="</span>",
|
||||
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='<span class="highlight">',
|
||||
stop_sel="</span>",
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user