I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
Hey guys.I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me.
Hey guys.I have a django project. In this project, I made a search box with ajax, but the same data is coming more than once. Is the problem in ajax? or is the problem in django? I am not sure. Please help me. my html code
enter code here
<form method="POST">
{% csrf_token %}
<input type="text" name="text" placeholder="Ne Aramıştınız?" id="searchInputChange">
<button>Ara <i ></i></button>
</form>
<div >
<div id="null-search-dietitians">
Aradığınız sonuç bulunamadı. Lütfen aradığınız kelimeyi gözden geçiriniz.
</div>
{% for posts in posts%}
<div data-firs-load="true">
<div >
<img src="{{posts.photo}}" alt="">
<a onclick="openVideoModal(event)" data-iframe-link="{{posts.video}}">
<i ></i>
<br>
İzle
</a>
</div>
<div >
<div >
<div >
<div >
{{posts.isim}} {{posts.soyisim}}
</div>
<div >
{{posts.uzmanlik}}
</div>
<div >
<i ></i>
<i ></i>
<i ></i>
<i ></i>
<i ></i>
</div>
</div>
<div >
<div >
<div >
Yorum Sayısı
</div>
<div >
{{posts.yorum_sayi}}
</div>
</div>
<div >
<div >
Danışan Sayısı
</div>
<div >
{{posts.danisan_sayi}}
</div>
</div>
</div>
</div>
<div >
<div >
<div>Uzmanlıklar :</div>
<div> {{posts.hizmetler}} </div>
</div>
<div >
<div >
<div >
<a href="{% url 'diyetisyen' slug=posts.slug %}">Profili İncele</a>
</div>
<div >
<a href="{%url 'randevu' slug=posts.slug %}">Randevu Al</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
my ajax code
enter code here
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();
if(searchValue.length>=3){
if(searchValue === ''){
dietitansFirstLoad.forEach(element=>{
element.style.display = 'flex'
})
pagination.style.display = 'flex'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
nullDietitans.style.display = 'none'
}
else{
fetch("/getDietitians",{
body: JSON.stringify({searchText:searchValue}),
method: "POST",
})
.then((res)=>res.json())
.then((data)=>{
console.log(data)
dietitansFirstLoad.forEach(element=>{
element.style.display = 'none'
})
pagination.style.display = 'none'
if(data.length > 0){
$.each(data,(index,value)=>{
$.each(data,(index1,value1)=>{
$(".all-dietitans-content").append(''
'<div data-search="true"><div >'
'<img src="' value1.photo '" alt="">'
'<a onclick="openVideoModal(event)" data-iframe-link="' value1.video '">'
'<i ></i><br>İzle</a></div><div ><div ><div ><div >'
value1.isim ' ' value1.soyisim
'</div><div >'
value1.uzmanlik
'</div><div ><i ></i><i ></i><i ></i><i ></i><i ></i></div></div><div ><div ><div >Yorum Sayısı</div><div >'
value1.yorum_sayi
'</div></div><div ><div >Danışan Sayısı</div><div >'
value1.danisan_sayi
'</div></div></div></div><div ><div ><div>Uzmanlıklar :</div><div>'
value1.hizmetler
'</div></div><div ><div ><div >'
'<a href="/diyetisyen/' value1.slug '">Profili İncele</a>'
'</div><div >'
'<a href="/randevu/' value1.slug '">Randevu Al</a>'
'</div></div></div></div></div></div>')
})
})
}
else{
nullDietitans.style.display = 'block'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
}
});
}
}
else{
dietitansFirstLoad.forEach(element=>{
element.style.display = 'flex'
})
pagination.style.display = 'flex'
document.querySelectorAll('.all-dietitans-content > .dietitans[data-search="true"]').forEach(element=>{
element.remove()
})
nullDietitans.style.display = 'none'
}
})
CodePudding user response:
It's because you're doing multiple queries and |
to combine them, that's why it is returning duplicates.
instead of doing list = query1 | query2
use Q objects
@csrf_exempt
def getDietitians(request):
from django.http import JsonResponse
if request.method == "POST":
search_str=json.loads(request.body).get('searchText')
from django.db.models import Q
expenses = diyetisyenler.objects.filter(
Q(isim__istartswith=search_str) |
Q(soyisim__istartswith=search_str) |
Q(uzmanlik__icontains=search_str) |
Q(hizmetler__icontains=search_str)
)
data=expenses.values()
return JsonResponse(list(data),safe=False)
Edit
Answer: JS issue, the item list should be removed on every search
And I've worked with similar applications, so I'll drop some ideas I've done :)
Delay
It might be a good idea to add a delay, so it's not posting for every single keystroke.
Example: Searching for abc
- Searches for
a
- Searches for
ab
- Searches for
abc
With a delay, I've got it at 400 milliseconds, more than likely I'll just search once for abc
- unless the person types super slow
View
// global unfortunately :(
var interval = 0;
var counter = 0;
$('#inputfield').on('input', function(e) {
if (!$(this).is(':focus')){ return; }
var search = $(this).val().trim();
if (search){
clearInterval(interval);
interval = setInterval(function() {
counter ;
if (counter >= 4){ // 4 * 100 => 400 millisecond delay
clearInterval(interval);
counter = 0;
searchfunction(this);
};
}, 100);
}else{
// Could clear results here
};
};
Ping-Pong Timestamp
Larger Queries will sometimes overwrite smaller ones
Example:
- Send search for
a
(query1) [takes 15 seconds] - Send search for
absolutely
(query2) [takes 2 seconds] - query2 returns
- query1 returns, overwriting query2 (not good)
Solution
- On Javascript POST, send
'time': Date.now(),
along with search - In python return
time
with the results{'list':list(data), 'time':request.POST.get('time')}
- On Javascript POST return, check if return is newer than rendered
- If newer: updated results & it's time (time would be any way to store when you sent the search for the what's rendered)
- If older: just skip the render