diff --git a/backend/BookShelf/settings.py b/backend/BookShelf/settings.py index 357ea14..686f8a8 100644 --- a/backend/BookShelf/settings.py +++ b/backend/BookShelf/settings.py @@ -83,6 +83,10 @@ ), 'DEFAULT_PAGINATION_CLASS': 'BookShelf.utilities.pagination.Pagination', 'PAGE_SIZE': 10, + 'DEFAULT_FILTER_BACKENDS': 'BookShelf.utilities.filters.SearchFilter', + # 'DEFAULT_FILTER_BACKENDS': [ + # 'rest_framework.filters.SearchFilter', + # ], } SIMPLE_JWT = { diff --git a/backend/BookShelf/utilities/filters.py b/backend/BookShelf/utilities/filters.py new file mode 100644 index 0000000..945021f --- /dev/null +++ b/backend/BookShelf/utilities/filters.py @@ -0,0 +1,33 @@ +from rest_framework.filters import BaseFilterBackend + + +class SearchFilter(BaseFilterBackend): + """ + A custom search filter that allows more flexible query handling. + """ + + def get_search_fields(self, view): + """ + Returns the search fields defined on the view. + """ + return getattr(view, 'search_fields', None) + + def filter_queryset(self, request, queryset, view): + """ + Perform custom filtering based on search fields and query parameters. + """ + search_fields = self.get_search_fields(view) + search_param = request.query_params.get( + 'search') # Default query param is `search` + + if not search_fields or not search_param: + return queryset # No search fields or query parameter, return unfiltered queryset # noqa + + # Build a query dynamically + from django.db.models import Q + query = Q() + for field in search_fields: + # Case-insensitive search + query |= Q(**{f"{field}__icontains": search_param}) + + return queryset.filter(query) diff --git a/backend/BookShelf/utilities/pagination.py b/backend/BookShelf/utilities/pagination.py index 5f36f98..386a419 100644 --- a/backend/BookShelf/utilities/pagination.py +++ b/backend/BookShelf/utilities/pagination.py @@ -18,3 +18,14 @@ def get_page_size(self, request): self.max_page_size ) return self.page_size + + # For customizing the paginated response + # def get_paginated_response(self, data): + # return Response({ + # 'total_count': self.page.paginator.count, + # 'total_pages': self.page.paginator.num_pages, + # 'current_page': self.page.number, + # 'next': self.get_next_link(), + # 'previous': self.get_previous_link(), + # 'results': data, + # }) diff --git a/backend/publisher_api/migrations/0003_alter_publisher_name.py b/backend/publisher_api/migrations/0003_alter_publisher_name.py new file mode 100644 index 0000000..7c6ca2c --- /dev/null +++ b/backend/publisher_api/migrations/0003_alter_publisher_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-11-28 20:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('publisher_api', '0002_publisher_added_by_publisher_added_date_time_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='publisher', + name='name', + field=models.CharField(db_index=True, max_length=255), + ), + ] diff --git a/backend/publisher_api/models.py b/backend/publisher_api/models.py index 4166a44..49aeb0b 100644 --- a/backend/publisher_api/models.py +++ b/backend/publisher_api/models.py @@ -2,7 +2,7 @@ class Publisher(models.Model): - name = models.CharField(max_length=255) + name = models.CharField(max_length=255, db_index=True) address = models.CharField(max_length=255, blank=True, null=True) website = models.URLField(blank=True, null=True) email = models.EmailField(blank=True, null=True) diff --git a/backend/publisher_api/views/v1.py b/backend/publisher_api/views/v1.py index 64a0f9b..b3624d4 100644 --- a/backend/publisher_api/views/v1.py +++ b/backend/publisher_api/views/v1.py @@ -3,6 +3,7 @@ from rest_framework import status from BookShelf.utilities.permissions import IsAdminOrModerator +from BookShelf.utilities.filters import SearchFilter from publisher_api.models import Publisher @@ -15,6 +16,9 @@ class PublisherViewSet(ModelViewSet): permission_classes = [ IsAdminOrModerator, ] + filter_backends = [SearchFilter] + search_fields = ['name'] + # search_param = 'q' # Default search query parameter is `search` # authentication_classes = [TokenAuthentication] def perform_create(self, serializer):