Repository: inventree/inventree
Issue: [BUG] Filtering "owner" fields in API forms is broken

**Describe the bug**

Any field in an API form which references an "owner" (e.g. "user" or "group") cannot be filtered by entering search text. The search text has no effect and *all* results are always displayed.

**To Reproduce**
Steps to reproduce the behavior:
1. Edit a model which has an "owner" (e.g. "Edit Purchase Order")
2. Enter text into the "responsible" field
3. Results are not filtered by the input value

**Expected behavior**
Results should be filtered by the input string (using select2 AJAX calls)

**Deployment Method**
- [x] Docker
- [x] Bare Metal

**Extra Notes**

Cannot (yet) work out how to add "name" in the `search_fields` section in `users/api.py` - this is because the "owner" field is a generic foreign key relationship...

Changed files:
InvenTree/users/api.py

diff --git a/InvenTree/users/api.py b/InvenTree/users/api.py
index 240d6aabc..222f284ad 100644
--- a/InvenTree/users/api.py
+++ b/InvenTree/users/api.py
@@ -7,15 +7,16 @@ from django.core.exceptions import ObjectDoesNotExist
 
 from django.conf.urls import url, include
 
-from rest_framework import generics, permissions
+from django_filters.rest_framework import DjangoFilterBackend
+
+from rest_framework import filters, generics, permissions
 from rest_framework.views import APIView
 from rest_framework.authtoken.models import Token
 from rest_framework.response import Response
 from rest_framework import status
 
-from .serializers import UserSerializer, OwnerSerializer
-
-from .models import RuleSet, Owner, check_user_role
+from users.models import RuleSet, Owner, check_user_role
+from users.serializers import UserSerializer, OwnerSerializer
 
 
 class OwnerList(generics.ListAPIView):
@@ -26,6 +27,37 @@ class OwnerList(generics.ListAPIView):
     queryset = Owner.objects.all()
     serializer_class = OwnerSerializer
 
+    def filter_queryset(self, queryset):
+        """
+        Implement text search for the "owner" model.
+
+        Note that an "owner" can be either a group, or a user,
+        so we cannot do a direct text search.
+
+        A "hack" here is to post-process the queryset and simply
+        remove any values which do not match.
+
+        It is not necessarily "efficient" to do it this way,
+        but until we determine a better way, this is what we have...
+        """
+
+        search_term = str(self.request.query_params.get('search', '')).lower()
+
+        queryset = super().filter_queryset(queryset)
+
+        if not search_term:
+            return queryset
+
+        results = []
+
+        # Extract search term f
+
+        for result in queryset.all():
+            if search_term in result.name().lower():
+                results.append(result)
+
+        return results
+
 
 class OwnerDetail(generics.RetrieveAPIView):
     """
@@ -96,6 +128,17 @@ class UserList(generics.ListAPIView):
     serializer_class = UserSerializer
     permission_classes = (permissions.IsAuthenticated,)
 
+    filter_backends = [
+        DjangoFilterBackend,
+        filters.SearchFilter,
+    ]
+
+    search_fields = [
+        'first_name',
+        'last_name',
+        'username',
+    ]
+
 
 class GetAuthToken(APIView):
     """ Return authentication token for an authenticated user. """