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

Django结合HTMX实现无限滚动分页时插入顺序异常问题排查

无限滚动分页排序异常问题排查与解决

我用HTMX实现无限滚动分页,其他功能正常,但新加载的对象排序偶尔出错。比如设置paginate_by = 10时,前10条排序正常,后续加载的10条里有7-8条排序正确,剩下2条本该在表格顶部的却跑到了末尾。

相关代码

Django View代码

class ShippedProductListView(ListView):
    model = models.Product
    context_object_name = "products"
    paginate_by = 10
    ordering = ['-shipment__shipment_date']

    def get_queryset(self):
        queryset = models.Product.objects.filter(status=models.ProductStatus.SENT)
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['total_count'] = self.get_queryset().count()
        return context

主HTML模板

<table>
  <!-- some content here -->
    <tbody>
        {% include "production/shipped_products_table.html" with products=products %}
        <!-- Shipped products table updates with htmx -->
    </tbody>
</table>

子模板 shipped_products_table.html

{% for d in products %}
    {% if forloop.last %}
    <tr
        hx-trigger="revealed"
        hx-get="{% url 'shipped_products_list' %}?page={{ page_obj.number|add:1 }}"
        hx-swap="afterend"
        h
    >
    {% else %}
    <tr>   
    {% endif %}
    <tr>
        <td><a class="link-success" href="{% url 'products_detail' sn=d.serial_number %}">{{ d.serial_number }}</a></td>
        <!-- some more content here -->
    </tr>
{% empty %}
    <h5 class="pt-4">Nothing here yet.</h5>
{% endfor %}

问题原因

  1. 排序字段不唯一:仅用-shipment__shipment_date排序时,若多条记录的shipment_date完全相同,数据库分页无法保证这部分记录的稳定排序,不同页加载时会出现顺序混乱。
  2. 子模板DOM结构错误:存在重复的<tr>标签(先判断生成一个<tr>,又直接写了一个<tr>),还有无用的h属性,这会导致DOM结构异常,干扰HTMX的插入逻辑。

解决步骤

1. 补充唯一排序字段

修改View的ordering属性,添加唯一字段(比如主键id)确保排序稳定:

ordering = ['-shipment__shipment_date', '-id']

即使shipment_date相同,也会按id倒序排列,保证分页时顺序一致。

2. 修复子模板的DOM错误

修正shipped_products_table.html中的重复标签和无效属性:

{% for d in products %}
    <tr {% if forloop.last %}
            hx-trigger="revealed"
            hx-get="{% url 'shipped_products_list' %}?page={{ page_obj.number|add:1 }}"
            hx-swap="afterend"
        {% endif %}>
        <td><a class="link-success" href="{% url 'products_detail' sn=d.serial_number %}">{{ d.serial_number }}</a></td>
        <!-- some more content here -->
    </tr>
{% empty %}
    <h5 class="pt-4">Nothing here yet.</h5>
{% endfor %}
  • 移除重复的<tr>标签,将HTMX属性直接加到循环的<tr>上
  • 删除无用的h属性

3. 验证分页逻辑

确保查询集应用了正确排序,也可以在get_queryset中显式指定排序:

def get_queryset(self):
    queryset = models.Product.objects.filter(status=models.ProductStatus.SENT).order_by('-shipment__shipment_date', '-id')
    return queryset

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 08:32:09