Django分页教程及示例

2025-04-07T15:33:37+08:00 | 4分钟阅读 | 更新于 2025-04-07T15:33:37+08:00

Macro Zhao

Django分页教程及示例

推荐超级课程:

@TOC

Django的分页模块允许你将大量数据分割成更小的块(页面)。这对于以可管理的方式显示项目列表,如博客文章或产品,特别有用。让我们深入探讨如何逐步实现分页。

  1. 什么是分页? ======================

分页是将大型数据集分成更小的集合或页面的过程。每个页面包含有限数量的项目,用户可以浏览不同的页面。

  1. 设置Django项目 =======================

首先,创建并激活虚拟环境,以及创建Django项目和应用,如果你还没有的话。

mkdir myproject  
cd myproject  
  
python -m venv venv # 创建虚拟环境  
source venv\bin\activate # 激活虚拟环境  
  
django-admin startproject myproject .  
python manage.py startapp myapp

更新settings.py中的INSTALLED_APPS以包含应用:

INSTALLED_APPS = [  
    # 其他应用  
    'myapp',  
]
  1. 设置模型 ====================

让我们创建一个简单的Post模型来显示分页内容。

# myapp/models.py  
from django.db import models  
  
  
class Post(models.Model):  
    title = models.CharField(max_length=200)  
    content = models.TextField()  
  
    def __str__(self):  
        return self.title

现在,进行迁移并迁移模型:

python manage.py makemigrations  
python manage.py migrate

你也可以在Django管理面板中添加一些示例数据或使用shell

python manage.py shell
from myapp.models import Post  
  
for i in range(1, 101):  
    Post.objects.create(title=f"文章{i}", content=f"文章{i}的内容")
  1. 创建带分页的视图 ==================================

Django提供了Paginator类来处理分页。让我们创建一个视图来对Post对象进行分页。

# myapp/views.py  
from django.core.paginator import Paginator  
from django.shortcuts import render  
from .models import Post  
  
  
def post_list(request):  
    posts = Post.objects.all()  
    paginator = Paginator(posts, 10)  # 每页显示10篇帖子。  
      
    page_number = request.GET.get('page')  
    page_obj = paginator.get_page(page_number)  
      
    return render(request, 'myapp/post_list.html', {'page_obj': page_obj})

在这里,我们使用PaginatorPost对象分成每页10篇的页面。我们还从URL查询参数中获取page_number(例如?page=2等),并将page_obj传递给模板。

  1. 在模板中使用分页 ================================

现在,让我们创建一个模板来显示分页后的帖子。

<!-- myapp/templates/myapp/post_list.html -->  
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>分页帖子列表</title>  
</head>  
<body>  
    <h1>分页帖子</h1>  
  
    <ul>  
        {% for post in page_obj %}  
            <li>{{ post.title }}</li>  
        {% endfor %}  
    </ul>  
  
    <div class="pagination">  
        <span>  
            第{{ page_obj.number }}页,共{{ page_obj.paginator.num_pages }}页  
        </span>  
  
        {% if page_obj.has_previous %}  
            <a href="?page=1">首页</a>  
            <a href="?page={{ page_obj.previous_page_number }}">上一页</a>  
        {% endif %}  
  
        {% for num in page_obj.paginator.page_range %}  
            {% if page_obj.number == num %}  
                <strong>{{ num }}</strong>  
            {% else %}  
                <a href="?page={{ num }}">{{ num }}</a>  
            {% endif %}  
        {% endfor %}  
  
        {% if page_obj.has_next %}  
            <a href="?page={{ page_obj.next_page_number }}">下一页</a>  
            <a href="?page={{ page_obj.paginator.num_pages }}">末页</a>  
        {% endif %}  
    </div>  
</body>  
</html>

说明:

  • for循环显示page_obj中的每个帖子标题。
  • 我们创建分页控件,显示:
  • 如果有上一页,则显示首页和上一页按钮。
  • 页码和当前页高亮显示。
  • 如果有更多页,则显示下一页和末页按钮。
  1. 处理边缘情况 ======================

  2. 空页:当用户请求不存在的页面时(例如page=1000),Django会引发EmptyPage异常。你可以在视图中处理这个情况:

# myapp/views.py  
from django.core.paginator import EmptyPage, PageNotAnInteger  
  
def post_list(request):  
    posts = Post.objects.all()  
    paginator = Paginator(posts, 10)  
      
    page_number = request.GET.get('page')  
    try:  
        page_obj = paginator.get_page(page_number)  
    except PageNotAnInteger:  
        page_obj = paginator.page(1)  
    except EmptyPage:  
        page_obj = paginator.page(paginator.num_pages)  
      
    return render(request, 'myapp/post_list.html', {'page_obj': page_obj})

2. 性能考虑:在处理大型数据集时,分页查询可能会变得缓慢。考虑使用 select_relatedprefetch_related 来减少在处理相关模型时的数据库访问次数。

  1. 最终示例 ================

让我们把所有内容整合起来:

  1. 模型Post 模型被定义用于存储文章标题和内容。
  2. 视图post_list 视图使用 Django 的分页功能将文章分为每页10篇。
  3. 模板:模板显示文章并包含分页控制,带有用于在页面间导航的链接。

完整代码示例:

  1. 模型(models.py
# myapp/views.py  
from django.db import models  
  
  
class Post(models.Model):  
    title = models.CharField(max_length=200)  
    content = models.TextField()  
  
    def __str__(self):  
        return self.title
  1. 视图(views.py
# myapp/views.py  
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger  
from django.shortcuts import render  
from .models import Post  
  
def post_list(request):  
    posts = Post.objects.all()  
    paginator = Paginator(posts, 10)  
      
    page_number = request.GET.get('page')  
    try:  
        page_obj = paginator.get_page(page_number)  
    except PageNotAnInteger:  
        page_obj = paginator.page(1)  
    except EmptyPage:  
        page_obj = paginator.page(paginator.num_pages)  
      
    return render(request, 'myapp/post_list.html', {'page_obj': page_obj})
  1. 模板(post_list.html
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>分页文章列表</title>  
</head>  
<body>  
    <h1>分页文章</h1>  
  
    <ul>  
        {% for post in page_obj %}  
            <li>{{ post.title }}</li>  
        {% endfor %}  
    </ul>  
  
    <div class="pagination">  
        <span>  
            第 {{ page_obj.number }} 页,共 {{ page_obj.paginator.num_pages }} 页  
        </span>  
  
        {% if page_obj.has_previous %}  
            <a href="?page=1">首页</a>  
            <a href="?page={{ page_obj.previous_page_number }}">上一页</a>  
        {% endif %}  
  
        {% for num in page_obj.paginator.page_range %}  
            {% if page_obj.number == num %}  
                <strong>{{ num }}</strong>  
            {% else %}  
                <a href="?page={{ num }}">{{ num }}</a>  
            {% endif %}  
        {% endfor %}  
  
        {% if page_obj.has_next %}  
            <a href="?page={{ page_obj.next_page_number }}">下一页</a>  
            <a href="?page={{ page_obj.paginator.num_pages }}">末页</a>  
        {% endif %}  
    </div>  
</body>  
</html>

结论

本教程涵盖了 Django 分页的基础知识及示例。分页在处理大型数据集时对于改善用户体验至关重要。感谢您的阅读!如果您发现任何错误或有改进建议,请在下方留言。

© 2011 - 2025 Macro Zhao的分享站

关于我

如遇到加载502错误,请尝试刷新😄

Hi,欢迎访问 Macro Zhao 的博客。Macro Zhao(或 Macro)是我在互联网上经常使用的名字。

我是一个热衷于技术探索和分享的IT工程师,在这里我会记录分享一些关于技术、工作和生活上的事情。

我的CSDN博客:
https://macro-zhao.blog.csdn.net/

欢迎你通过评论或者邮件与我交流。
Mail Me

推荐好玩(You'll Like)
  • AI 动·画
    • 这是一款有趣·免费的能让您画的画中的角色动起来的AI工具。
    • 支持几十种动作生成。
我的项目(My Projects)
  • 爱学习网

  • 小乙日语App

    • 这是一个帮助日语学习者学习日语的App。
      (当然初衷也是为了自用😄)
    • 界面干净,简洁,漂亮!
    • 其中包含 N1 + N2 的全部单词和语法。
    • 不需注册,更不需要订阅!完全免费!
  • 小乙日文阅读器

    • 词汇不够?照样能读日语名著!
    • 越读积累越多,积跬步致千里!
    • 哪里不会点哪里!妈妈再也不担心我读不了原版读物了!
赞助我(Sponsor Me)

如果你喜欢我的作品或者发现它们对你有所帮助,可以考虑给我买一杯咖啡 ☕️。这将激励我在未来创作和分享更多的项目和技术。🦾

👉 请我喝一杯咖啡

If you like my works or find them helpful, please consider buying me a cup of coffee ☕️. It inspires me to create and share more projects in the future. 🦾

👉 Buy me a coffee