Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_queryset() error with Django pagination #123

Open
isaacjoy opened this issue Apr 2, 2018 · 4 comments
Open

get_queryset() error with Django pagination #123

isaacjoy opened this issue Apr 2, 2018 · 4 comments
Labels

Comments

@isaacjoy
Copy link

isaacjoy commented Apr 2, 2018

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.

@rhblind
Copy link
Owner

rhblind commented Apr 2, 2018

Hey, thanks for the detailed error report. I'll have a look!

@rhblind rhblind added the bug label Apr 2, 2018
@isaacjoy
Copy link
Author

isaacjoy commented Apr 3, 2018

It seems this is an issue within Haystack itself: django-haystack/django-haystack#1586

@bentappin
Copy link

Oddly I also get this is if I add ?page=1 to the query string but not if I leave the query string empty.

@bentappin
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants