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

如何通过Ajax在Django中无刷新重新加载history.items()循环?

实现Django模板局部刷新(Ajax更新循环内容)

1. 调整模板结构,分离可刷新区域

先把需要动态更新的循环部分包裹在一个唯一ID的容器中,同时修复原模板中重复ID的问题(HTML规范要求ID唯一):

<div class="container" id="cd">
    <div class="row">
        <div class="col-2">
            <label for="serialno" class="h4 text-center mx-4"> S.No </label>
        </div>
        <div class="col-3">
            <label for="billno" class="h4 text-center"> Bill No</label>
        </div>
        <div class="col-5">
            <label for="Items" class="h4 text-center"> Items</label>
        </div>
        <div class="col-2">
            <label for="total" class="h4 text-center"> Total</label>
        </div>
        <hr>
    </div>
    <!-- 新增专属容器,用于后续替换动态内容 -->
    <div id="history-container">
        {% for b,d in history.items %}
        <!-- 将重复的id改为class,避免HTML无效 -->
        <div class="row refresh-row">
            <div class="col-2 py-2">
                <label class="h6">{{forloop.counter}}. | {{b.created_at}}</label>
            </div>
            <div class="col-3 py-2">
                <label class="h5">{{b}}</label>
            </div>
            <div class="col-5 py-2">
                {% for i in d %}
                <label class="h6">{{i.itemname}} x {{i.qty}} {{i.subtotal}}</label><br>
                {% endfor %}
            </div>
            <div class="col-2 py-2">
                <span class="h6">&#8377;</span>
                <label class="h6">{{b.grandtotal}}</label>
            </div>
        </div>
        {% endfor %}
    </div>
</div>

2. 修改Django视图,支持Ajax返回局部HTML

处理history路由的视图需要区分普通请求和Ajax请求:普通请求返回完整页面,Ajax请求只返回循环部分的HTML片段。

首先创建一个模板片段history_fragment.html,仅保留循环内容:

{% for b,d in history.items %}
<div class="row refresh-row">
    <div class="col-2 py-2">
        <label class="h6">{{forloop.counter}}. | {{b.created_at}}</label>
    </div>
    <div class="col-3 py-2">
        <label class="h5">{{b}}</label>
    </div>
    <div class="col-5 py-2">
        {% for i in d %}
        <label class="h6">{{i.itemname}} x {{i.qty}} {{i.subtotal}}</label><br>
        {% endfor %}
    </div>
    <div class="col-2 py-2">
        <span class="h6">&#8377;</span>
        <label class="h6">{{b.grandtotal}}</label>
    </div>
</div>
{% endfor %}

然后修改视图函数:

from django.shortcuts import render

def history_view(request):
    if request.method == 'POST':
        # 获取前端传入的参数
        tb1_value = request.POST.get('tb1')
        # 这里替换成你的业务逻辑:根据tb1_value获取更新后的history数据
        updated_history = get_updated_history_data(tb1_value)
        
        # 判断是否为Ajax请求(Django 3.1+需手动检查请求头)
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            # 返回渲染后的模板片段
            return render(request, 'history_fragment.html', {'history': updated_history})
    
    # 非POST请求或普通浏览器请求,返回完整页面
    initial_history = get_initial_history_data()
    return render(request, 'history_page.html', {'history': initial_history})

3. 更新Ajax代码,处理返回内容并替换容器

修改Ajax的success回调,把后端返回的HTML片段替换到指定容器中:

<script>
    $(document).on('change','#myform',function(e){
        e.preventDefault();
        $.ajax({
            type:'POST',
            url:"{% url 'history' %}",
            data:{
                tb1:$('#cal').val(),
                csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
            },
            dataType: 'html', // 指定返回类型为HTML
            success:function(response){
                // 替换容器内的旧内容
                $('#history-container').html(response);
            },
            error:function(xhr, status, error){
                // 可选:处理请求失败的情况
                console.error('请求失败:', error);
            }
        });
    });
</script>

关键注意事项

  • 禁止重复ID:原模板中循环生成的id="refresh"违反HTML规范,必须改为class或动态ID。
  • Ajax请求判断:通过X-Requested-With请求头识别Ajax请求,确保视图返回正确内容。
  • 模板复用:使用模板片段避免重复编写循环代码,同时减少Ajax传输的数据量。

内容的提问来源于stack exchange,提问作者Anwar Mydheen K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:45:32