From 9a90f195023262f482649e9768945a3d0de0faca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 4 Jul 2020 13:50:19 +0200 Subject: [PATCH] Separate the autocompletion logic form the views --- bda/views.py | 2 +- bds/autocomplete.py | 2 +- cof/urls.py | 3 +-- gestioncof/autocomplete.py | 24 +---------------- gestioncof/tests/test_views.py | 2 +- gestioncof/views.py | 19 +++++++++++++- kfet/autocomplete.py | 41 +----------------------------- kfet/urls.py | 6 ++--- kfet/views.py | 39 ++++++++++++++++++++++++++++ shared/{views => }/autocomplete.py | 9 ------- shared/tests/mixins.py | 2 +- shared/views.py | 11 ++++++++ 12 files changed, 78 insertions(+), 82 deletions(-) rename shared/{views => }/autocomplete.py (95%) create mode 100644 shared/views.py diff --git a/bda/views.py b/bda/views.py index f799360d..25fa97e2 100644 --- a/bda/views.py +++ b/bda/views.py @@ -42,7 +42,7 @@ from bda.models import ( Tirage, ) from gestioncof.decorators import BuroRequiredMixin, buro_required, cof_required -from shared.views.autocomplete import Select2QuerySetView +from shared.views import Select2QuerySetView @cof_required diff --git a/bds/autocomplete.py b/bds/autocomplete.py index 6660a7d6..7fec4cea 100644 --- a/bds/autocomplete.py +++ b/bds/autocomplete.py @@ -1,7 +1,7 @@ from django.contrib.auth import get_user_model from django.db.models import Q -from shared.views import autocomplete +from shared import autocomplete User = get_user_model() diff --git a/cof/urls.py b/cof/urls.py index 0b03f2db..963b3b14 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -24,7 +24,6 @@ if "gestioncof" in settings.INSTALLED_APPS: from wagtail.documents import urls as wagtaildocs_urls from gestioncof import csv_views, views as gestioncof_views - from gestioncof.autocomplete import autocomplete from gestioncof.urls import ( calendar_patterns, clubs_patterns, @@ -109,7 +108,7 @@ if "gestioncof" in settings.INSTALLED_APPS: # Autocompletion path( "autocomplete/registration", - autocomplete, + gestioncof_views.registration_autocomplete, name="cof.registration.autocomplete", ), path( diff --git a/gestioncof/autocomplete.py b/gestioncof/autocomplete.py index 648b239b..febbcac9 100644 --- a/gestioncof/autocomplete.py +++ b/gestioncof/autocomplete.py @@ -1,10 +1,7 @@ from django.contrib.auth import get_user_model from django.db.models import Q -from django.http import Http404 -from django.views.generic import TemplateView -from gestioncof.decorators import buro_required -from shared.views import autocomplete +from shared import autocomplete User = get_user_model() @@ -41,22 +38,3 @@ class COFSearch(autocomplete.Compose): ("others", COFOthersSearch()), ("clippers", autocomplete.LDAPSearch()), ] - - -cof_search = COFSearch() - - -class AutocompleteView(TemplateView): - template_name = "gestioncof/search_results.html" - - def get_context_data(self, *args, **kwargs): - ctx = super().get_context_data(*args, **kwargs) - if "q" not in self.request.GET: - raise Http404 - q = self.request.GET["q"] - ctx["q"] = q - ctx.update(cof_search.search(q.split())) - return ctx - - -autocomplete = buro_required(AutocompleteView.as_view()) diff --git a/gestioncof/tests/test_views.py b/gestioncof/tests/test_views.py index 09e86860..b623b283 100644 --- a/gestioncof/tests/test_views.py +++ b/gestioncof/tests/test_views.py @@ -16,8 +16,8 @@ from django.urls import reverse from bda.models import Salle, Tirage from gestioncof.models import CalendarSubscription, Club, Event, Survey, SurveyAnswer from gestioncof.tests.mixins import MegaHelperMixin, ViewTestCaseMixin +from shared.autocomplete import Clipper from shared.tests.mixins import CSVResponseMixin, ICalMixin, MockLDAPMixin -from shared.views.autocomplete import Clipper from .utils import create_member, create_root, create_user diff --git a/gestioncof/views.py b/gestioncof/views.py index 07a0ae03..83b2111f 100644 --- a/gestioncof/views.py +++ b/gestioncof/views.py @@ -25,6 +25,7 @@ from django_cas_ng.views import LogoutView as CasLogoutView from icalendar import Calendar, Event as Vevent from bda.models import Spectacle, Tirage +from gestioncof.autocomplete import COFSearch from gestioncof.decorators import buro_required, cof_required from gestioncof.forms import ( CalendarForm, @@ -58,7 +59,7 @@ from gestioncof.models import ( SurveyQuestion, SurveyQuestionAnswer, ) -from shared.views.autocomplete import Select2QuerySetView +from shared.views import Select2QuerySetView class HomeView(LoginRequiredMixin, TemplateView): @@ -948,3 +949,19 @@ class UserAutocomplete(Select2QuerySetView): user_autocomplete = buro_required(UserAutocomplete.as_view()) + + +class AutocompleteView(TemplateView): + template_name = "gestioncof/search_results.html" + + def get_context_data(self, *args, **kwargs): + ctx = super().get_context_data(*args, **kwargs) + if "q" not in self.request.GET: + raise Http404 + q = self.request.GET["q"] + ctx["q"] = q + ctx.update(COFSearch().search(q.split())) + return ctx + + +registration_autocomplete = buro_required(AutocompleteView.as_view()) diff --git a/kfet/autocomplete.py b/kfet/autocomplete.py index 2a88ce1f..04a4be2b 100644 --- a/kfet/autocomplete.py +++ b/kfet/autocomplete.py @@ -1,10 +1,7 @@ from django.contrib.auth import get_user_model -from django.contrib.auth.mixins import PermissionRequiredMixin from django.db.models import Q -from django.http import Http404 -from django.views.generic import TemplateView -from shared.views import autocomplete +from shared import autocomplete User = get_user_model() @@ -60,39 +57,3 @@ class KfetAutocomplete(autocomplete.Compose): ("users_notcof", OthersSearch()), ("clippers", autocomplete.LDAPSearch()), ] - - -kfet_autocomplete = KfetAutocomplete() - - -class AccountCreateAutocompleteView(PermissionRequiredMixin, TemplateView): - template_name = "kfet/account_create_autocomplete.html" - permission_required = "kfet.is_team" - - def get_context_data(self, **kwargs): - ctx = super().get_context_data(**kwargs) - if "q" not in self.request.GET: - raise Http404 - q = self.request.GET["q"] - ctx["q"] = q - results = kfet_autocomplete.search(q.split()) - ctx["options"] = sum((len(res) for res in results.values())) - ctx.update(results) - return ctx - - -class AccountSearchAutocompleteView(PermissionRequiredMixin, TemplateView): - template_name = "kfet/account_search_autocomplete.html" - permission_required = "kfet.is_team" - - def get_context_data(self, **kwargs): - ctx = super().get_context_data(**kwargs) - if "q" not in self.request.GET: - raise Http404 - q = self.request.GET["q"] - ctx["q"] = q - ctx["accounts"] = [ - (user.profile.account_kfet.trigramme, user.get_full_name()) - for user in KfetAccountSearch().search(q.split()) - ] - return ctx diff --git a/kfet/urls.py b/kfet/urls.py index a4ce450c..2548e77e 100644 --- a/kfet/urls.py +++ b/kfet/urls.py @@ -1,7 +1,7 @@ from django.contrib.auth.decorators import permission_required from django.urls import include, path, register_converter -from kfet import autocomplete, converters, views +from kfet import converters, views from kfet.decorators import teamkfet_required register_converter(converters.TrigrammeConverter, "trigramme") @@ -38,13 +38,13 @@ urlpatterns = [ ), path( "autocomplete/account_new", - autocomplete.AccountCreateAutocompleteView.as_view(), + views.AccountCreateAutocompleteView.as_view(), name="kfet.account.create.autocomplete", ), # Account - Search path( "autocomplete/account_search", - autocomplete.AccountSearchAutocompleteView.as_view(), + views.AccountSearchAutocompleteView.as_view(), name="kfet.account.search.autocomplete", ), # Account - Read diff --git a/kfet/views.py b/kfet/views.py index b6c49f72..5fd502c0 100644 --- a/kfet/views.py +++ b/kfet/views.py @@ -27,6 +27,7 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView from gestioncof.models import CofProfile from kfet import KFET_DELETED_TRIGRAMME, consumers from kfet.auth.decorators import kfet_password_auth +from kfet.autocomplete import KfetAccountSearch, KfetAutocomplete from kfet.config import kfet_config from kfet.decorators import teamkfet_required from kfet.forms import ( @@ -2586,3 +2587,41 @@ class ArticleStatSales(ScaleMixin, JSONDetailView): }, ] return context + + +# --- +# Autocompletion views +# --- + + +class AccountCreateAutocompleteView(PermissionRequiredMixin, TemplateView): + template_name = "kfet/account_create_autocomplete.html" + permission_required = "kfet.is_team" + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + if "q" not in self.request.GET: + raise Http404 + q = self.request.GET["q"] + ctx["q"] = q + results = KfetAutocomplete().search(q.split()) + ctx["options"] = sum((len(res) for res in results.values())) + ctx.update(results) + return ctx + + +class AccountSearchAutocompleteView(PermissionRequiredMixin, TemplateView): + template_name = "kfet/account_search_autocomplete.html" + permission_required = "kfet.is_team" + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + if "q" not in self.request.GET: + raise Http404 + q = self.request.GET["q"] + ctx["q"] = q + ctx["accounts"] = [ + (user.profile.account_kfet.trigramme, user.get_full_name()) + for user in KfetAccountSearch().search(q.split()) + ] + return ctx diff --git a/shared/views/autocomplete.py b/shared/autocomplete.py similarity index 95% rename from shared/views/autocomplete.py rename to shared/autocomplete.py index 4aed6a2e..02b6b661 100644 --- a/shared/views/autocomplete.py +++ b/shared/autocomplete.py @@ -1,7 +1,6 @@ import logging from collections import namedtuple -from dal import autocomplete from django.conf import settings from django.db.models import Q @@ -100,14 +99,6 @@ class ModelSearch(SearchUnit): 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) - - # --- # LDAP search # --- diff --git a/shared/tests/mixins.py b/shared/tests/mixins.py index 030b3d5c..7b5edf6a 100644 --- a/shared/tests/mixins.py +++ b/shared/tests/mixins.py @@ -44,7 +44,7 @@ class MockLDAPMixin: # Mock ldap module whose `initialize_method` always return the same ldap object. mock_ldap_module = self.MockLDAPModule(mock_ldap_obj) - patcher = mock.patch("shared.views.autocomplete.ldap", new=mock_ldap_module) + patcher = mock.patch("shared.autocomplete.ldap", new=mock_ldap_module) patcher.start() self.addCleanup(patcher.stop) diff --git a/shared/views.py b/shared/views.py new file mode 100644 index 00000000..8fd28796 --- /dev/null +++ b/shared/views.py @@ -0,0 +1,11 @@ +from dal import autocomplete + +from shared.autocomplete import ModelSearch + + +class Select2QuerySetView(ModelSearch, autocomplete.Select2QuerySetView): + """Compatibility layer between ModelSearch and Select2QuerySetView.""" + + def get_queryset(self): + keywords = self.q.split() + return super().search(keywords)