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

Django自动分页出现重复帖子问题的解决方法

Django自动分页首屏帖子重复问题修复

问题现象

home.html模板通过{% for post in post_lists %}循环渲染首屏5条已发布帖子,但自动分页加载时,home_list.html模板会重复加载这5条帖子。分页功能本身可正常加载所有后续帖子,仅首屏内容重复。


相关代码

home.html

{% for post in post_lists %}
<div class="post_content" id="post_content">
<!----帖子展示代码---->
</div>
{% endfor %}
<div id="pagination-loader" class="pagination_pages" data-page="1"></div>
</div>
<script>
$(document).ready(function(){
    var loadedPage = 1; // 记录已加载的页码

    // 加载下一页帖子的函数
    function loadNextPage() {
        // 发起AJAX请求
        var nextPageUrl = '/load-posts/?page=' + loadedPage;
        console.log("下一页URL:", nextPageUrl);

        $.ajax({
            url: nextPageUrl,
            type: 'GET',
            dataType: 'json',
            success: function(response) {
                console.log("服务器响应:", response);

                // 检查响应中是否有帖子数据
                if (response.posts) {
                    // 将帖子HTML追加到容器末尾
                    $('#post_contenter').append(response.html_posts);

                    // 检查是否还有下一页
                    if (response.next_page_url) {
                        // 递增已加载页码
                        loadedPage++;
                    } else {
                        // 没有下一页则隐藏加载指示器
                        $('#pagination-loader').hide();
                    }
                } else {
                    // 无帖子数据时输出错误
                    console.error('加载帖子失败:响应中缺少帖子数据');
                }
            },
            error: function(jqXHR, textStatus, errorThrown) {
                // 处理请求错误
                console.error('加载帖子失败:', textStatus, errorThrown);
            }
        });
    }

    // 页面滚动事件处理
    $(window).on('scroll', function() {
        // 获取当前滚动位置
        var scrollPosition = $(window).scrollTop();
        // 获取浏览器窗口高度
        var windowHeight = $(window).height();
        // 获取整个文档高度
        var documentHeight = $(document).height();
        
        // 用户滚动到页面底部时
        if (scrollPosition + windowHeight >= documentHeight) {
            // 加载指示器可见时,加载下一页
            if ($('#pagination-loader').is(':visible')) {
                loadNextPage();
            }
        }
    });

    // 页面加载时检查是否需要加载第一页
    if($(window).scrollTop() + $(window).height() == $(document).height()) {
        loadNextPage();
    }
});
</script>

home_list.html

{% if posts %}
    <div class="post-list">
        {% for post in posts %}
<div class="post_content" id="post_content">
<!----帖子展示代码---->
</div>
</div>
       {% endfor %}
{% endif %}

views.py

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.http import JsonResponse
from django.template.loader import render_to_string
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from .models import PostForm, Userpublication, Subscription

@login_required
def create_post(request):
    form = PostForm(request.POST or None)

    if request.method == 'POST':
        if form.is_valid():
            post = form.save(commit=False)
            post.author = request.user
            post.save()
            return redirect('home')

    # 获取当前用户关注的用户ID列表
    subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)

    # 获取关注用户的所有帖子
    subscribed_posts = Userpublication.objects.filter(author__in=subscribed_user_ids)

    # 获取当前用户自己的帖子
    own_posts = Userpublication.objects.filter(author=request.user)

    # 合并帖子列表并按创建时间倒序去重
    all_posts = (subscribed_posts | own_posts).order_by('-time_create').distinct()

    # 处理分页
    page_number = request.GET.get('page', 1)
    paginator = Paginator(all_posts, 5)  # 每页5条帖子

    try:
        page_posts = paginator.page(page_number)
    except PageNotAnInteger:
        page_posts = paginator.page(1)
    except EmptyPage:
        page_posts = paginator.page(paginator.num_pages)

    context = {'form': form, 'post_lists': page_posts, 'title': 'Twippie | 动态', 'page_number': page_number}
    return render(request, 'twippie/home.html', context)

@login_required
def load_posts(request):
    # 从请求中获取页码,默认第1页
    page_number = request.GET.get('page', 1)
    
    # 获取当前用户关注的用户ID列表
    subscribed_user_ids = Subscription.objects.filter(subscriber=request.user).values_list('target_user', flat=True)
    
    # 获取关注用户或自己的所有帖子
    all_posts = Userpublication.objects.filter(Q(author__in=subscribed_user_ids) | Q(author=request.user)).order_by('-time_create').distinct()
    
    # 创建分页器
    paginator = Paginator(all_posts, 5)  # 每页5条帖子

    try:
        # 获取当前页的帖子
        current_page_posts = paginator.page(page_number)
    except PageNotAnInteger:
        # 页码非整数时返回第1页
        current_page_posts = paginator.page(1)
    except EmptyPage:
        # 页码超出范围时返回空响应
        return JsonResponse({'posts': [], 'next_page_url': None})
    
    # 渲染帖子HTML
    html_posts = render_to_string('twippie/home_list.html', {'posts': current_page_posts})
    
    # 构造帖子列表用于JSON返回
    posts_list = [{'id': post.id, 'content': post.content} for post in current_page_posts]
    
    # 获取下一页URL(如果存在)
    next_page_url = None
    if current_page_posts.has_next():
        next_page_url = reverse('load_posts') + f'?page={current_page_posts.next_page_number()}'
    
    # 返回JSON响应
    return JsonResponse({'posts': posts_list, 'html_posts': html_posts, 'next_page_url': next_page_url})

修复步骤

1. 调整前端初始页码与加载逻辑

问题核心是首屏已加载第1页,但AJAX请求仍从第1页开始,导致重复。修改前端代码:

  • 将loadedPage初始值改为2,因为首屏已经渲染了第1页内容,AJAX应该从第2页开始请求。
  • 移除页面加载时自动调用loadNextPage()的逻辑,避免页面刚加载就重复请求第1页。

修改后的前端脚本关键部分:

$(document).ready(function(){
    var loadedPage = 2; // 首屏已加载第1页,AJAX从第2页开始

    // ... 其他函数保持不变

    // 移除这段自动加载第一页的代码
    // if($(window).scrollTop() + $(window).height() == $(document).height()) {
    //     loadNextPage();
    // }
});

2. 修正模板中的重复ID问题

HTML中多个元素使用了相同的id="post_content",这会导致DOM选择器异常,建议改为仅使用类名:

<!-- home.html -->
<div class="post_content">
<!-- home_list.html -->
<div class="post_content">

3. 验证后端分页逻辑一致性

确保create_post和load_posts视图中的帖子查询逻辑完全一致:

  • 两个视图中all_posts的过滤条件、排序方式、去重逻辑必须相同,否则会导致分页数据错位。当前代码已经满足,但需后续维护时注意保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 02:53:11