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
相关产品推荐
相关产品推荐

