diff --git a/umap/autocomplete.py b/umap/autocomplete.py index c2bd02c0..537fa634 100644 --- a/umap/autocomplete.py +++ b/umap/autocomplete.py @@ -2,6 +2,7 @@ from agnocomplete.core import AgnocompleteModel from agnocomplete.register import register from django.conf import settings from django.contrib.auth import get_user_model +from django.db.models import Q @register @@ -13,3 +14,24 @@ class AutocompleteUser(AgnocompleteModel): data = super().item(current_item) data["url"] = current_item.get_url() return data + + def get_queryset_filters(self, query): + if len(query) <= 3 and self._force_exact: + conditions = Q() + for field_name in self.fields: + if not field_name[0].isalnum(): + field_name = field_name[1:] + # Force exact match + conditions |= Q(**{self._construct_qs_filter(f"={field_name}"): query}) + return conditions + + return super().get_queryset_filters(query) + + def build_filtered_queryset(self, query, **kwargs): + self._force_exact = len(query) <= 3 + qs = super().build_filtered_queryset(query, **kwargs) + if len(query) <= 3 and not len(qs): + # Not exact match, let's fallback to normal "startswith" query + self._force_exact = False + qs = super().build_filtered_queryset(query, **kwargs) + return qs diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index e13a9c9a..9a963c61 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -510,3 +510,18 @@ def test_can_combine_search_and_filter(client, map): url = reverse("search") response = client.get(url + "?q=dur&tags=bike") assert "Blé dur" in response.content.decode() + + +@pytest.mark.django_db +def test_can_find_small_usernames(client): + UserFactory(username="Joe") + UserFactory(username="JoeJoe") + url = "/agnocomplete/AutocompleteUser/" + response = client.get(url + "?q=joe") + data = json.loads(response.content)["data"] + assert len(data) == 1 + assert data[0]["label"] == "Joe" + response = client.get(url + "?q=joej") + data = json.loads(response.content)["data"] + assert len(data) == 1 + assert data[0]["label"] == "JoeJoe"