You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Fetch实现帖子列表局部刷新加载更多的问题求助

使用Fetch实现帖子列表局部刷新加载更多的问题求助

问题分析

看了你的代码,主要有两个关键错误导致返回了整个页面而不是局部片段:

  1. AJAX请求头判断拼写错误:视图里写的是request.headers.get("x-request-with"),但实际请求里的头是x-requested-with(多了个ed),导致判断不成立,每次都返回了包含父模板头部的完整posts-list.html页面。
  2. JS里的DOM选择器错误:原JS代码里的选择器是.post,但你的帖子容器类名是.posts,这会导致无法找到正确的DOM元素追加内容。

另外还有个小细节:模板里的标签分隔符逻辑写反了,会导致最后一个标签后出现多余逗号。


修正方案

1. 修复视图函数(views.py)

修正AJAX请求头的拼写,确保能正确识别异步请求:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render, get_object_or_404
from .models import Post, Tag

def post_list(request, tag_slug=None):
    if tag_slug:
        tag = get_object_or_404(Tag, slug=tag_slug)
        posts = Post.objects.filter(tags__in=[tag])
    else:
        posts = Post.objects.all()
        tag = None

    page = request.GET.get('page')
    paginator = Paginator(posts, 1)
    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = []

    # 修正:请求头名称为x-requested-with
    if request.headers.get("x-requested-with") == "XMLHttpRequest":
        return render(request, "social/fetch-post.html", {"posts": posts})
    
    context = {'posts': posts, 'tag': tag}
    return render(request, "social/posts-list.html", context)

2. 修复JS选择器(posts-list.html)

把错误的选择器改成正确的.posts

function loadMore(){
    var url = '{% if tag_slug %}{% url "post_list_by_tag" tag.slug %}{% else %}{% url "social:post_list" %}{% endif %}'+'?page='+page;
    fetch(url, {
      method: 'GET',
      headers: {
        'content-type': 'text/html',
        'x-requested-with': 'XMLHttpRequest'
      },
    }).then(function(response){
      return response.text();
    }).then(function(html){
      // 修正:选择器从.post改为.posts
      document.querySelector(".posts").insertAdjacentHTML("beforeend",html);
      page++;
    })
}

3. 优化模板标签分隔符(fetch-post.html)

避免最后一个标签后出现多余逗号:

{% for post in posts %}
<div class="posts-item">
  {{post.description|linebreaks|truncatewords:20}} Published at {{post.created}} by {{post.author}} <br>
  {% for tag in post.tag.all %}
  <a href="{% url 'social:post_list_by_tag' tag.slug %}">{{tag.name}}</a>
  <!-- 修正:非最后一个标签才添加逗号 -->
  {% if not forloop.last %}, {% endif %}
  {% endfor %}
  <a href="{% url 'social:post_detail' post.pk %}">post details</a>
  <hr><br>
</div>
{% endfor %}

额外优化建议

  • 处理无更多数据的情况:当请求的页码超出范围时,JS可以判断返回的HTML为空,自动隐藏“加载更多”按钮,避免无效点击。
  • 添加加载状态:点击按钮后禁用按钮并显示“加载中”提示,请求完成后再恢复,提升用户体验。
  • 复用模板片段:主页面posts-list.html里的帖子循环代码可以用{% include "social/fetch-post.html" %}代替,减少重复代码,方便后续维护。

修改完成后,点击“加载更多”就只会请求并追加局部帖子片段,不会再渲染整个页面了。

火山引擎 最新活动