You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django博客网站分页功能失效,附前后端代码寻求解决方案

Django博客分页功能实现修正方案

现有代码问题汇总

  • blogs_pagination接口存在语法错误:序列化行误写为blogs.serialize(),blogs是分页页对象而非单条博客实例,会直接抛出异常
  • home视图首次加载返回全量博客数据,未携带分页状态,模板渲染时没有初始分页信息
  • 前端模板只有分页HTML骨架,没有绑定点击事件、请求分页接口、更新页面内容的逻辑
  • 分页接口未处理非法页码(如超过最大页、非数字页码),容易触发404或报错

修正步骤

1. 修正后端视图代码

from django.core.paginator import Paginator

def home(request):
    # 首次加载返回第一页分页数据,兼容非JS场景
    all_blogs = BlogModel.objects.all().order_by("-created_at")
    paginator = Paginator(all_blogs, 3)
    page_number = request.GET.get('page', 1)
    page_obj = paginator.get_page(page_number)
    
    context = {
        "blogs": page_obj,
        "services": Service.objects.all(),
        "works": RecentWork.objects.all(),
        "has_next": page_obj.has_next(),
        "has_previous": page_obj.has_previous(),
        "total_pages": paginator.num_pages,
        "current_page": page_obj.number
    }
    return render(request,"home.html", context)

def blogs_pagination(request, page_number=1):
    blogs_query = BlogModel.objects.all().order_by("-created_at")
    paginator = Paginator(blogs_query, 3)
    # get_page自动处理非法页码,自动返回有效页
    current_page = paginator.get_page(page_number)

    return JsonResponse({
        # 修正序列化错误,遍历单条博客序列化
        "blogs": [blog.serialize() for blog in current_page],
        "totalPages": paginator.num_pages,
        "hasNext": current_page.has_next(),
        "hasPrevious": current_page.has_previous(),
        "currentPage": current_page.number
    })

2. 配置分页路由

在你应用的urls.py中新增分页接口路由:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('blogs/page/<int:page_number>/', views.blogs_pagination, name='blogs_pagination'),
]

3. 补全BlogModel序列化方法

确保你的BlogModel模型已经定义了serialize方法,返回前端需要的字段:

from django.db import models

class BlogModel(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    # 其他字段自行补充

    def serialize(self):
        return {
            "id": self.id,
            "title": self.title,
            "content": self.content,
            "created_at": self.created_at.strftime("%Y-%m-%d %H:%M:%S")
        }

4. 修正前端模板代码

如果需要异步无刷新分页,替换你的home.html相关代码如下:

<!-- 博客列表容器 -->
<div id="blog-list">
  {% for blog in blogs %}
  <div class="blog-item">
    <h3>{{ blog.title }}</h3>
    <p>{{ blog.content|truncatechars:200 }}</p>
    <span>发布时间:{{ blog.created_at|date:"Y-m-d H:i" }}</span>
  </div>
  {% endfor %}
</div>

<!-- 分页导航 -->
<nav aria-label="Page navigation">
  <ul id='pagination' class="pagination justify-content-end container-fluid">
    <li id='hasPrevious' class="page-item {% if not has_previous %}disabled{% endif %}">
      <a class="page-link" href="javascript:;" aria-label="上一页" data-page="{{ current_page|add:-1 }}">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
    <!-- 动态渲染页码按钮 -->
    {% for num in "x"|rjust:total_pages %}
    <li class="page-item {% if forloop.counter == current_page %}active{% endif %}">
      <a class="page-link" href="javascript:;" data-page="{{ forloop.counter }}">{{ forloop.counter }}</a>
    </li>
    {% endfor %}
    <li id='hasNext' class="page-item {% if not has_next %}disabled{% endif %}">
      <a class="page-link" href="javascript:;" aria-label="下一页" data-page="{{ current_page|add:1 }}">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

<!-- 分页交互逻辑 -->
<script>
let currentPage = {{ current_page }};
// 拼接分页接口基础地址
const basePaginationUrl = "{% url 'blogs_pagination' page_number=0 %}".slice(0, -1);

// 绑定所有分页按钮点击事件
document.querySelectorAll(".page-link").forEach(link => {
  link.addEventListener("click", function(e) {
    e.preventDefault();
    const targetPage = parseInt(this.dataset.page);
    if (targetPage < 1 || targetPage > {{ total_pages }}) return;

    // 请求分页数据
    fetch(`${basePaginationUrl}${targetPage}/`)
      .then(res => res.json())
      .then(data => {
        // 替换博客列表内容
        const blogList = document.getElementById("blog-list");
        blogList.innerHTML = "";
        data.blogs.forEach(blog => {
          const item = document.createElement("div");
          item.className = "blog-item";
          item.innerHTML = `
            <h3>${blog.title}</h3>
            <p>${blog.content.substring(0, 200)}</p>
            <span>发布时间:${blog.created_at}</span>
          `;
          blogList.appendChild(item);
        });
        // 更新分页按钮状态
        document.getElementById("hasPrevious").classList.toggle("disabled", !data.hasPrevious);
        document.getElementById("hasNext").classList.toggle("disabled", !data.hasNext);
        // 更新页码激活状态
        document.querySelectorAll(".page-item").forEach(item => {
          const page = parseInt(item.querySelector(".page-link")?.dataset.page);
          if (page) item.classList.toggle("active", page === data.currentPage);
        });
        // 更新上下页按钮的目标页码
        document.querySelector("#hasPrevious .page-link").dataset.page = data.currentPage - 1;
        document.querySelector("#hasNext .page-link").dataset.page = data.currentPage + 1;
        currentPage = data.currentPage;
      });
  });
});
</script>

如果你不需要异步刷新,也可以用更简单的服务端渲染方案,不用写任何JS,只需要把分页按钮的href改为/?page=目标页码即可。

内容的提问来源于stack exchange,提问作者daya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:51:03