Merge branch 'kerl/merge_shared_utils' into 'master'

Préparation de la vue d'autocompletion pour l'intégration du BDS

See merge request klub-dev-ens/gestioCOF!401
This commit is contained in:
Ludovic Stephan 2020-05-07 14:54:50 +02:00
commit 5298a19667
8 changed files with 62 additions and 31 deletions

View file

@ -61,9 +61,9 @@ linters:
- pip install --upgrade black isort flake8
script:
- black --check .
- isort --recursive --check-only --diff bda bds clubs cof events gestioncof kfet petitscours provisioning shared utils
- isort --recursive --check-only --diff bda bds clubs cof events gestioncof kfet petitscours provisioning shared
# Print errors only
- flake8 --exit-zero bda bds clubs cof events gestioncof kfet petitscours provisioning shared utils
- flake8 --exit-zero bda bds clubs cof events gestioncof kfet petitscours provisioning shared
cache:
key: linters
paths:

View file

@ -42,7 +42,7 @@ from bda.models import (
Tirage,
)
from gestioncof.decorators import BuroRequiredMixin, buro_required, cof_required
from utils.views.autocomplete import Select2QuerySetView
from shared.views.autocomplete import Select2QuerySetView
@cof_required

View file

@ -58,7 +58,7 @@ from gestioncof.models import (
SurveyQuestion,
SurveyQuestionAnswer,
)
from utils.views.autocomplete import Select2QuerySetView
from shared.views.autocomplete import Select2QuerySetView
class HomeView(LoginRequiredMixin, TemplateView):

View file

@ -9,7 +9,6 @@ source =
kfet
petitscours
shared
utils
omit =
*migrations*
*test*.py
@ -37,7 +36,7 @@ default_section = THIRDPARTY
force_grid_wrap = 0
include_trailing_comma = true
known_django = django
known_first_party = bda,bds,clubs,cof,events,gestioncof,kfet,petitscours,shared,utils
known_first_party = bda,bds,clubs,cof,events,gestioncof,kfet,petitscours,shared
line_length = 88
multi_line_output = 3
not_skip = __init__.py

View file

@ -0,0 +1,57 @@
from dal import autocomplete
from django.db.models import Q
class ModelSearch:
"""Basic search engine for models based on filtering.
The class should be configured through its ``model`` class attribute: the ``search``
method will return a queryset of instances of this model. The ``search_fields``
attributes indicates which fields to search in.
Example:
>>> from django.contrib.auth.models import User
>>>
>>> class UserSearch(ModelSearch):
... model = User
... search_fields = ["username", "first_name", "last_name"]
>>>
>>> user_search = UserSearch() # has type ModelSearch[User]
>>> user_search.search(["toto", "foo"]) # returns a queryset of Users
"""
model = None
search_fields = []
def get_queryset_filter(self, keywords):
filter_q = Q()
if not keywords:
return filter_q
for keyword in keywords:
kw_filter = Q()
for field in self.search_fields:
kw_filter |= Q(**{"{}__icontains".format(field): keyword})
filter_q &= kw_filter
return filter_q
def search(self, keywords):
"""Returns the queryset of model instances matching all the keywords.
The semantic of the search is the following: a model instance appears in the
search results iff all of the keywords given as arguments occur in at least one
of the search fields.
"""
return self.model.objects.filter(self.get_queryset_filter(keywords))
class Select2QuerySetView(ModelSearch, autocomplete.Select2QuerySetView):
"""Compatibility layer between ModelSearch and Select2QuerySetView."""
def get_queryset(self):
keywords = self.q.split()
return super().search(keywords)

View file

View file

@ -1,25 +0,0 @@
from dal import autocomplete
from django.db.models import Q
class Select2QuerySetView(autocomplete.Select2QuerySetView):
model = None
search_fields = []
def get_queryset_filter(self):
q = self.q
filter_q = Q()
if not q:
return filter_q
words = q.split()
for word in words:
for field in self.search_fields:
filter_q |= Q(**{"{}__icontains".format(field): word})
return filter_q
def get_queryset(self):
return self.model.objects.filter(self.get_queryset_filter())