Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#14873 closed (fixed)

A paginated ListView with a List instead of queryset produces an error

Reported by: andornaut Owned by: nobody
Component: Generic views Version: 1.3-alpha
Severity: Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Background

This issue occurs when using a subclass of ListView that overrides the get_queryset method and returns a List instead of a queryset, while also defining paginage_by. This should work according to the docstring for get_queryset, but it produces an exception.

Relevant Code

django.views.generic.list.MultipleObjectMixin.get_queryset#15

    def get_queryset(self):
        """
        Get the list of items for this view. This must be an interable, and may
        be a queryset (in which qs-specific behavior will be enabled).

django.views.generic.list.MultipleObjectMixin.paginate_queryset#31

    def paginate_queryset(self, queryset, page_size):
        """
        Paginate the queryset, if needed.
        """
        if queryset.count() > page_size:

The error occurs when trying to evaluate queryset.count() on a List.

Possible Solution

If a non-queryset Iterable is used, then use len(queryset) instead of queryset.count()

Change History (4)

comment:1 Changed 4 years ago by SmileyChris

  • milestone set to 1.3
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 4 years ago by andornaut

Another (and preferable, IMO) suggested fix:

In django.views.generic.list.MultipleObjectMixin.paginate_queryset#35

Replace this:

if queryset.count() > page_size:

With this:

if hasattr(self, 'paginate_by') and self.paginate_by:

Currently, the pagination-related context variables page_obj and paginator (line 91 of the same module) are only included if the number of pages is greater than 1. This requires that the template author handle this case in templates that use page_obj.has_next and other variables. Previously (IIRC), in Django 1.2's function-based generic views, the template author could count on those variables always being present, and so s/he didn't have to handle the special case where there is only 1 page. I believe that it would be preferable for paginator and page_obj to be present if the user specifies that they want to use a pagination by setting paginate_by. This also, coincidentally, resolves the issue mentioned in this ticket.

comment:3 Changed 4 years ago by SmileyChris

  • Resolution set to fixed
  • Status changed from new to closed

(In [14864]) Fixes #14873 -- A paginated ListView with a List instead of queryset produces an error.

Additional minor change in functionality: the page is now not considered paginated if the objects do not span multiple pages according to the paginator. This will only affect views with a custom paginator method which uses orphans.

comment:4 Changed 4 years ago by jacob

  • milestone 1.3 deleted

Milestone 1.3 deleted

Note: See TracTickets for help on using tickets.
Back to Top