drf-haystack
drf-haystack copied to clipboard
get_queryset() error with Django pagination
Hi there,
I'm using Haystack with the DRF and I noticed that when I added the get_serializer_class to my Haystack viewset, the pagination returned {"detail": "Invalid page."}
for every page other than 1.
I want to return a custom serializer dependent on the user's authentication.
Here is my viewset:
class SearchViewSet(HaystackViewSet):
throttle_classes = (SearchThrottle,)
permission_classes = (AllowAny,)
def get_serializer_class(self):
if self.request.user.is_anonymous:
return PublicSearchSerializer
else:
return SearchSerializer
I saw that in the DRF for pagination they have this method to paginate a queryset..
invalid_page_message = _('Invalid page.')
def paginate_queryset(self, queryset, request, view=None):
"""
Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view.
"""
page_size = self.get_page_size(request)
if not page_size:
return None
paginator = self.django_paginator_class(queryset, page_size)
page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = paginator.num_pages
try:
self.page = paginator.page(page_number)
except InvalidPage as exc:
msg = self.invalid_page_message.format(
page_number=page_number, message=six.text_type(exc)
)
raise NotFound(msg)
if paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True
self.request = request
return list(self.page)
so self.page = paginator.page(page_number)
is failing and that relies on the core paginator from Django which I guess it not at fault?
I saw that Haystack's get_queryset() in HaystackGenericAPIView looks like this:
def get_queryset(self, index_models=[]):
"""
Get the list of items for this view.
Returns ``self.queryset`` if defined and is a ``self.object_class``
instance.
@:param index_models: override `self.index_models`
"""
if self.queryset is not None and isinstance(self.queryset, self.object_class):
queryset = self.queryset.all()
else:
queryset = self.object_class()._clone()
if len(index_models):
queryset = queryset.models(*index_models)
elif len(self.index_models):
queryset = queryset.models(*self.index_models)
return queryset
Could it be that this is not correctly passing the queryset to the pagination?
I'm using the following Django paginator class in my settings:
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': int(os.getenv('DJANGO_PAGINATION_LIMIT', 10)),
Apologies if this was long-winded - first time creating an issue.
Hey, thanks for the detailed error report. I'll have a look!
It seems this is an issue within Haystack itself: https://github.com/django-haystack/django-haystack/issues/1586
Oddly I also get this is if I add ?page=1
to the query string but not if I leave the query string empty.
I thought I'd report back what my problem was as I think it's probably the same as this issue.
Anything in the query string is being used in the FilterQueryBuilder
including the page
parameter to filter the queryset.
Adding exclude = ['page']
to my serializer has fixed this in the short term for me.