From 7097aa17d3b63384b3723f2c5dc43a72cd3896eb Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Sat, 11 Nov 2023 12:03:47 +0100 Subject: [PATCH] =?UTF-8?q?Am=C3=A9lioration=20de=20la=20recherche?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agenda_culturel/static/style.scss | 16 +++- .../templates/agenda_culturel/search.html | 83 ++++++++++--------- .../templatetags/utils_extra.py | 8 +- src/agenda_culturel/urls.py | 3 +- src/agenda_culturel/views.py | 68 ++++++++++++--- 5 files changed, 123 insertions(+), 55 deletions(-) diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index 72262dc..1bc2858 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -298,9 +298,9 @@ article#filters { } } -.helptext { +.helptext, .location-search { font-size: 80%; - opacity: 0.7; + margin-top: -0.7em; } .django-ckeditor-widget { @@ -316,4 +316,16 @@ article#filters { .slide-buttons { float: right; +} + +.highlight { + color: var(--primary); + font-weight: bold; + font-style: italic; +} + +.search .description { + margin-left: 1em; + font-size: 90%; + margin-top: -0.5em; } \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/search.html b/src/agenda_culturel/templates/agenda_culturel/search.html index a02cc64..4038bc8 100644 --- a/src/agenda_culturel/templates/agenda_culturel/search.html +++ b/src/agenda_culturel/templates/agenda_culturel/search.html @@ -1,57 +1,64 @@ {% extends "agenda_culturel/page.html" %} -{% block title %}Rechercher un évnement{% endblock %} +{% block title %}Rechercher un événement{% endblock %} +{% load utils_extra %} {% block content %} - -
+ {% endblock %} \ No newline at end of file diff --git a/src/agenda_culturel/templatetags/utils_extra.py b/src/agenda_culturel/templatetags/utils_extra.py index 5ab883e..20b118d 100644 --- a/src/agenda_culturel/templatetags/utils_extra.py +++ b/src/agenda_culturel/templatetags/utils_extra.py @@ -59,6 +59,10 @@ def url_day(d): @register.simple_tag def picto_from_name(name, datatooltip=""): - return mark_safe('' + \ + result = '' + \ '' + \ - '') + '' + if datatooltip != "": + result = '' + result + '' + + return mark_safe(result) diff --git a/src/agenda_culturel/urls.py b/src/agenda_culturel/urls.py index 18b0dfc..7059794 100644 --- a/src/agenda_culturel/urls.py +++ b/src/agenda_culturel/urls.py @@ -28,7 +28,8 @@ urlpatterns = [ path("test_app/", include("test_app.urls")), path("static-content/create", StaticContentCreateView.as_view(), name="create_static_content"), path("static-content//edit", StaticContentUpdateView.as_view(), name="edit_static_content"), - path('rechercher/', event_search, name='event_search') + path('rechercher/', event_search, name='event_search'), + path('rechercher/complet/', event_search_full, name='event_search_full') ] if settings.DEBUG: diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py index 99b4e43..f9a4db3 100644 --- a/src/agenda_culturel/views.py +++ b/src/agenda_culturel/views.py @@ -4,6 +4,8 @@ from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.contrib.auth.mixins import LoginRequiredMixin from django.http import QueryDict from django import forms +from django.contrib.postgres.search import SearchQuery, SearchHeadline + from .forms import EventSubmissionModelForm from .celery import create_event_from_submission @@ -403,16 +405,34 @@ def event_list(request): return render(request, 'agenda_culturel/list.html', {'filter': filter, 'paginator_filter': response}) +class SimpleSearchEventFilter(django_filters.FilterSet): + q = django_filters.CharFilter(method='custom_filter', label=_("Search")) + + def custom_filter(self, queryset, name, value): + search_query = SearchQuery(value, config='french') + qs = queryset.filter( + Q(title__contains=value) | Q(location__contains=value) | Q(description__contains=value)) + for f in ["title", "location", "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'] + class SearchEventFilter(django_filters.FilterSet): tags = django_filters.CharFilter(lookup_expr='icontains') - title = django_filters.CharFilter(lookup_expr='contains') - location = django_filters.CharFilter(lookup_expr='contains') - description = django_filters.CharFilter(lookup_expr='contains') + 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'})) - q = django_filters.CharFilter(method='custom_filter', label=_("Search")) - o = django_filters.OrderingFilter( # tuple-mapping retains order fields=( @@ -422,18 +442,36 @@ class SearchEventFilter(django_filters.FilterSet): ), ) - def custom_filter(self, queryset, name, value): - return queryset.filter( - Q(title__contains=value) | Q(location__contains=value) | Q(description__contains=value)) + 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 = ['q', 'title', 'location', 'description', 'category', 'tags', 'start_day'] + fields = ['title', 'location', 'description', 'category', 'tags', 'start_day'] + + + +def event_search(request, full=False): + + if full: + filter = SearchEventFilter(request.GET, queryset=get_event_qs(request).order_by("-start_day")) + else: + filter = SimpleSearchEventFilter(request.GET, queryset=get_event_qs(request).order_by("-start_day")) -def event_search(request): - filter = SearchEventFilter(request.GET, queryset=get_event_qs(request).order_by("-start_day")) paginator = Paginator(filter.qs, 10) page = request.GET.get('page') @@ -444,4 +482,10 @@ def event_search(request): except EmptyPage: response = paginator.page(paginator.num_pages) - return render(request, 'agenda_culturel/search.html', {'filter': filter, 'paginator_filter': response}) + return render(request, 'agenda_culturel/search.html', {'filter': filter, + 'has_results': len(request.GET) != 0 or (len(request.GET) > 1 and "page" in request.GET), + 'paginator_filter': response, + 'full': full}) + +def event_search_full(request): + return event_search(request, True)