Sachihiro
Sachihiro

Reputation: 1793

Django: Paginator returns all the data from db, and ordering is not working

I have this ListView and i am trying to get only 12 cars from my db, and order them by price, i have 20 entries in my db and in the buttons of pagination it shows 6 buttons, aka 6 pages, so it is returning all possible data from db, at this point I am lost and can't find the bug, any help would be very much appreciated for both, pagination and ordering.

class CardListView(ListView):
    model = Car
    template_name = 'home.html'
    context_object_name = 'cars'
    ordering = ['-price']
    paginate_by = 5
    limit = 12

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        paginator = context['paginator']
        page_numbers_range = 10 
        max_index = len(paginator.page_range)

        page = self.request.GET.get('page')
        current_page = int(page) if page else 1

        start_index = int((current_page - 1) / page_numbers_range) * page_numbers_range
        end_index = start_index + page_numbers_range
        if end_index >= max_index:
            end_index = max_index

        page_range = paginator.page_range[start_index:end_index]
        cars = Car.objects.all()[:self.limit]
        car_types = CarCategory.objects.all()

        context['cars'] = cars

        context['car_types'] = car_types
        context['page_range'] = page_range
        return context

Upvotes: 1

Views: 59

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477190

You do not need to do the pagination logic by yourself, you only should implement in the get_context_data the additional elements you want to pass to the template. The pagination logic is handled by the ListView itself. If you want to limit the queryset, you should do that in the get_queryset(..) [Django-doc] function:

class CardListView(ListView):
    model = Car
    template_name = 'home.html'
    context_object_name = 'cars'
    ordering = ['-price']
    paginate_by = 5
    limit = 12

    def get_queryset(self):
        return super().get_queryset()[:self.limit]

    def get_context_data(self, **kwargs):
        context = super().get_context_data()  # with paginated queryset
        context['car_types'] = car_types = CarCategory.objects.all()
        return context

The original ListView implementation will call the get_queryset, and then pass it to the proper paginator. By using super() we furthermore do not need to care about the ordering, etc. These are all handled by the ListView itself.

Upvotes: 2

Related Questions