Repository: mathesar-foundation/mathesar

Issue:
Implement filters for the table list API
**Problem**
<!-- Please provide a clear and concise description of the problem that this feature request is designed to solve.-->
Users should be able to filter tables by name.

**Proposed solution**
<!-- A clear and concise description of your proposed solution or feature. -->
Table list API should take a name filter parameter.

**Additional context**
<!-- Add any other context or screenshots about the feature request here.-->
We should use `django-filter` for this.


Discussion:

Resolving patch:
diff --git a/config/settings.py b/config/settings.py
--- a/config/settings.py
+++ b/config/settings.py
@@ -39,6 +39,7 @@
     "django.contrib.messages",
     "django.contrib.staticfiles",
     "rest_framework",
+    "django_filters",
     "mathesar",
 ]
 
diff --git a/mathesar/filters.py b/mathesar/filters.py
new file mode 100644
--- /dev/null
+++ b/mathesar/filters.py
@@ -0,0 +1,15 @@
+from django_filters import rest_framework as filters
+
+from mathesar.models import Table
+
+
+class CharInFilter(filters.BaseInFilter, filters.CharFilter):
+    pass
+
+
+class TableFilter(filters.FilterSet):
+    name = CharInFilter(field_name='name', lookup_expr='in')
+
+    class Meta:
+        model = Table
+        fields = ['name']
diff --git a/mathesar/views/api.py b/mathesar/views/api.py
--- a/mathesar/views/api.py
+++ b/mathesar/views/api.py
@@ -2,6 +2,7 @@
 from rest_framework.exceptions import NotFound, ValidationError
 from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin
 from rest_framework.response import Response
+from django_filters import rest_framework as filters
 
 from mathesar.database.utils import get_non_default_database_keys
 from mathesar.models import Table, Schema, DataFile
@@ -9,6 +10,7 @@
 from mathesar.serializers import TableSerializer, SchemaSerializer, RecordSerializer, DataFileSerializer
 from mathesar.utils.schemas import create_schema_and_object
 from mathesar.utils.api import create_table_from_datafile
+from mathesar.filters import TableFilter
 
 
 class SchemaViewSet(viewsets.GenericViewSet, ListModelMixin, RetrieveModelMixin):
@@ -27,6 +29,8 @@ class TableViewSet(viewsets.GenericViewSet, ListModelMixin, RetrieveModelMixin,
     queryset = Table.objects.all().order_by('-created_at')
     serializer_class = TableSerializer
     pagination_class = DefaultLimitOffsetPagination
+    filter_backends = (filters.DjangoFilterBackend,)
+    filterset_class = TableFilter
 
     def create(self, request):
         serializer = TableSerializer(data=request.data,


Test patch:
diff --git a/mathesar/tests/views/api/test_table_api.py b/mathesar/tests/views/api/test_table_api.py
--- a/mathesar/tests/views/api/test_table_api.py
+++ b/mathesar/tests/views/api/test_table_api.py
@@ -78,6 +78,30 @@ def test_table_list(create_table, client):
     check_table_response(response_table, table, table_name)
 
 
+def test_table_list_filter(create_table, client):
+    tables = {
+        'Nasa Table List Filter': create_table('Nasa Table List Filter'),
+        'Filler Table 1': create_table('Filler Table 1'),
+        'Filler Table 2': create_table('Filler Table 2')
+    }
+
+    filter_tables = ['Nasa Table List Filter', 'Filler Table 1']
+    query_str = ','.join(filter_tables)
+
+    response = client.get(f'/api/v0/tables/?name={query_str}')
+    response_data = response.json()
+    assert response.status_code == 200
+    assert response_data['count'] == 2
+    assert len(response_data['results']) == 2
+
+    response_tables = {res['name']: res for res in response_data['results']}
+    for table_name in filter_tables:
+        assert table_name in response_tables
+        table = tables[table_name]
+        response_table = response_tables[table_name]
+        check_table_response(response_table, table, table_name)
+
+
 def test_table_detail(create_table, client):
     """
     Desired format: