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

如何基于Django ListView搭配搜索输入框实现前端列表动态过滤

实现方案(最简最优,纯ListView实现)

核心逻辑:复用ListView原生get_queryset过滤逻辑,通过GET请求传递搜索参数,AJAX局部更新页面内容,无需额外自定义路由或复杂逻辑。

1. 视图修改

class ManageUserView(SuperUserRequired, ListView):
    model = User
    template_name = 'webapp/klant/beheerklant.html'

    def get_queryset(self):
        # 从GET参数取搜索关键词,无关键词时默认返回空字符串
        query = self.request.GET.get('q', '')
        # 基础查询集:排除超管
        qs = super().get_queryset().exclude(is_superuser=True)
        # 有搜索词时按规则过滤
        if query:
            qs = qs.filter(contactNaam__icontains=query)
        return qs

    def get(self, request, *args, **kwargs):
        # 先执行原生get逻辑拿到上下文
        response = super().get(request, *args, **kwargs)
        # 判断是AJAX请求的话,只返回表格行的HTML片段
        if request.headers.get('x-requested-with') == 'XMLHttpRequest':
            from django.template.loader import render_to_string
            from django.http import JsonResponse
            context = self.get_context_data()
            html = render_to_string('webapp/klant/partials/klant_rows.html', context, request=request)
            return JsonResponse({'html': html})
        # 普通请求返回完整页面
        return response

补充说明:你需要新建一个片段模板webapp/klant/partials/klant_rows.html,把原来模板里for循环生成的<tr>代码全放进去,减少重复代码


2. 模板修改

原模板调整,给tbody加ID,抽离行代码:

<div class="card mt-3">
    <div class="card-body">
    <form action="" method="get">
        <input data-url="{% url 'klantbeheer' %}" class="zoekklanten" name="q" type="text" placeholder="Zoek op contactnaam...">
    </form>
    {% if object_list %}
            <div class="single-table">
                <div class="table-responsive">
                    <table class="table text-center">
                        <thead class="text-uppercase bg-dark">
                            <tr class="text-white">
                                <th scope="col">Bedrijfsnaam</th>
                                <th scope="col">Contactnaam</th>
                                <th scope="col">Locatie</th>
                                <th scope="col">Actie</th>
                            </tr>
                        </thead>
                        <tbody id="klant-tbody">
                            <!-- 抽离出来的行代码 放到单独的片段模板里 这里直接include -->
                            {% include 'webapp/klant/partials/klant_rows.html' %}
                        </tbody>
                    </table>
                </div>
            </div>
        {% else %}
        <p>Geen gebruikers gevonden</p>
            <p>
                <a href="{% url 'klantaanmaken' user.id %}" class="btn btn-primary">Maak klant aan</a>
            </p>
        {% endif %}
    </div>
</div>

新建片段模板webapp/klant/partials/klant_rows.html内容:

{% for user in object_list %}
<tr>
    <td>{{ user.bedrijfsNaam }}</td>
    <td>{{ user.contactNaam }}</td>
    <td>{{ user.adres }}</td>
    <td>
        <a href="{% url 'klantupdaten' user.id  %}"><i class="fas fa-edit"></i></a>
        <a href="#" data-url="{% url 'klantverwijderen' user.id %}" class="deletegebruiker" data-bs-toggle="modal" data-bs-target="#dynamic-modal"><i class="fas fa-trash-alt"></i></a>
    </td>
</tr>
{% endfor %}

3. JQuery修改

// 加防抖函数 避免频繁发请求
function debounce(func, wait = 300) {
    let timeout;
    return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    }
}

$('.zoekklanten').on('keyup', debounce(function(){
    var url = $(this).data('url')
    var query = $(this).val();

    $.ajax({
        url:url,
        type:'GET',
        data:{
            'q': query
        },
        success: function(result){
            // 直接替换tbody内容
            $('#klant-tbody').html(result.html);
        },
        error: function(data){
            console.error('搜索失败', data);
        }
    })
}))

方案优势

  • 完全复用ListView原生逻辑,没有额外冗余代码,维护成本低
  • 用GET请求实现搜索,符合REST规范,支持搜索结果页面直接分享
  • 加了防抖优化请求次数,性能更好
  • 禁用JS时表单直接提交也能正常实现搜索功能,兼容性强

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:36:05