Как создать пользовательский класс разбиения на страницы с номерами страниц?

#python #django #pagination

Вопрос:

Я пытаюсь создать пользовательский класс разбиения на страницы. Вот моя попытка:

 class CustomPagination(PageNumberPagination):
    
    page_item_count = 10
    page = 1

    def get_paginated_response(self, data):
        
        page = self.page
        next_page = None
        previous_page = None

        if page.has_next():
            next_page = page.next_page_number()
        
        if page.has_previous():
            previous_page = page.previous_page_number()

        return Response({
            "page_count": page.count,
            "result_count": len(data),
            "next": next_page,
            "previous": previous_page,
            "has_next_page": page.has_next(),
            "has_previous_page": page.has_previous(),
            "result": data,
        })
 

Этот код сейчас работает неправильно, и это не то, что я хочу.

Я хочу задать параметр queryset с запросом в виде page_item_count и страницы.

Я хочу вернуть что-то подобное:

 return Response({
    "page_count": page.count,    # Page count. i.e. there are 100 items, and we show 10 per page, then it must be 10.
    "result_count": len(data),   # object count. i.e. 100
    "next": next_page,    # Next page number. It's a number like 2,3,4,5... Not a link
    "previous": previous_page,    # Prev page number, like 2,3,....
    "has_next_page": page.has_next(),    # boolean
    "has_previous_page": page.has_previous(),    # boolean
    "result": data,    # objects to be returned
})
 

Как я могу этого достичь?

Ответ №1:

Вот решение, которое вы ищете. Вам не нужно ничего делать в представлениях. Вы можете напрямую использовать встроенную в Django разбивку на страницы в своем шаблоне. вот ссылка

  <!-- Pagination-->
                        <ul class="pagination justify-content-center mb-4">
                            {% if page_obj.has_previous %}
                            <li class="page-item"><a class="page-link" href="?page=1">First Page</a></li>
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.previous_page_number }}">← Back</a></li>
                            {% endif %}
    
                            {% if page_obj.has_next %}
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}">Next Page →</a></li>
                            
                            {% endif %}
    
                            {% for i in paginator.page_range %}
                            {% if page_obj.number == i %}
                            <li class="page-item"><a class="page-link" href="#!">{{ i }}</a></li>
                              
                            {% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %} #change number as your requirement. such as if you have 50 page and how many page number you want to show per page.   
                            <li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
                            {%endif%}
                            {% endfor %}
    
                            <li class="page-item"><a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last Page</a></li>
                        </ul>
                    </div>
              
 

Ответ №2:

Вам не нужно использовать другое имя для атрибутов разбиения на страницы DRF:

 class CustomPagination(PageNumberPagination):
    page_size = 100  # this is equivalent to your 'page_item_count'
    page_size_query_param = 'page_item_count' # this sets the param name for the page size
    max_page_size = 1000
 

Чтобы переопределить разбитый на страницы ответ, вы можете:

     def get_paginated_response(self, data):
        """
        PageNumberPagination response override
        """
        return Response(OrderedDict([
            ('page_count', self.get_page_size(self.request)), # total # on current page
            ('page_number', int(self.request.query_params.get(self.page_query_param, 1))),
            ('result_count', self.page.paginator.count),     # total # of objects that will be paginated
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('results', data)
        ]))
 

На самом деле вам не нужно добавлять логическое поле в ответ, чтобы проверить, есть ли в нем следующая страница, так как полей next и previous достаточно.