如何基于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
相关产品推荐
相关产品推荐

