Django学习之旅--第12课:Django分页与性能优化实战 - 从数据加载到系统提速

当平台数据量增长到一定规模,简单的全量查询和页面渲染会导致加载缓慢、用户体验下降。本节课将聚焦分页机制与性能优化,通过Django内置分页工具实现数据分批加载,结合数据库查询优化、缓存策略和前端优化技巧,全面提升系统响应速度,确保平台在数据量增长时仍能保持高效运行。

一、Django分页核心组件与基础实现

分页的核心是将大量数据拆分为多个页面加载,减少单次数据传输量。Django提供了PaginatorPage两个核心类,简化分页逻辑实现。

1.1 分页核心组件解析

  • Paginator:负责将数据集合分页

    • 核心参数:object_list(需分页的数据,如QuerySet)、per_page(每页条数)
    • 核心方法:page(number)(获取指定页码的数据页)
  • Page:表示单个分页页面

    • 常用属性:object_list(当前页数据)、number(当前页码)、paginator(关联的Paginator对象)
    • 常用方法:has_next()(是否有下一页)、has_previous()(是否有上一页)、next_page_number()/previous_page_number()(获取下/上一页页码)

1.2 服务列表分页实现(传统分页)

以服务列表为例,实现基础分页功能,支持筛选条件与页码联动。

1.2.1 视图层:处理分页逻辑
# services/views.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from .models import Service

def service_list(request):
    """服务列表页:支持分类筛选、关键词搜索和分页"""
    # 1. 获取查询参数(分类、搜索关键词、页码)
    category = request.GET.get('category', '')  # 分类筛选
    search_query = request.GET.get('q', '')     # 关键词搜索
    page_num = request.GET.get('page')          # 页码

    # 2. 构建基础查询集(只查询活跃服务)
    services = Service.objects.filter(is_active=True)

    # 3. 应用筛选条件(保留筛选状态,与分页联动)
    if category:
        services = services.filter(category=category)
    if search_query:
        services = services.filter(
            Q(name__icontains=search_query) | Q(description__icontains=search_query)
        )

    # 4. 分页处理(每页12条数据,按创建时间倒序)
    paginator = Paginator(services.order_by('-created_at'), 12)
    try:
        services_page = paginator.page(page_num)  # 获取指定页数据
    except PageNotAnInteger:
        services_page = paginator.page(1)  # 页码不是整数时返回第1页
    except EmptyPage:
        services_page = paginator.page(paginator.num_pages)  # 页码超出范围时返回最后一页

    # 5. 传递数据到模板(包含分页对象和筛选参数)
    context = {
   
   
        'services': services_page,  # 分页后的当前页数据
        'category_filter': category,  # 当前分类筛选条件(用于模板回显)
        'search_query': search_query  # 当前搜索关键词(用于模板回显)
    }
    return render(request, 'services/service_list.html', context)
1.2.2 模板层:渲染分页导航

分页导航需支持页码跳转,并保留筛选条件(如分类、搜索关键词):

<!-- templates/services/service_list.html -->
{% extends "base.html" %}
{% load static %}

{% block content %}
<div class="container my-5">
    <!-- 筛选表单(省略,与前几课保持一致) -->

    <!-- 服务列表网格 -->
    <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
        {% for service in services %}
            <!-- 服务卡片组件(复用前几课的service_card.html) -->
            {% include 'services/partials/service_card.html' %}
        {% empty %}
            <div class="col-12">
                <div class="alert alert-info">没有找到匹配的服务</div>
            </div>
        {% endfor %}
    </div>

    <!-- 分页导航(当总页数>1时显示) -->
    {% if services.paginator.num_pages > 1 %}
    <nav class="mt-5">
        <ul class="pagination justify-content-center">
            <!-- 首页和上一页 -->
            {% if services.has_previous %}
            <li class="page-item">
                <a class="page-link" 
                   href="?page=1{% if category_filter %}&category={
    
    { category_filter }}{% endif %}{% if search_query %}&q={
    
    { search_query }}{% endif %}">
                    首页
                </a>
            </li>
            <li class="page-item">
                <a class="page-link" 
                   href="?page={
    
    { services.previous_page_number }}{% if category_filter %}&category={
    
    { category_filter }}{% endif %}{% if search_query %}&q={
    
    { search_query }}{% endif %}">
                    &laquo; 上一页
                </a>
            </li>
            {% endif %}

            <!-- 页码列表(只显示当前页附近3页,避免页码过多) -->
            {% for num in services.paginator.page_range %}
                {% if num == services.number %}
                <!-- 当前页 -->
                <li class="page-item active">
                    <span class="page-link">{
  
  { num }}</span>
                </li>
                {% elif num > services.number|add:'-3' and num < services.number|add:'3' %}
                <!-- 当前页前后3页 -->
                <li class="page-item">
                    <a class="page-link" 
                       href="?page={
    
    { num }}{% if category_filter %}&category={
    
    { category_filter }}{% endif %}{% if search_query %}&q={
    
    { search_query }}{% endif %}">
                        {
  
  { num }}
                    </a>
                </li>
                {% endif %}
            {% endfor %}

            <!-- 下一页和末页 -->
            {% if services.has_next %}
            <li class="page-item"></
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RonaldoL9

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值