Commit d361fbde authored by Hamza Dely's avatar Hamza Dely

[consos/views] Utilisation d'un filtre modifié pour la recherche dans les notes

parent 00129cb0
......@@ -2,6 +2,7 @@
Vues de l'application « Consos »
"""
import django
from django.urls import reverse_lazy
from django.shortcuts import get_object_or_404
from django.contrib import messages
......@@ -13,7 +14,7 @@ from django.views.generic.edit import FormView, CreateView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.contrib.contenttypes.models import ContentType
from rest_framework import viewsets, status, filters
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.decorators import detail_route
......@@ -21,6 +22,7 @@ from django_filters.rest_framework import DjangoFilterBackend
from note_kfet.utils import to_bool
from note_kfet.droits import D, Acl
from note_kfet.filters import NoteSearchFilter
from note_kfet.views.mixins import NoteMixin
from note_kfet.views.decorators import requires
......@@ -313,8 +315,8 @@ class NoteViewSet(viewsets.GenericViewSet):
"""
queryset = Note.objects.all()
serializer_class = NoteSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('$alias',)
filter_backends = (NoteSearchFilter,)
search_fields = ('alias',)
@requires("comptes.adherent_chercher", Acl.BASIQUE)
def list(self, request):
......@@ -341,14 +343,22 @@ class NoteViewSet(viewsets.GenericViewSet):
)
qs = qs.select_related('proprietaire__note')
data = [
{
'alias' : alias.alias,
'pseudo' : alias.proprietaire.pseudo,
'solde' : alias.proprietaire.note.solde,
'adherent' : alias.proprietaire.note.adherent,
} for alias in qs
]
try:
data = [
{
'alias' : alias.alias,
'pseudo' : alias.proprietaire.pseudo,
'solde' : alias.proprietaire.note.solde,
'adherent' : alias.proprietaire.note.adherent,
} for alias in qs
]
except django.db.DataError as e:
return Response(
{
"detail" : "%s" % e.args,
},
status=status.HTTP_400_BAD_REQUEST,
)
fields = ['adherent', 'pseudo', 'alias', 'solde']
serializer = self.get_serializer(data, fields=fields, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
......
"""
Filtres spéciaux pour la Note Kfet
"""
import operator
from functools import reduce
from distutils.util import strtobool
from django.db import models
from django.db.models.constants import LOOKUP_SEP
from rest_framework import filters
from rest_framework.compat import distinct
from note_kfet.utils import escape_regex
class NoteSearchFilter(filters.SearchFilter):
"""
Filtre de recherche permettant d'effectuer au choix
une recherche brute ou une recherche par expression régulière
en commençant à chercher au début d'un mot
"""
def get_regex_mode(self, request):
return strtobool(request.query_params.get('regex', 'false'))
def construct_search(self, field_name):
return LOOKUP_SEP.join([field_name, 'iregex'])
def filter_queryset(self, request, queryset, view):
search_fields = getattr(view, 'search_fields', None)
use_regex_mode = self.get_regex_mode(request)
search_terms = self.get_search_terms(request)
if not search_fields or not search_terms:
return queryset
search_terms = [
"^%s" % (
search_term if use_regex_mode else escape_regex(search_term)
) for search_term in search_terms
]
orm_lookups = [
self.construct_search(search_field)
for search_field in search_fields
]
base = queryset
conditions = []
for search_term in search_terms:
queries = [
models.Q(**{orm_lookup: search_term})
for orm_lookup in orm_lookups
]
conditions.append(reduce(operator.or_, queries))
queryset = queryset.filter(reduce(operator.and_, conditions))
if self.must_call_distinct(queryset, search_fields):
# Filtering against a many-to-many field requires us to
# call queryset.distinct() in order to avoid duplicate items
# in the resulting queryset.
# We try to avoid this if possible, for performance reasons.
queryset = distinct(queryset, base)
return queryset
......@@ -53,3 +53,17 @@ def to_bool(value):
return bool(strtobool(value))
except ValueError:
return None
def escape_regex(regex):
"""
Échappe les caractères spéciaux utilisés dans les expressions
régulières POSIX (PREs)
"""
escaped = ""
for char in regex:
if char in ['{', '}', '(', ')', '[', ']', '|', '?', '*', '.', '\\',]:
escaped += '\\' + char
else:
escaped += char
return escaped
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment