mirror of https://gitlab.crans.org/bde/nk20
Order note research results: match first aliases then normalized names
This commit is contained in:
parent
ca7f4791ed
commit
a9258c332a
|
@ -4,14 +4,15 @@
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.db.models import Q
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework import routers, serializers
|
from rest_framework import routers, serializers
|
||||||
from rest_framework.filters import SearchFilter
|
|
||||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
from rest_framework.viewsets import ReadOnlyModelViewSet
|
||||||
from activity.api.urls import register_activity_urls
|
from activity.api.urls import register_activity_urls
|
||||||
from api.viewsets import ReadProtectedModelViewSet
|
from api.viewsets import ReadProtectedModelViewSet
|
||||||
from member.api.urls import register_members_urls
|
from member.api.urls import register_members_urls
|
||||||
from note.api.urls import register_note_urls
|
from note.api.urls import register_note_urls
|
||||||
|
from note.models import Alias
|
||||||
from treasury.api.urls import register_treasury_urls
|
from treasury.api.urls import register_treasury_urls
|
||||||
from logs.api.urls import register_logs_urls
|
from logs.api.urls import register_logs_urls
|
||||||
from permission.api.urls import register_permission_urls
|
from permission.api.urls import register_permission_urls
|
||||||
|
@ -52,9 +53,47 @@ class UserViewSet(ReadProtectedModelViewSet):
|
||||||
"""
|
"""
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
serializer_class = UserSerializer
|
serializer_class = UserSerializer
|
||||||
filter_backends = [DjangoFilterBackend, SearchFilter]
|
filter_backends = [DjangoFilterBackend]
|
||||||
filterset_fields = ['id', 'username', 'first_name', 'last_name', 'email', 'is_superuser', 'is_staff', 'is_active', ]
|
filterset_fields = ['id', 'username', 'first_name', 'last_name', 'email', 'is_superuser', 'is_staff', 'is_active', ]
|
||||||
search_fields = ['$username', '$first_name', '$last_name', '$note__alias__name', '$note__alias__normalized_name', ]
|
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super().get_queryset().order_by("username")
|
||||||
|
|
||||||
|
if "search" in self.request.GET:
|
||||||
|
pattern = self.request.GET["search"]
|
||||||
|
|
||||||
|
# We match first a user by its username, then if an alias is matched without normalization
|
||||||
|
# And finally if the normalized pattern matches a normalized alias.
|
||||||
|
queryset = queryset.filter(
|
||||||
|
username__iregex="^" + pattern
|
||||||
|
).union(
|
||||||
|
queryset.filter(
|
||||||
|
Q(note__alias__name__iregex="^" + pattern)
|
||||||
|
& ~Q(username__iregex="^" + pattern)
|
||||||
|
), all=True).union(
|
||||||
|
queryset.filter(
|
||||||
|
Q(note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||||
|
& ~Q(note__alias__name__iregex="^" + pattern)
|
||||||
|
& ~Q(username__iregex="^" + pattern)
|
||||||
|
),
|
||||||
|
all=True).union(
|
||||||
|
queryset.filter(
|
||||||
|
Q(note__alias__normalized_name__iregex="^" + pattern.lower())
|
||||||
|
& ~Q(note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||||
|
& ~Q(note__alias__name__iregex="^" + pattern)
|
||||||
|
& ~Q(username__iregex="^" + pattern)
|
||||||
|
),
|
||||||
|
all=True).union(
|
||||||
|
queryset.filter(
|
||||||
|
(Q(last_name__iregex="^" + pattern) | Q(first_name__iregex="^" + pattern))
|
||||||
|
& ~Q(note__alias__normalized_name__iregex="^" + pattern.lower())
|
||||||
|
& ~Q(note__alias__normalized_name__iregex="^" + Alias.normalize(pattern))
|
||||||
|
& ~Q(note__alias__name__iregex="^" + pattern)
|
||||||
|
& ~Q(username__iregex="^" + pattern)
|
||||||
|
),
|
||||||
|
all=True)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
# This ViewSet is the only one that is accessible from all authenticated users!
|
# This ViewSet is the only one that is accessible from all authenticated users!
|
||||||
|
|
|
@ -180,9 +180,9 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
"""
|
"""
|
||||||
Filter the user list with the given pattern.
|
Filter the user list with the given pattern.
|
||||||
"""
|
"""
|
||||||
qs = super().get_queryset().distinct("pk").annotate(alias=F("note__alias__name"))\
|
qs = super().get_queryset().distinct("username").annotate(alias=F("note__alias__name"))\
|
||||||
.annotate(normalized_alias=F("note__alias__normalized_name"))\
|
.annotate(normalized_alias=F("note__alias__normalized_name"))\
|
||||||
.filter(profile__registration_valid=True)
|
.filter(profile__registration_valid=True).order_by("username")
|
||||||
if "search" in self.request.GET:
|
if "search" in self.request.GET:
|
||||||
pattern = self.request.GET["search"]
|
pattern = self.request.GET["search"]
|
||||||
|
|
||||||
|
@ -190,13 +190,16 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
return qs.none()
|
return qs.none()
|
||||||
|
|
||||||
qs = qs.filter(
|
qs = qs.filter(
|
||||||
Q(first_name__iregex=pattern)
|
username__iregex="^" + pattern
|
||||||
| Q(last_name__iregex=pattern)
|
).union(
|
||||||
| Q(profile__section__iregex=pattern)
|
qs.filter(
|
||||||
| Q(username__iregex=pattern)
|
(Q(alias__iregex="^" + pattern)
|
||||||
| Q(alias__iregex=pattern)
|
| Q(normalized_alias__iregex="^" + Alias.normalize(pattern))
|
||||||
| Q(normalized_alias__iregex=Alias.normalize(pattern))
|
| Q(last_name__iregex="^" + pattern)
|
||||||
)
|
| Q(first_name__iregex="^" + pattern)
|
||||||
|
| Q(email__istartswith=pattern))
|
||||||
|
& ~Q(username__iregex="^" + pattern)
|
||||||
|
), all=True)
|
||||||
else:
|
else:
|
||||||
qs = qs.none()
|
qs = qs.none()
|
||||||
|
|
||||||
|
|
|
@ -40,9 +40,19 @@ class NotePolymorphicViewSet(ReadOnlyProtectedModelViewSet):
|
||||||
|
|
||||||
alias = self.request.query_params.get("alias", ".*")
|
alias = self.request.query_params.get("alias", ".*")
|
||||||
queryset = queryset.filter(
|
queryset = queryset.filter(
|
||||||
Q(alias__name__regex="^" + alias)
|
name__iregex="^" + alias
|
||||||
| Q(alias__normalized_name__regex="^" + Alias.normalize(alias))
|
).union(
|
||||||
| Q(alias__normalized_name__regex="^" + alias.lower()))
|
queryset.filter(
|
||||||
|
Q(normalized_name__iregex="^" + Alias.normalize(alias))
|
||||||
|
& ~Q(name__iregex="^" + alias)
|
||||||
|
),
|
||||||
|
all=True).union(
|
||||||
|
queryset.filter(
|
||||||
|
Q(normalized_name__iregex="^" + alias.lower())
|
||||||
|
& ~Q(normalized_name__iregex="^" + Alias.normalize(alias))
|
||||||
|
& ~Q(name__iregex="^" + alias)
|
||||||
|
),
|
||||||
|
all=True)
|
||||||
|
|
||||||
return queryset.distinct()
|
return queryset.distinct()
|
||||||
|
|
||||||
|
@ -85,9 +95,19 @@ class AliasViewSet(ReadProtectedModelViewSet):
|
||||||
|
|
||||||
alias = self.request.query_params.get("alias", ".*")
|
alias = self.request.query_params.get("alias", ".*")
|
||||||
queryset = queryset.filter(
|
queryset = queryset.filter(
|
||||||
Q(name__regex="^" + alias)
|
name__iregex="^" + alias
|
||||||
| Q(normalized_name__regex="^" + Alias.normalize(alias))
|
).union(
|
||||||
| Q(normalized_name__regex="^" + alias.lower()))
|
queryset.filter(
|
||||||
|
Q(normalized_name__iregex="^" + Alias.normalize(alias))
|
||||||
|
& ~Q(name__iregex="^" + alias)
|
||||||
|
),
|
||||||
|
all=True).union(
|
||||||
|
queryset.filter(
|
||||||
|
Q(normalized_name__iregex="^" + alias.lower())
|
||||||
|
& ~Q(normalized_name__iregex="^" + Alias.normalize(alias))
|
||||||
|
& ~Q(name__iregex="^" + alias)
|
||||||
|
),
|
||||||
|
all=True)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
@ -108,13 +128,25 @@ class ConsumerViewSet(ReadOnlyProtectedModelViewSet):
|
||||||
queryset = super().get_queryset()
|
queryset = super().get_queryset()
|
||||||
|
|
||||||
alias = self.request.query_params.get("alias", ".*")
|
alias = self.request.query_params.get("alias", ".*")
|
||||||
|
queryset = queryset.order_by('name').prefetch_related('note')
|
||||||
|
# We match first an alias if it is matched without normalization,
|
||||||
|
# then if the normalized pattern matches a normalized alias.
|
||||||
queryset = queryset.filter(
|
queryset = queryset.filter(
|
||||||
Q(name__regex="^" + alias)
|
name__iregex="^" + alias
|
||||||
| Q(normalized_name__regex="^" + Alias.normalize(alias))
|
).union(
|
||||||
| Q(normalized_name__regex="^" + alias.lower()))\
|
queryset.filter(
|
||||||
.order_by('name').prefetch_related('note')
|
Q(normalized_name__iregex="^" + Alias.normalize(alias))
|
||||||
|
& ~Q(name__iregex="^" + alias)
|
||||||
|
),
|
||||||
|
all=True).union(
|
||||||
|
queryset.filter(
|
||||||
|
Q(normalized_name__iregex="^" + alias.lower())
|
||||||
|
& ~Q(normalized_name__iregex="^" + Alias.normalize(alias))
|
||||||
|
& ~Q(name__iregex="^" + alias)
|
||||||
|
),
|
||||||
|
all=True)
|
||||||
|
|
||||||
return queryset
|
return queryset.distinct()
|
||||||
|
|
||||||
|
|
||||||
class TemplateCategoryViewSet(ReadProtectedModelViewSet):
|
class TemplateCategoryViewSet(ReadProtectedModelViewSet):
|
||||||
|
|
|
@ -79,7 +79,7 @@ function refreshBalance () {
|
||||||
* @param fun For each found note with the matched alias `alias`, fun(note, alias) is called.
|
* @param fun For each found note with the matched alias `alias`, fun(note, alias) is called.
|
||||||
*/
|
*/
|
||||||
function getMatchedNotes (pattern, fun) {
|
function getMatchedNotes (pattern, fun) {
|
||||||
$.getJSON("/api/note/alias/?format=json&alias=" + pattern + "&search=user|club&ordering=normalized_name", fun);
|
$.getJSON("/api/note/alias/?format=json&alias=" + pattern + "&search=user|club", fun);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -261,9 +261,7 @@ function autoCompleteNote (field_id, note_list_id, notes, notes_display, alias_p
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$.getJSON("/api/note/consumer/?format=json&alias="
|
$.getJSON("/api/note/consumer/?format=json&alias=" + pattern + "&search=user|club",
|
||||||
+ pattern
|
|
||||||
+ "&search=user|club&ordering=normalized_name",
|
|
||||||
function (consumers) {
|
function (consumers) {
|
||||||
// The response arrived too late, we stop the request
|
// The response arrived too late, we stop the request
|
||||||
if (pattern !== $("#" + field_id).val())
|
if (pattern !== $("#" + field_id).val())
|
||||||
|
|
Loading…
Reference in New Issue