Django+Ajax搜索框返回重复数据问题排查求助
Django Ajax搜索结果重复问题修复
问题根源
搜索结果重复显示的核心原因是Ajax代码中嵌套了两层$.each(data)循环:外层遍历搜索结果数组时,内层又完整遍历一遍数组,导致每个结果被重复添加N次(N等于结果数组的长度)。
修复步骤
- 移除嵌套循环:只保留一层
$.each(data)循环,直接使用外层循环的变量渲染内容。 - 清空历史结果:发起新搜索前,先删除所有
data-search="true"的元素,避免多次搜索结果叠加。 - 添加CSRF令牌:Django的POST请求必须携带CSRF令牌,否则会触发403权限错误,需在fetch请求的headers中补充该令牌。
修正后的完整Ajax代码
const nullDietitans = document.getElementById('null-search-dietitians') const pagination = document.querySelector('.pagination') const dietitiansContent = document.querySelector(".all-dietitans-content") const dietitansFirstLoad = document.querySelectorAll('.all-dietitans-content > .dietitans[data-firs-load="true"]') const searchInputChange = document.querySelector("#searchInputChange"); searchInputChange.addEventListener('input', (e) => { nullDietitans.style.display = 'none' let searchValue = e.target.value.trim(); // 清空之前的搜索结果 document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element => { element.remove() }) if (searchValue.length >= 3) { dietitansFirstLoad.forEach(element => { element.style.display = 'none' }) pagination.style.display = 'none' fetch("/getDietitians", { body: JSON.stringify({ searchText: searchValue }), method: "POST", headers: { 'Content-Type': 'application/json', 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value } }) .then((res) => res.json()) .then((data) => { console.log(data) if (data.length > 0) { // 仅保留一层循环遍历结果 $.each(data, (index, value) => { $(".all-dietitans-content").append('' + '<div class="dietitans" data-search="true"><div class="left-image">' + '<img src="' + value.photo + '" alt="">' + '<a onclick="openVideoModal(event)" data-iframe-link="' + value.video + '">' + '<i class="far fa-play-circle"></i><br>İzle</a></div><div class="right-content"><div class="dietitans-infos"><div class="left"><div class="name">' + value.isim + ' ' + value.soyisim + '</div><div class="degree">' + value.uzmanlik + '</div><div class="stars"><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i><i class="fas fa-star"></i></div></div><div class="right"><div class="item"><div class="title">Yorum Sayısı</div><div class="number">' + value.yorum_sayi + '</div></div><div class="item"><div class="title">Danışan Sayısı</div><div class="number">' + value.danisan_sayi + '</div></div></div></div><div class="dietitans-services-content"><div class="dietitans-description"><div>Uzmanlıklar :</div><div>' + value.hizmetler + '</div></div><div class="buttons-and-text"><div class="buttons"><div class="button-style-2">' + '<a href="/diyetisyen/' + value.slug + '">Profili İncele</a>' + '</div><div class="button-style-1">' + '<a href="/randevu/' + value.slug + '">Randevu Al</a>' + '</div></div></div></div></div></div>') }) } else { nullDietitans.style.display = 'block' } }); } else { dietitansFirstLoad.forEach(element => { element.style.display = 'flex' }) pagination.style.display = 'flex' nullDietitans.style.display = 'none' } })
额外优化说明
- 原代码中
searchValue === ''的判断逻辑永远不会触发(外层已判断searchValue.length >=3),已直接删除以简化代码。 - 将清空历史结果的操作移到事件处理开头,确保每次搜索都基于全新的结果容器。
内容的提问来源于stack exchange,提问作者Burak Demirer
相关产品推荐
相关产品推荐

