Django - 实现简单分页

# Pagination


>以下代码摘自 Django 官方文档


[Django Pagination 的官方文档](https://docs.djangoproject.com/en/2.0/topics/pagination/)


Django 提供了几个类, 可以帮助您管理分页数据 - 也就是说,通过 "上一个 / 下一个" 链接分割多个页面的数据, 这些类放在 `django/core/ paginator.py`中。


## 例子


```
>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']


>>> p = Paginator(objects, 2) # 2 条数据为一页, 实例化分页对象
>>> p.count  # 对象一共 4 个元素
4
>>> p.num_pages # 对象分为 4 页
2
>>> type(p.page_range) # 类型
<class 'range'>
>>> p.page_range # 对象页的可迭代范围
range(1, 3)


>>> page1 = p.page(1) # 取对象的第一分页对象
>>> page1 # 第一页分页对象的元素列表
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']


>>> page2 = p.page(2) # 取对象的第二页分页对象
>>> page2.object_list # 第二页分页对象的元素列表
['george', 'ringo']


>>> page2.has_next() # 第二页分页对象有下一页对象吗
False
>>> page2.has_previous() # 第二页分页对象是否还有前一页
True
>>> page2.has_other_pages() # 第二页分页对象是否还有其他页
True
>>> page2.nex_page_number() # 第二页分页对象下一页的页码, 因为没了, 所以报错
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'Page' object has no attribute 'nex_page_number'


>>> page2.previous_page_number() # 第二页分页对象的上一页码值
1
>>> page2.start_index() # 第二页分页对象开始的索引
3
>>> page2.end_index() # 第二页分页对象结束的索引
4
>>> page1.start_index() # 第一页分页对象开始的索引, 注意: 索引是从 1 开始的
1
>>> page1.end_index() # 第一页分页对象开始的索引
```


## 在视图中使用 Paginator


下面是视图代码:


```
from django.shortcuts import render
from django.http import HttpResponse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


from .models import HeroInfo


def listing(request):
    hero_list = HeroInfo.objects.all()
    paginator = Paginator(hero_list, 5)  # 每页显示五个元素


    page = request.GET.get('page')


    try:
        heros = paginator.page(page)
    except PageNotAnInteger:  # 如果页码不是整数, 则显示第一页
        heros = paginator.page(1)
    except EmptyPage: # 如果页码超出范围, 则显示最后一页
        heros = paginator.page(paginator.num_pages)
    return render(request, 'herolist.html', {'heros': heros})




```


html 代码:


不过这里还有个 bug, 就是在最后一页的时候, 点击上一页, 显示的确是第一页的内容.


```
{% load static %}<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hero</title>
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>


{#遍历hero列表, 显示元素信息 #}
<ul>
    {% for hero in heros %}
        <li>{{ hero.name }}</li>
    {% endfor %}
</ul>


<div class="pagination">
    <span class="step-links">
        {% if heros.has_previous %} {# 判断是否还有上一页 #}
            <a href="?page=1">&laquo; 第一页</a>
            <a href="?page{{ heros.previous_page_number }}">上一页</a>
        {% endif %}


        <span class="current">
            Page {{ heros.number }} of {{ heros.paginator.num_pages }}.
        </span>


        {% if heros.has_next %}
            <a href="?page={{ heros.next_page_number }}">下一页</a>
            <a href="?page={{ heros.paginator.num_pages }}">最后 &laquo;</a>
        {% endif %}
    </span>
</div>


</body>
</html>
```


urls 代码:


```
from django.conf.urls import url
from booktest import views


urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^listing/$', views.listing, name='listing'),
]
```


大概就是这么个效果:


![分页效果1](https://i.imgur.com/o99cd5z.png)


![分页效果2](https://i.imgur.com/CXou49N.png)


![分页效果3](https://i.imgur.com/ChfyqSL.png)
### 如何在 Django REST framework 中使用分页 为了实现Django REST framework (DRF) 中的分页功能,可以按照如下方法进行设置: #### 配置全局分页选项 可以在项目的 `settings.py` 文件中指定默认的分页类以及每页显示的最大项数。这使得在整个应用程序范围内统一处理分页逻辑变得简单。 ```python # settings.py REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 10, } ``` 上述配置选择了 `LimitOffsetPagination` 类作为默认分页机制,并设定了页面大小为 10 条记录[^3]。 对于更灵活的需求,还可以考虑其他类型的内置分页器如 `PageNumberPagination` 或者创建自定义分页器来满足特定场景下的要求[^5]。 #### 使用标准视图中的分页支持 当采用 DRF 提供的标准视图(例如基于类的通用视图或视图集)时,默认情况下会自动应用所设定好的分页行为;然而如果是通过普通的 APIView 实现,则需手动调用分页 API 才能获得相同效果。 下面是一个简单的例子展示了如何在一个列表视图里启用分页特性: ```python from rest_framework import generics from myapp.models import MyModel from myapp.serializers import MyModelSerializer class MyModelListView(generics.ListAPIView): queryset = MyModel.objects.all() serializer_class = MyModelSerializer ``` 在这个案例中,由于继承了 `generics.ListAPIView` ,因此无需额外编码即可享受已配置好分页带来的便利。 如果想要进一步定制化分页的表现形式,比如改变链接结构或是调整响应体的内容布局等,可以通过重写现有的分页器或者新建子类来自定义所需的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值