Autocompletion refactoring + generic view

This commit is contained in:
Martin Pépin 2020-07-01 22:29:07 +02:00
parent 637572ab58
commit 4d96d2c645
No known key found for this signature in database
GPG key ID: E7520278B1774448
21 changed files with 379 additions and 268 deletions

View file

@ -1,10 +1,9 @@
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 django.urls import reverse
from django.utils.translation import gettext_lazy as _
from gestioncof.decorators import buro_required
from shared.views import autocomplete
from shared import autocomplete
User = get_user_model()
@ -12,45 +11,48 @@ User = get_user_model()
class COFMemberSearch(autocomplete.ModelSearch):
model = User
search_fields = ["username", "first_name", "last_name"]
verbose_name = _("Membres du COF")
def get_queryset_filter(self, *args, **kwargs):
qset_filter = super().get_queryset_filter(*args, **kwargs)
qset_filter &= Q(profile__is_cof=True)
return qset_filter
def result_uuid(self, user):
return user.username
def result_link(self, user):
return reverse("user-registration", args=(user.username,))
class COFOthersSearch(autocomplete.ModelSearch):
model = User
search_fields = ["username", "first_name", "last_name"]
verbose_name = _("Non-membres du COF")
def get_queryset_filter(self, *args, **kwargs):
qset_filter = super().get_queryset_filter(*args, **kwargs)
qset_filter &= Q(profile__is_cof=False)
return qset_filter
def result_uuid(self, user):
return user.username
def result_link(self, user):
return reverse("user-registration", args=(user.username,))
class COFLDAPSearch(autocomplete.LDAPSearch):
def result_link(self, clipper):
return reverse("clipper-registration", args=(clipper.clipper, clipper.fullname))
class COFSearch(autocomplete.Compose):
search_units = [
("members", "username", COFMemberSearch),
("others", "username", COFOthersSearch),
("clippers", "clipper", autocomplete.LDAPSearch),
("members", COFMemberSearch()),
("others", COFOthersSearch()),
("clippers", COFLDAPSearch()),
]
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())

View file

@ -1,56 +1,21 @@
{% load search_utils %}
{% extends "shared/search_results.html" %}
{% load i18n %}
<ul>
{% if members %}
<li class="autocomplete-header">Membres</li>
{% for user in members %}
{% if forloop.counter < 5 %}
<li class="autocomplete-value">
<a href="{% url "user-registration" user.username %}">
{{ user|highlight_user:q }}
</a>
</li>
{% elif forloop.counter == 5 %}
<li class="autocomplete-more">...</li>
{% endif %}
{% endfor %}
{% endif %}
{% if others %}
<li class="autocomplete-header">Non-membres</li>
{% for user in others %}
{% if forloop.counter < 5 %}
<li class="autocomplete-value">
<a href="{% url "user-registration" user.username %}">
{{ user|highlight_user:q }}
</a>
</li>
{% elif forloop.counter == 5 %}
<li class="autocomplete-more">...</li>
{% endif %}
{% endfor %}
{% endif %}
{% if clippers %}
<li class="autocomplete-header">Utilisateurs <tt>clipper</tt></li>
{% for clipper in clippers %}
{% if forloop.counter < 5 %}
<li class="autocomplete-value">
<a href="{% url "clipper-registration" clipper.clipper clipper.fullname %}">
{{ clipper|highlight_clipper:q }}
</a>
</li>
{% elif forloop.counter == 5 %}
<li class="autocomplete-more">...</li>
{% endif %}
{% endfor %}
{% endif %}
{% if total %}
<li class="autocomplete-header">Pas dans la liste ?</li>
{% else %}
<li class="autocomplete-header">Aucune correspondance trouvée</li>
{% endif %}
<li><a href="{% url "empty-registration" %}">Créer un compte</a></li>
</ul>
{% block extra_section %}
<li class="autocomplete-header">
{% if not results %}
<span class="autocomplete-item">
{% trans "Aucune correspondance trouvée" %}
</span>
{% else %}
<span class="autocomplete-item">
{% trans "Pas dans la liste ?" %}
</span>
{% endif %}
</li>
<li class="autocomplete-new">
<a class="autocomplete-item" href="{% url "empty-registration" %}">
{% trans "Créer un compte" %}
</a>
</li>
{% endblock %}

View file

@ -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, LDAPSearch
from shared.tests.mixins import CSVResponseMixin, ICalMixin, MockLDAPMixin
from shared.views.autocomplete import Clipper
from .utils import create_member, create_root, create_user
@ -290,14 +290,30 @@ class RegistrationAutocompleteViewTests(MockLDAPMixin, ViewTestCaseMixin, TestCa
self.assertEqual(r.status_code, 200)
def extract(section):
return [r.verbose_name for r in section.entries]
others = []
members = []
clippers = []
for section in r.context["results"]:
if section.name == "others":
others = extract(section)
elif section.name == "members":
members = extract(section)
elif section.name == "clippers":
clippers = extract(section)
else:
raise ValueError("Unexpected section name: {}".format(section.name))
self.assertQuerysetEqual(
r.context["others"], map(repr, expected_others), ordered=False
others, map(str, expected_others), ordered=False, transform=str
)
self.assertQuerysetEqual(
r.context["members"], map(repr, expected_members), ordered=False,
members, map(str, expected_members), ordered=False, transform=str
)
self.assertCountEqual(
map(str, r.context["clippers"]), map(str, expected_clippers)
self.assertSetEqual(
set(clippers), set(map(LDAPSearch().result_verbose_name, expected_clippers))
)
def test_username(self):

View file

@ -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 cof_search
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 AutocompleteView, Select2QuerySetView
class HomeView(LoginRequiredMixin, TemplateView):
@ -942,9 +943,18 @@ class ConfigUpdate(FormView):
##
# For the admin site
class UserAutocomplete(Select2QuerySetView):
model = User
search_fields = ("username", "first_name", "last_name")
user_autocomplete = buro_required(UserAutocomplete.as_view())
class COFAutocompleteView(AutocompleteView):
template_name = "gestioncof/search_results.html"
search_composer = cof_search
registration_autocomplete = buro_required(COFAutocompleteView.as_view())