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

求助:基于Django实现社交网站无限滚动分页的方法

实现Django无限滚动分页的解决方案

一、后端视图调整

修改views.py中的posts_of_following_profiles视图,让它能区分普通请求和AJAX请求,AJAX请求时仅返回帖子内容片段,而非完整页面:

from django.http import HttpResponse
from django.shortcuts import render
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from itertools import chain
from django.contrib.auth.decorators import login_required

@login_required
def posts_of_following_profiles(request):
    profile = Profile.objects.get(user=request.user)
    users = [user for user in profile.following.all()]
    posts = []
    qs = None
    for u in users:
        p = Profile.objects.get(user=u)
        p_posts = p.user.post_set.all()
        posts.append(p_posts)
    my_posts = profile.profile_posts()
    posts.append(my_posts)
    if len(posts) > 0:
        qs = sorted(chain(*posts), reverse=True, key=lambda obj: obj.date_posted)

    paginator = Paginator(qs, 6)
    page = request.GET.get('page')
    try:
        posts_list = paginator.page(page)
    except PageNotAnInteger:
        posts_list = paginator.page(1)
    except EmptyPage:
        # AJAX请求且页码超出范围时返回空内容
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return HttpResponse('')
        posts_list = paginator.page(paginator.num_pages)

    # 判断是否为AJAX请求
    if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        # 仅返回帖子内容片段
        return render(request, 'blog/posts_fragment.html', {'posts': posts_list})
    
    return render(request, 'blog/feeds.html', {'profile': profile, 'posts': posts_list})

二、创建帖子内容片段文件

新建blog/posts_fragment.html,只保留渲染单个帖子的代码(需对应你原feed.html中的帖子结构):

{% for post in posts %}
    <!-- 替换为你实际的帖子渲染代码 -->
    <div class="post-item mb-4">
        <h4>{{ post.title }}</h4>
        <p>{{ post.content|truncatewords:30 }}</p>
        <span class="text-muted">{{ post.date_posted|date:"F d, Y" }}</span>
    </div>
{% endfor %}

三、修改feed.html模板

  1. 重构页面结构,给帖子容器加ID,隐藏原分页按钮:
<!-- 帖子列表容器 -->
<div id="posts-container">
    {% include 'blog/posts_fragment.html' %}
</div>

<!-- 加载提示,初始隐藏 -->
<div id="loading" class="text-center py-3" style="display: none;">
    <p>正在加载更多帖子...</p>
</div>

<!-- 注释掉原分页按钮 -->
{% comment %}
{% if posts.has_other_pages %}
  ... 原分页代码 ...
{% endif %}
{% endcomment %}
  1. 添加JavaScript实现滚动监听与AJAX加载:
<script>
let currentPage = 2;
let isLoading = false;

// 监听滚动事件
window.addEventListener('scroll', () => {
    // 距离页面底部100px时触发加载
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 100 && !isLoading) {
        loadMorePosts();
    }
});

function loadMorePosts() {
    isLoading = true;
    document.getElementById('loading').style.display = 'block';

    const xhr = new XMLHttpRequest();
    xhr.open('GET', `?page=${currentPage}`, true);
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

    xhr.onload = function() {
        if (xhr.status === 200) {
            const response = xhr.responseText;
            if (response) {
                // 将新帖子追加到容器末尾
                document.getElementById('posts-container').insertAdjacentHTML('beforeend', response);
                currentPage++;
            } else {
                // 无更多内容,移除滚动监听
                window.removeEventListener('scroll', arguments.callee);
                document.getElementById('loading').textContent = '已加载全部帖子';
            }
        }
        isLoading = false;
        document.getElementById('loading').style.display = 'none';
    };

    xhr.onerror = function() {
        console.error('加载失败,请稍后重试');
        isLoading = false;
        document.getElementById('loading').style.display = 'none';
    };

    xhr.send();
}
</script>

四、关键注意事项

  • 确保posts_fragment.html中的代码和原feed.html里的帖子渲染逻辑完全一致,避免样式或内容错乱。
  • isLoading变量用于防止滚动时重复触发加载请求。
  • 滚动触发的阈值(document.body.offsetHeight - 100)可根据需求调整,提前触发能提升用户体验。
  • 若需要保留手动加载选项,可添加一个"加载更多"按钮,点击时调用loadMorePosts()函数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:47:13